diff options
Diffstat (limited to 'desktop')
681 files changed, 72440 insertions, 0 deletions
diff --git a/desktop/inc/app.hxx b/desktop/inc/app.hxx new file mode 100644 index 000000000000..b950d2583097 --- /dev/null +++ b/desktop/inc/app.hxx @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_APP_HXX_ +#define _DESKTOP_APP_HXX_ + +// stl includes first +#include <map> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <vcl/svapp.hxx> +#include <vcl/timer.hxx> +#include <tools/resmgr.hxx> +#include <unotools/bootstrap.hxx> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/uno/Reference.h> +#include <osl/mutex.hxx> + +using namespace com::sun::star::task; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; + +#define DESKTOP_SAVETASKS_MOD 0x1 +#define DESKTOP_SAVETASKS_UNMOD 0x2 +#define DESKTOP_SAVETASKS_ALL 0x3 + +namespace desktop +{ + +/*-------------------------------------------------------------------- + Description: Application-class + --------------------------------------------------------------------*/ +class CommandLineArgs; +class Lockfile; +class AcceptorMap : public std::map< rtl::OUString, Reference<XInitialization> > {}; +struct ConvertData; +class Desktop : public Application +{ + friend class UserInstall; + + int doShutdown(); + + public: + enum BootstrapError + { + BE_OK, + BE_UNO_SERVICEMANAGER, + BE_UNO_SERVICE_CONFIG_MISSING, + BE_PATHINFO_MISSING, + BE_USERINSTALL_FAILED, + BE_LANGUAGE_MISSING, + BE_USERINSTALL_NOTENOUGHDISKSPACE, + BE_USERINSTALL_NOWRITEACCESS, + BE_OFFICECONFIG_BROKEN + }; + enum BootstrapStatus + { + BS_OK, + BS_TERMINATE + }; + + Desktop(); + ~Desktop(); + virtual int Main( ); + virtual void Init(); + virtual void InitFinished(); + virtual void DeInit(); + virtual sal_Bool QueryExit(); + virtual sal_uInt16 Exception(sal_uInt16 nError); + virtual void SystemSettingsChanging( AllSettings& rSettings, Window* pFrame ); + virtual void AppEvent( const ApplicationEvent& rAppEvent ); + + DECL_LINK( OpenClients_Impl, void* ); + + static void OpenClients(); + static void OpenDefault(); + + DECL_LINK( EnableAcceptors_Impl, void*); + + static void HandleAppEvent( const ApplicationEvent& rAppEvent ); + static ResMgr* GetDesktopResManager(); + static CommandLineArgs& GetCommandLineArgs(); + + void HandleBootstrapErrors( BootstrapError ); + void SetBootstrapError( BootstrapError nError ) + { + if ( m_aBootstrapError == BE_OK ) + m_aBootstrapError = nError; + } + BootstrapError GetBootstrapError() const + { + return m_aBootstrapError; + } + + void SetBootstrapStatus( BootstrapStatus nStatus ) + { + m_aBootstrapStatus = nStatus; + } + BootstrapStatus GetBootstrapStatus() const + { + return m_aBootstrapStatus; + } + + static sal_Bool isCrashReporterEnabled(); + + // first-start (ever) related methods + static sal_Bool CheckExtensionDependencies(); + + static void DoRestartActionsIfNecessary( sal_Bool bQuickStart ); + static void SetRestartState(); + + void SynchronizeExtensionRepositories(); + void SetSplashScreenText( const ::rtl::OUString& rText ); + void SetSplashScreenProgress( sal_Int32 ); + + void CreateProcessServiceFactory(); + + private: + // Bootstrap methods + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > CreateApplicationServiceManager(); + + void RegisterServices( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xSMgr ); + void DeregisterServices(); + + void DestroyApplicationServiceManager( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xSMgr ); + + void CreateTemporaryDirectory(); + void RemoveTemporaryDirectory(); + + sal_Bool InitializeInstallation( const rtl::OUString& rAppFilename ); + sal_Bool InitializeConfiguration(); + void FlushConfiguration(); + static sal_Bool shouldLaunchQuickstart(); + sal_Bool InitializeQuickstartMode( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rSMgr ); + + void HandleBootstrapPathErrors( ::utl::Bootstrap::Status, const ::rtl::OUString& aMsg ); + void StartSetup( const ::rtl::OUString& aParameters ); + + // Get a resource message string securely e.g. if resource cannot be retrieved return aFaultBackMsg + ::rtl::OUString GetMsgString( sal_uInt16 nId, const ::rtl::OUString& aFaultBackMsg ); + + // Create a error message depending on bootstrap failure code and an optional file url + ::rtl::OUString CreateErrorMsgString( utl::Bootstrap::FailureCode nFailureCode, + const ::rtl::OUString& aFileURL ); + + static void PreloadModuleData( const CommandLineArgs& ); + static void PreloadConfigurationData(); + + Reference<XStatusIndicator> m_rSplashScreen; + void OpenSplashScreen(); + void CloseSplashScreen(); + + void EnableOleAutomation(); + DECL_LINK( ImplInitFilterHdl, ConvertData* ); + DECL_LINK( AsyncInitFirstRun, void* ); + /** checks if the office is run the first time + <p>If so, <method>DoFirstRunInitializations</method> is called (asynchronously and delayed) and the + respective flag in the configuration is reset.</p> + */ + void CheckFirstRun( ); + + /// does initializations which are necessary for the first run of the office + void DoFirstRunInitializations(); + + static sal_Bool SaveTasks(); + static sal_Bool _bTasksSaved; + + static void retrieveCrashReporterState(); + static sal_Bool isUIOnSessionShutdownAllowed(); + + // on-demand acceptors + static void createAcceptor(const rtl::OUString& aDescription); + static void enableAcceptors(); + static void destroyAcceptor(const rtl::OUString& aDescription); + + sal_Bool m_bMinimized; + sal_Bool m_bInvisible; + bool m_bServicesRegistered; + sal_uInt16 m_nAppEvents; + BootstrapError m_aBootstrapError; + BootstrapStatus m_aBootstrapStatus; + + Lockfile *m_pLockfile; + Timer m_firstRunTimer; + + static ResMgr* pResMgr; + static sal_Bool bSuppressOpenDefault; +}; + +} + +#endif // _DESKTOP_APP_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/inc/deployment.hrc b/desktop/inc/deployment.hrc new file mode 100755 index 000000000000..22492cd8ae88 --- /dev/null +++ b/desktop/inc/deployment.hrc @@ -0,0 +1,78 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DEPLOYMENT_HRC +#define INCLUDED_DEPLOYMENT_HRC + +#define MASKCOLOR MaskColor = \ + Color { Red = 0xFFFF ; Green = 0x0000 ; Blue = 0xFFFF ; }; + +#define RID_DEPLOYMENT_START 2000 + +#define RID_DEPLOYMENT_GUI_START RID_DEPLOYMENT_START +#define RID_DEPLOYMENT_MISC_START (RID_DEPLOYMENT_START+500) +#define RID_DEPLOYMENT_MANAGER_START (RID_DEPLOYMENT_START+1000) +#define RID_DEPLOYMENT_REGISTRY_START (RID_DEPLOYMENT_START+1500) + +#define RID_DEPLOYMENT_BUNDLE_START (RID_DEPLOYMENT_START+2000) +#define RID_IMG_DEF_PACKAGE_BUNDLE RID_DEPLOYMENT_BUNDLE_START + +#define RID_DEPLOYMENT_SCRIPT_START (RID_DEPLOYMENT_START+2500) +#define RID_IMG_SCRIPTLIB RID_DEPLOYMENT_SCRIPT_START +#define RID_IMG_DIALOGLIB (RID_DEPLOYMENT_SCRIPT_START+2) + +#define RID_DEPLOYMENT_CONF_START (RID_DEPLOYMENT_START+3000) +#define RID_IMG_CONF_XML RID_DEPLOYMENT_CONF_START + +#define RID_DEPLOYMENT_COMPONENT_START (RID_DEPLOYMENT_START+3500) +#define RID_IMG_COMPONENT RID_DEPLOYMENT_COMPONENT_START +#define RID_IMG_JAVA_COMPONENT (RID_DEPLOYMENT_COMPONENT_START+2) +#define RID_IMG_TYPELIB (RID_DEPLOYMENT_COMPONENT_START+4) +#define RID_IMG_JAVA_TYPELIB (RID_DEPLOYMENT_COMPONENT_START+6) + +#define RID_DEPLOYMENT_UNOPKG_START (RID_DEPLOYMENT_START+4000) +#define RID_STR_UNOPKG_ACCEPT_LIC_1 (RID_DEPLOYMENT_UNOPKG_START+1) +#define RID_STR_UNOPKG_ACCEPT_LIC_2 (RID_DEPLOYMENT_UNOPKG_START+2) +#define RID_STR_UNOPKG_ACCEPT_LIC_3 (RID_DEPLOYMENT_UNOPKG_START+3) +#define RID_STR_UNOPKG_ACCEPT_LIC_4 (RID_DEPLOYMENT_UNOPKG_START+4) +#define RID_STR_UNOPKG_ACCEPT_LIC_YES (RID_DEPLOYMENT_UNOPKG_START+5) +#define RID_STR_UNOPKG_ACCEPT_LIC_Y (RID_DEPLOYMENT_UNOPKG_START+6) +#define RID_STR_UNOPKG_ACCEPT_LIC_NO (RID_DEPLOYMENT_UNOPKG_START+7) +#define RID_STR_UNOPKG_ACCEPT_LIC_N (RID_DEPLOYMENT_UNOPKG_START+8) +#define RID_STR_UNOPKG_ERROR (RID_DEPLOYMENT_UNOPKG_START+9) +#define RID_STR_CONCURRENTINSTANCE (RID_DEPLOYMENT_UNOPKG_START+10) + +#define RID_DEPLOYMENT_DEPENDENCIES_START (RID_DEPLOYMENT_START + 4400) +#define RID_DEPLYOMENT_DEPENDENCIES_UNKNOWN RID_DEPLOYMENT_DEPENDENCIES_START +#define RID_DEPLYOMENT_DEPENDENCIES_MIN (RID_DEPLOYMENT_DEPENDENCIES_START+1) +#define RID_DEPLYOMENT_DEPENDENCIES_MAX (RID_DEPLOYMENT_DEPENDENCIES_START+2) + +#define RID_DEPLOYMENT_LICENSE_START (RID_DEPLOYMENT_START+4500) + +#define RID_DEPLOYMENT_HELP_START (RID_DEPLOYMENT_START+5000) +#define RID_IMG_HELP RID_DEPLOYMENT_HELP_START +#endif diff --git a/desktop/inc/makefile.mk b/desktop/inc/makefile.mk new file mode 100755 index 000000000000..8715d814274f --- /dev/null +++ b/desktop/inc/makefile.mk @@ -0,0 +1,47 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=inc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +.IF "$(ENABLE_PCH)"!="" +ALLTAR : \ + $(SLO)$/precompiled.pch \ + $(SLO)$/precompiled_ex.pch + +.ENDIF # "$(ENABLE_PCH)"!="" + diff --git a/desktop/inc/migration.hxx b/desktop/inc/migration.hxx new file mode 100644 index 000000000000..3319d8d7716f --- /dev/null +++ b/desktop/inc/migration.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_MIGRATION_HXX_ +#define _DESKTOP_MIGRATION_HXX_ + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +namespace desktop { + +class Migration +{ +public: + static void migrateSettingsIfNecessary(); +}; +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/inc/pch/precompiled_desktop.cxx b/desktop/inc/pch/precompiled_desktop.cxx new file mode 100644 index 000000000000..24d7e45f222d --- /dev/null +++ b/desktop/inc/pch/precompiled_desktop.cxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "precompiled_desktop.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/inc/pch/precompiled_desktop.hxx b/desktop/inc/pch/precompiled_desktop.hxx new file mode 100644 index 000000000000..6baa50c69781 --- /dev/null +++ b/desktop/inc/pch/precompiled_desktop.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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): Generated on 2006-09-01 17:49:39.170923 + +#ifdef PRECOMPILED_HEADERS +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/beans/NamedValue.hpp" +#include "comphelper/processfactory.hxx" +#include "osl/file.hxx" +#include "rtl/bootstrap.hxx" +#include "rtl/ustring.hxx" +#include "tools/datetime.hxx" +#include "tools/debug.hxx" +#include "unotools/configmgr.hxx" +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/prj/build.lst b/desktop/prj/build.lst new file mode 100644 index 000000000000..a2c6f0ac6f88 --- /dev/null +++ b/desktop/prj/build.lst @@ -0,0 +1,47 @@ +dt desktop : TRANSLATIONS:translations sfx2 stoc BERKELEYDB:berkeleydb sysui BOOST:boost svx xmlhelp sal unoil officecfg offapi filter LIBXSLT:libxslt NULL +dt desktop usr1 - all dt_mkout NULL +dt desktop\inc nmake - all dt_inc NULL +dt desktop\prj get - all dt_prj NULL +dt desktop\res get - all dt_res NULL +dt desktop\source\app nmake - all dt_app dt_migr dt_inc dt_dp_misc NULL +dt desktop\source\migration nmake - all dt_migr dt_inc NULL +dt desktop\source\migration\services nmake - all dt_services dt_inc dt_dp_misc NULL +dt desktop\source\offacc nmake - all dt_offac dt_inc NULL +dt desktop\source\splash nmake - all dt_spl dt_migr dt_inc NULL +dt desktop\win32\source nmake - w dt_wrapper dt_inc NULL +dt desktop\win32\source\setup nmake - w dt_setup dt_inc NULL +dt desktop\win32\source\officeloader nmake - w dt_officeloader dt_inc NULL +dt desktop\win32\source\guiloader nmake - w dt_guiloader dt_wrapper.w dt_inc NULL +dt desktop\win32\source\guistdio nmake - w dt_guistdio dt_inc NULL +dt desktop\win32\source\applauncher nmake - w dt_applauncher dt_inc NULL +dt desktop\win32\source\applauncher\ooo nmake - w dt_applauncher_ooo dt_applauncher.w dt_inc NULL +dt desktop\win32\source\QuickStart nmake - w dt_win32_quickstart NULL +dt desktop\win32\source\QuickStart\so nmake - w dt_win32_quickstart_so dt_win32_quickstart.w NULL + +dt desktop\os2\source\applauncher nmake - p dt_applauncher dt_inc NULL +dt desktop\unx\source\officeloader nmake - u dt_officeloader_unx dt_inc NULL +dt desktop\unx\source nmake - u dt_uwrapper dt_pagein.u dt_inc NULL +dt desktop\source\pagein nmake - u dt_pagein dt_inc NULL +dt desktop\source\pkgchk\unopkg nmake - all dt_unopkg dt_dp_misc dt_app dt_inc dt_guiloader.w NULL +dt desktop\unx\splash nmake - u dt_usplash dt_pagein.u dt_inc NULL +dt desktop\source\deployment nmake - all dt_deployment dt_dp_manager dt_dp_registry dt_dp_registry_package dt_dp_registry_executable dt_dp_registry_help dt_dp_registry_script dt_dp_registry_sfwk dt_dp_registry_component dt_dp_registry_configuration dt_dp_unopkg dt_inc dt_dp_misc NULL +dt desktop\source\deployment\misc nmake - all dt_dp_misc dt_inc NULL +dt desktop\source\deployment\unopkg nmake - all dt_dp_unopkg dt_inc NULL +dt desktop\source\deployment\gui nmake - all dt_dp_gui dt_dp_misc dt_inc NULL +dt desktop\source\deployment\manager nmake - all dt_dp_manager dt_inc NULL +dt desktop\source\deployment\registry nmake - all dt_dp_registry dt_inc NULL +dt desktop\source\deployment\registry\package nmake - all dt_dp_registry_package dt_inc NULL +dt desktop\source\deployment\registry\script nmake - all dt_dp_registry_script dt_inc NULL +dt desktop\source\deployment\registry\sfwk nmake - all dt_dp_registry_sfwk dt_inc NULL +dt desktop\source\deployment\registry\component nmake - all dt_dp_registry_component dt_inc NULL +dt desktop\source\deployment\registry\configuration nmake - all dt_dp_registry_configuration dt_inc NULL +dt desktop\source\deployment\registry\help nmake - all dt_dp_registry_help dt_inc NULL +dt desktop\source\deployment\registry\executable nmake - all dt_dp_registry_executable dt_inc NULL +dt desktop\scripts nmake - u dt_scripts dt_inc NULL +dt desktop\util nmake - all dt_util dt_app dt_pagein.u dt_spl dt_uwrapper.u dt_usplash.u dt_wrapper.w dt_officeloader.w dt_officeloader_unx.u dt_migr dt_win32_quickstart_so.w dt_zipintro NULL +dt desktop\zipintro nmake - all dt_zipintro NULL +dt desktop\registry\data\org\openoffice\Office nmake - all sn_regconfig NULL +dt desktop\qa\deployment_misc nmake - all sn_qa_deployment_misc dt_dp_misc dt_inc NULL +dt desktop\test\deployment\active nmake - all dt_test_deployment_active NULL +dt desktop\test\deployment\boxt nmake - all dt_test_deployment_boxt NULL +dt desktop\test\deployment\passive nmake - all dt_test_deployment_passive NULL diff --git a/desktop/prj/d.lst b/desktop/prj/d.lst new file mode 100644 index 000000000000..008ade9ff656 --- /dev/null +++ b/desktop/prj/d.lst @@ -0,0 +1,146 @@ +mkdir: %COMMON_DEST%\bin\hid +mkdir: %_DEST%\bin\so +mkdir: %_DEST%\bin\c01 +mkdir: %_DEST%\bin\c05 +mkdir: %_DEST%\bin\c08 +mkdir: %_DEST%\bin\odf4ms + +..\%COMMON_OUTDIR%\misc\*.hid %COMMON_DEST%\bin\hid\*.hid +..\%__SRC%\bin\soffice.bin %_DEST%\bin\soffice.bin +..\%__SRC%\bin\officeloader.exe %_DEST%\bin\soffice.exe +..\%__SRC%\bin\soffice %_DEST%\bin\soffice.bin +..\%__SRC%\bin\soffice_mac %_DEST%\bin\soffice +..\%__SRC%\bin\oosplash %_DEST%\bin\oosplash.bin +..\%__SRC%\bin\so\soffice.bin %_DEST%\bin\so\soffice.bin +..\%__SRC%\bin\so\officeloader.exe %_DEST%\bin\so\soffice.exe +..\%__SRC%\bin\so\soffice %_DEST%\bin\so\soffice.bin +..\%__SRC%\bin\so\soffice_mac %_DEST%\bin\so\soffice +..\%__SRC%\bin\sofficea*.dll %_DEST%\bin\sofficea*.dll +..\%__SRC%\lib\isofficeapp.lib %_DEST%\lib\isofficeapp.lib +..\%__SRC%\lib\libsofficeapp.dylib %_DEST%\lib\libsofficeapp.dylib +..\%__SRC%\lib\libsofficeapp.so %_DEST%\lib\libsofficeapp.so + +..\%__SRC%\bin\soffice_oo.exe %_DEST%\bin\soffice_oo.exe +..\%__SRC%\bin\soffice_oo %_DEST%\bin\soffice_oo.bin +..\%__SRC%\bin\so\soffice_so.exe %_DEST%\bin\so\soffice_so.exe +..\%__SRC%\bin\so\soffice_so %_DEST%\bin\so\soffice_so.bin + +..\%__SRC%\bin\scalc.exe %_DEST%\bin\scalc.exe +..\%__SRC%\bin\sdraw.exe %_DEST%\bin\sdraw.exe +..\%__SRC%\bin\simpress.exe %_DEST%\bin\simpress.exe +..\%__SRC%\bin\smath.exe %_DEST%\bin\smath.exe +..\%__SRC%\bin\swriter.exe %_DEST%\bin\swriter.exe +..\%__SRC%\bin\sbase.exe %_DEST%\bin\sbase.exe +..\%__SRC%\bin\sweb.exe %_DEST%\bin\sweb.exe +..\%__SRC%\bin\os2quickstart.exe %_DEST%\bin\quickstart.exe +..\%__SRC%\bin\so\scalc.exe %_DEST%\bin\so\scalc.exe +..\%__SRC%\bin\so\sdraw.exe %_DEST%\bin\so\sdraw.exe +..\%__SRC%\bin\so\simpress.exe %_DEST%\bin\so\simpress.exe +..\%__SRC%\bin\so\smath.exe %_DEST%\bin\so\smath.exe +..\%__SRC%\bin\so\swriter.exe %_DEST%\bin\so\swriter.exe +..\%__SRC%\bin\so\sbase.exe %_DEST%\bin\so\sbase.exe +..\%__SRC%\bin\so\sweb.exe %_DEST%\bin\so\sweb.exe + +..\%__SRC%\bin\quickstart.exe %_DEST%\bin\quickstart.exe +..\%__SRC%\bin\quickstart.exe %_DEST%\bin\install_quickstart.exe +..\%__SRC%\bin\soquickstart.exe %_DEST%\bin\so\quickstart.exe +..\%__SRC%\bin\soquickstart.exe %_DEST%\bin\so\install_quickstart.exe + +..\%__SRC%\misc\soffice.exe.manifest %_DEST%\bin\soffice.exe.manifest +..\%__SRC%\misc\soffice.bin.manifest %_DEST%\bin\soffice.bin.manifest +..\%__SRC%\bin\wrp*.dll %_DEST%\bin\wrp*.dll +..\%__SRC%\bin\spl*.dll %_DEST%\bin\spl*.dll +..\%__SRC%\obj\officeloader.obj %_DEST%\lib\officeloader.obj +..\%__SRC%\obj\extendloaderenvironment.obj %_DEST%\lib\extendloaderenvironment.obj +..\%__SRC%\obj\copyright_ascii_sun.obj %_DEST%\lib\copyright_ascii_sun.obj +..\%__SRC%\obj\main.obj %_DEST%\lib\main.obj +..\%__SRC%\lib\libwrp*.so %_DEST%\lib\libwrp*.so +..\%__SRC%\lib\libwrp*.dylib %_DEST%\lib\libwrp*.dylib +..\%__SRC%\lib\libspl*.so %_DEST%\lib\libspl*.so +..\%__SRC%\lib\libspl*.dylib %_DEST%\lib\libspl*.dylib +..\%__SRC%\bin\offacc*.dll %_DEST%\bin\offacc*.dll +..\%__SRC%\lib\liboffacc*.so %_DEST%\lib\liboffacc*.so +..\%__SRC%\lib\liboffacc*.dylib %_DEST%\lib\liboffacc*.dylib +..\%__SRC%\bin\migratio*.dll %_DEST%\bin\migratio*.dll +..\%__SRC%\lib\migratio*.uno.so %_DEST%\lib\migratio*.uno.so +..\%__SRC%\lib\migratio*.uno.dylib %_DEST%\lib\migratio*.uno.dylib + +..\%__SRC%\bin\sweb %_DEST%\bin\sweb.bin + +..\%__SRC%\bin\loader2.ex? %_DEST%\bin\loader2.ex? + +..\%__SRC%\bin\depl*.dll %_DEST%\bin\depl*.dll +..\%__SRC%\lib\deployment*.uno.so %_DEST%\lib\deployment*.uno.so +..\%__SRC%\lib\deployment*.uno.dylib %_DEST%\lib\deployment*.uno.dylib +..\%__SRC%\bin\deploymentmisc*.dll %_DEST%\bin\deploymentmisc*.dll +..\%__SRC%\lib\libdeploymentmisc*.so %_DEST%\lib\libdeploymentmisc*.so +..\%__SRC%\lib\libdeploymentmisc*.dylib %_DEST%\lib\libdeploymentmisc*.dylib +..\%__SRC%\bin\guiloader.exe %_DEST%\bin\unopkg.exe +..\%__SRC%\bin\so\guiloader.exe %_DEST%\bin\so\unopkg.exe +..\%__SRC%\bin\unopkg %_DEST%\bin\unopkg.bin +..\%__SRC%\bin\so\unopkg %_DEST%\bin\so\unopkg.bin +..\%__SRC%\bin\unopkg.exe %_DEST%\bin\unopkg.bin +..\%__SRC%\bin\so\unopkg.exe %_DEST%\bin\so\unopkg.bin +..\%__SRC%\misc\unopkg.sh %_DEST%\bin\unopkg +..\%__SRC%\bin\unopkga*.dll %_DEST%\bin\unopkga*.dll +..\%__SRC%\lib\libunopkgapp.dylib %_DEST%\lib\libunopkgapp.dylib +..\%__SRC%\lib\libunopkgapp.so %_DEST%\lib\libunopkgapp.so + +..\%__SRC%\bin\pagein %_DEST%\bin\pagein +..\%__SRC%\misc\pagein-* %_DEST%\bin\pagein-* + +..\%__SRC%\bin\unoinfo.exe %_DEST%\bin\unoinfo.exe +..\%__SRC%\misc\unoinfo.sh %_DEST%\bin\unoinfo + +..\%__SRC%\bin\*.res %_DEST%\bin\*.res + +..\%__SRC%\misc\soffice.sh-expanded %_DEST%\bin\soffice +..\%__SRC%\misc\sbase.sh %_DEST%\bin\sbase +..\%__SRC%\misc\scalc.sh %_DEST%\bin\scalc +..\%__SRC%\misc\sdraw.sh %_DEST%\bin\sdraw +..\%__SRC%\misc\simpress.sh %_DEST%\bin\simpress +..\%__SRC%\misc\smaster.sh %_DEST%\bin\smaster +..\%__SRC%\misc\smath.sh %_DEST%\bin\smath +..\%__SRC%\misc\sweb.sh %_DEST%\bin\sweb +..\%__SRC%\misc\swriter.sh %_DEST%\bin\swriter +..\%__SRC%\misc\nswrapper.sh %_DEST%\bin\nswrapper +..\%__SRC%\misc\mozwrapper.sh %_DEST%\bin\mozwrapper +..\%__SRC%\misc\gdbtrace %_DEST%\bin\gdbtrace + +mkdir: %COMMON_DEST%\pck\brand +mkdir: %COMMON_DEST%\pck\brand_dev + +..\%__SRC%\bin\intro.zip %COMMON_DEST%\pck\intro.zip +..\%__SRC%\bin\brand\intro.zip %COMMON_DEST%\pck\brand\intro.zip +..\%__SRC%\bin\brand_dev\intro.zip %COMMON_DEST%\pck\brand_dev\intro.zip +..\%__SRC%\bin\shell\shell.zip %COMMON_DEST%\pck\shell.zip + +..\%__SRC%\bin\guiloader.exe %_DEST%\bin\testtool.exe + +..\%__SRC%\bin\guistdio.exe %_DEST%\bin\guistdio.com +..\%__SRC%\bin\guistdio.exe %_DEST%\bin\crashrep.com +..\%__SRC%\bin\unopkgio.exe %_DEST%\bin\unopkg.com + +..\scripts\ure-link %_DEST%\bin\ure-link +..\scripts\basis-link %_DEST%\bin\basis-link +..\scripts\basis-link %_DEST%\bin\c01\basis-link +..\scripts\basis-link %_DEST%\bin\c05\basis-link +..\scripts\basis-link %_DEST%\bin\c08\basis-link +..\scripts\so-basis-link %_DEST%\bin\so\basis-link +..\scripts\odf-basis-link %_DEST%\bin\odf4ms\basis-link + +mkdir: %_DEST%\xml\registry\spool +mkdir: %_DEST%\xml\registry\spool\org +mkdir: %_DEST%\xml\registry\spool\org\openoffice +mkdir: %_DEST%\xml\registry\spool\org\openoffice\Office +mkdir: %_DEST%\xml\registry\spool\org\openoffice\Office\Jobs + +..\%__SRC%\class\*.jar %_DEST%\bin\*.jar +..\%__SRC%\misc\registry\spool\org\openoffice\Office\Jobs\*.xcu %_DEST%\xml\registry\spool\org\openoffice\Office\Jobs +..\%__SRC%\misc\deployment.component %_DEST%\xml\deployment.component +..\%__SRC%\misc\deploymentgui.component %_DEST%\xml\deploymentgui.component +..\%__SRC%\misc\migrationoo2.component %_DEST%\xml\migrationoo2.component +..\%__SRC%\misc\migrationoo3.component %_DEST%\xml\migrationoo3.component +..\%__SRC%\misc\offacc.component %_DEST%\xml\offacc.component +..\%__SRC%\misc\spl.component %_DEST%\xml\spl.component +..\%__SRC%\misc\splash.component %_DEST%\xml\splash.component diff --git a/desktop/qa/deployment_misc/makefile.mk b/desktop/qa/deployment_misc/makefile.mk new file mode 100755 index 000000000000..16223914e740 --- /dev/null +++ b/desktop/qa/deployment_misc/makefile.mk @@ -0,0 +1,56 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 := qa_deployment_misc + +ENABLE_EXCEPTIONS := TRUE + +.INCLUDE: settings.mk +.INCLUDE: $(PRJ)$/source$/deployment$/inc$/dp_misc.mk + +CFLAGSCXX += $(CPPUNIT_CFLAGS) + +# TODO: On Windows, test_dp_version.cxx fails due to BOOL redefinition between +# windef.h and tools/solar.h caused by including "precompiled_desktop.hxx"; this +# hack to temporarily disable PCH will become unnecessary with the fix for issue +# 112600: +CFLAGSCXX += -DDISABLE_PCH_HACK + +SHL1TARGET = $(TARGET) +SHL1OBJS = $(SLO)$/test_dp_version.obj +SHL1STDLIBS = $(CPPUNITLIB) $(DEPLOYMENTMISCLIB) $(SALLIB) +SHL1VERSIONMAP = version.map +SHL1RPATH = NONE +SHL1IMPLIB = i$(SHL1TARGET) +DEF1NAME = $(SHL1TARGET) + +SLOFILES = $(SHL1OBJS) + +.INCLUDE: target.mk +.INCLUDE : _cppunit.mk diff --git a/desktop/qa/deployment_misc/test_dp_version.cxx b/desktop/qa/deployment_misc/test_dp_version.cxx new file mode 100644 index 000000000000..480172bb5abe --- /dev/null +++ b/desktop/qa/deployment_misc/test_dp_version.cxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "sal/config.h" + +#include <cstddef> + +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" +#include "cppunit/plugin/TestPlugIn.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" + +#include "../../source/deployment/inc/dp_version.hxx" + +namespace { + +class Test: public ::CppUnit::TestFixture { +public: + void test(); + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(test); + CPPUNIT_TEST_SUITE_END(); +}; + +void Test::test() { + struct Data { + rtl::OUString version1; + rtl::OUString version2; + ::dp_misc::Order order; + }; + static Data const data[] = { + { rtl::OUString(), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0.0000.00.0")), + ::dp_misc::EQUAL }, + { rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".01")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0.1")), + ::dp_misc::EQUAL }, + { rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("10")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("2")), + ::dp_misc::GREATER }, + { rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("9223372036854775808")), + // 2^63 + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("9223372036854775807")), + ::dp_misc::GREATER } + }; + for (::std::size_t i = 0; i < sizeof data / sizeof (Data); ++i) { + CPPUNIT_ASSERT_EQUAL( + data[i].order, + ::dp_misc::compareVersions(data[i].version1, data[i].version2)); + static ::dp_misc::Order const reverse[3] = { + ::dp_misc::GREATER, ::dp_misc::EQUAL, ::dp_misc::LESS + }; + CPPUNIT_ASSERT_EQUAL( + reverse[data[i].order], + ::dp_misc::compareVersions(data[i].version2, data[i].version1)); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Test); + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/qa/deployment_misc/version.map b/desktop/qa/deployment_misc/version.map new file mode 100755 index 000000000000..3308588ef6f8 --- /dev/null +++ b/desktop/qa/deployment_misc/version.map @@ -0,0 +1,34 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +UDK_3_0_0 { + global: + cppunitTestPlugIn; + + local: + *; +}; diff --git a/desktop/registry/data/org/openoffice/Office/Jobs.xcu b/desktop/registry/data/org/openoffice/Office/Jobs.xcu new file mode 100644 index 000000000000..0572d96a2a63 --- /dev/null +++ b/desktop/registry/data/org/openoffice/Office/Jobs.xcu @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--*********************************************************************** + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************ --> +<oor:component-data oor:name="Jobs" oor:package="org.openoffice.Office" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <node oor:name="Jobs"> + <node oor:name="ProductRegistration" oor:op="replace"> + <prop oor:name="Service"> + <value>com.sun.star.comp.framework.DoRegistrationJob</value> + </prop> + <node oor:name="Arguments"> + <prop oor:name="ProductName" oor:op="replace" oor:type="xs:string"> + <value>${SERVICETAG_PRODUCTNAME}</value> + </prop> + <prop oor:name="ProductVersion" oor:op="replace" oor:type="xs:string"> + <value>${SERVICETAG_PRODUCTVERSION}</value> + </prop> + <prop oor:name="ProductURN" oor:op="replace" oor:type="xs:string"> + <value>${SERVICETAG_URN}</value> + </prop> + <prop oor:name="ProductSource" oor:op="replace" oor:type="xs:string"> + <value>${SERVICETAG_SOURCE}</value> + </prop> + <prop oor:name="ProductParent" oor:op="replace" oor:type="xs:string"> + <value>${SERVICETAG_PARENTNAME}</value> + </prop> + <prop oor:name="Vendor" oor:op="replace" oor:type="xs:string"> + <value>Sun Microsystems, Inc.</value> + </prop> + <prop oor:name="RegistrationData" oor:op="replace" oor:type="xs:string"> + <value>$(user)/registration.xml</value> + </prop> + <prop oor:name="RegistrationURL" oor:op="replace" oor:type="xs:string"> + <value>${REGISTRATION_HOST}/register/${registry_urn}?product=${REGISTRATION_PRODUCT}&locale=${locale}&cid=${REGISTRATION_CID}</value> + </prop> + </node> + </node> + </node> + <node oor:name="Events"> + <node oor:name="onRegisterNow" oor:op="fuse"> + <node oor:name="JobList"> + <node oor:name="ProductRegistration" oor:op="replace"/> + </node> + </node> + <node oor:name="onRegisterLater" oor:op="fuse"> + <node oor:name="JobList"> + <node oor:name="ProductRegistration" oor:op="replace"/> + </node> + </node> + </node> +</oor:component-data> diff --git a/desktop/registry/data/org/openoffice/Office/makefile.mk b/desktop/registry/data/org/openoffice/Office/makefile.mk new file mode 100755 index 000000000000..2ad8441ea3d3 --- /dev/null +++ b/desktop/registry/data/org/openoffice/Office/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=setup_native +TARGET=data_registration +PACKAGE=org.openoffice.Office + +ABSXCSROOT=$(SOLARXMLDIR) +XCSROOT=.. +DTDDIR=$(ABSXCSROOT) +XSLDIR=$(ABSXCSROOT)$/processing +PROCESSOUT=$(MISC)$/$(TARGET) +PROCESSORDIR=$(SOLARBINDIR) + +.INCLUDE : settings.mk +.IF "$(L10N_framework)"=="" + +# --- Files ------------------------------------------------------- + +.IF "$(BUILD_SPECIAL)"!="" + +XCUFILES= \ + Jobs.xcu + +MODULEFILES= + +LOCALIZEDFILES= + +PACKAGEDIR=$(subst,.,$/ $(PACKAGE)) +SPOOLDIR=$(MISC)$/registry$/spool + +MYXCUFILES= \ + $(SPOOLDIR)$/$(PACKAGEDIR)$/Jobs$/Jobs-registration.xcu + +.ELSE # "$(BUILD_SPECIAL)"!="" + +dummy: + @echo "Nothing to build" + +.ENDIF # "$(BUILD_SPECIAL)"!="" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +.ENDIF # L10N_framework +ALLTAR : $(MYXCUFILES) + +$(SPOOLDIR)$/$(PACKAGEDIR)$/Jobs$/Jobs-registration.xcu : $(PROCESSOUT)$/registry$/data$/$/$(PACKAGEDIR)$/Jobs.xcu + @-$(MKDIRHIER) $(@:d) + @$(COPY) $< $@ + diff --git a/desktop/scripts/basis-link b/desktop/scripts/basis-link new file mode 100755 index 000000000000..3af84201e04f --- /dev/null +++ b/desktop/scripts/basis-link @@ -0,0 +1 @@ +Basis
\ No newline at end of file diff --git a/desktop/scripts/gdbtrace b/desktop/scripts/gdbtrace new file mode 100644 index 000000000000..548ffe6512e9 --- /dev/null +++ b/desktop/scripts/gdbtrace @@ -0,0 +1,12 @@ +set pagination off +echo log will be saved as gdbtrace.log, this will take some time, patience...\n +set logging redirect on +set logging file gdbtrace.log +set logging on +set logging overwrite on +run +bt +thread apply all bt +quit +set logging off +echo log is saved as gdbtrace.log\n diff --git a/desktop/scripts/makefile.mk b/desktop/scripts/makefile.mk new file mode 100755 index 000000000000..ce0c9b8ed292 --- /dev/null +++ b/desktop/scripts/makefile.mk @@ -0,0 +1,68 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=scripts + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Targets ------------------------------------------------------------- + +UNIXTEXT= \ + $(MISC)$/sbase.sh \ + $(MISC)$/scalc.sh \ + $(MISC)$/sdraw.sh \ + $(MISC)$/simpress.sh \ + $(MISC)$/smaster.sh \ + $(MISC)$/smath.sh \ + $(MISC)$/sweb.sh \ + $(MISC)$/swriter.sh \ + $(MISC)$/mozwrapper.sh \ + $(MISC)$/unoinfo.sh \ + $(MISC)$/unopkg.sh \ + $(MISC)$/gdbtrace + +.IF "$(OS)" != "MACOSX" + +ALLTAR: $(MISC)$/soffice.sh-expanded + +$(MISC)/soffice.sh-expanded: $(MISC)/soffice.sh +.IF "$(OS)" == "LINUX" && "$(CPUNAME)" == "POWERPC" + $(SED) 's/^#@# //' $< > $@ +.ELSE + $(COPY) $< $@ +.ENDIF + +UNIXTEXT+= $(MISC)$/soffice.sh + +.ENDIF + +.INCLUDE : target.mk diff --git a/desktop/scripts/mozwrapper.sh b/desktop/scripts/mozwrapper.sh new file mode 100755 index 000000000000..89b6415358be --- /dev/null +++ b/desktop/scripts/mozwrapper.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# if mozilla is not found, specify full path here +MOZILLA=mozilla + +if ${MOZILLA} -remote "openURL($1,new-window)" 2>&1 | egrep -si "not running on display"; then + ${MOZILLA} $1 +fi diff --git a/desktop/scripts/odf-basis-link b/desktop/scripts/odf-basis-link new file mode 100755 index 000000000000..3af84201e04f --- /dev/null +++ b/desktop/scripts/odf-basis-link @@ -0,0 +1 @@ +Basis
\ No newline at end of file diff --git a/desktop/scripts/sbase.sh b/desktop/scripts/sbase.sh new file mode 100755 index 000000000000..e3a8ed07d5c0 --- /dev/null +++ b/desktop/scripts/sbase.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" --base "$@" diff --git a/desktop/scripts/scalc.sh b/desktop/scripts/scalc.sh new file mode 100755 index 000000000000..c9c3cde39e49 --- /dev/null +++ b/desktop/scripts/scalc.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" --calc "$@" diff --git a/desktop/scripts/sdraw.sh b/desktop/scripts/sdraw.sh new file mode 100755 index 000000000000..4131a2505f48 --- /dev/null +++ b/desktop/scripts/sdraw.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" --draw "$@" diff --git a/desktop/scripts/simpress.sh b/desktop/scripts/simpress.sh new file mode 100755 index 000000000000..d78ea14207c0 --- /dev/null +++ b/desktop/scripts/simpress.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" --impress "$@" diff --git a/desktop/scripts/smaster.sh b/desktop/scripts/smaster.sh new file mode 100755 index 000000000000..ed9b09d51279 --- /dev/null +++ b/desktop/scripts/smaster.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" --global "$@" diff --git a/desktop/scripts/smath.sh b/desktop/scripts/smath.sh new file mode 100755 index 000000000000..454fa135ff8e --- /dev/null +++ b/desktop/scripts/smath.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" --math "$@" diff --git a/desktop/scripts/so-basis-link b/desktop/scripts/so-basis-link new file mode 100755 index 000000000000..3af84201e04f --- /dev/null +++ b/desktop/scripts/so-basis-link @@ -0,0 +1 @@ +Basis
\ No newline at end of file diff --git a/desktop/scripts/soffice.sh b/desktop/scripts/soffice.sh new file mode 100755 index 000000000000..775f9741f059 --- /dev/null +++ b/desktop/scripts/soffice.sh @@ -0,0 +1,178 @@ +#!/bin/sh +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +# +# STAR_PROFILE_LOCKING_DISABLED=1 +# export STAR_PROFILE_LOCKING_DISABLED +# + +# file locking now enabled by default +SAL_ENABLE_FILE_LOCKING=1 +export SAL_ENABLE_FILE_LOCKING + +# Uncomment the line below if you suspect that OpenGL is not +# working on your system. +# SAL_NOOPENGL=true; export SAL_NOOPENGL + +# uncomment line below to disable anti aliasing of fonts +# SAL_ANTIALIAS_DISABLE=true; export SAL_ANTIALIAS_DISABLE + +# uncomment line below if you encounter problems starting soffice on your system +# SAL_NO_XINITTHREADS=true; export SAL_NO_XINITTHREADS + +# The following is needed on Linux PPC with IBM j2sdk142: +#@# export JITC_PROCESSOR_TYPE=6 + +# resolve installation directory +sd_cwd=`pwd` +sd_res=$0 +while [ -h "$sd_res" ] ; do + cd "`dirname "$sd_res"`" + sd_basename=`basename "$sd_res"` + sd_res=`ls -l "$sd_basename" | sed "s/.*$sd_basename -> //g"` +done +cd "`dirname "$sd_res"`" +sd_prog=`pwd` +cd "$sd_cwd" + +# linked build needs additional settings +if [ -e $sd_prog/ooenv ] ; then + . $sd_prog/ooenv +fi + +# try to get some debug output? +GDBTRACECHECK= +STRACECHECK= +VALGRINDCHECK= + +# count number of selected checks; only one is allowed +checks= +# force the --valgrind option if the VALGRIND variable is set +test -n "$VALGRIND" && VALGRINDOPT="--valgrind" || VALGRINDOPT= + +for arg in $@ $VALGRINDOPT ; do + case "$arg" in + --backtrace) + if which gdb >/dev/null 2>&1 ; then + GDBTRACECHECK="gdb -nx --command=$sd_prog/gdbtrace --args" + checks="c$checks" + else + echo "Error: Can't find the tool \"gdb\", --backtrace option will be ignored." + exit 1 + fi + ;; + --strace) + if which strace >/dev/null 2>&1 ; then + STRACECHECK="strace -o strace.log -f -tt -s 256" + checks="c$checks" + else + echo "Error: Can't find the tool \"strace\", --strace option will be ignored." + exit 1; + fi + ;; + --valgrind) + test -n "$VALGRINDCHECK" && continue; + if which valgrind >/dev/null 2>&1 ; then + # another valgrind tool might be forced via the environment variable + test -z "$VALGRIND" && VALGRIND="memcheck" + # --trace-children-skip is pretty useful but supported only with valgrind >= 3.6.0 + valgrind_ver=`valgrind --version | sed -e "s/valgrind-//"` + valgrind_ver_maj=`echo $valgrind_ver | awk -F. '{ print \$1 }'` + valgrind_ver_min=`echo $valgrind_ver | awk -F. '{ print \$2 }'` + valgrind_skip= + if [ "$valgrind_ver_maj" -gt 3 -o \( "$valgrind_ver_maj" -eq 3 -a "$valgrind_ver_min" -ge 6 \) ] ; then + valgrind_skip='--trace-children-skip=*/java' + fi + # finally set the valgrind check + VALGRINDCHECK="valgrind --tool=$VALGRIND --trace-children=yes $valgrind_skip --num-callers=50 --error-exitcode=101" + checks="c$checks" + if [ "$VALGRIND" = "memcheck" ] ; then + export G_SLICE=always-malloc + export GLIBCXX_FORCE_NEW=1 + fi + else + echo "Error: Can't find the tool \"valgrind\", --valgrind option will be ignored" + exit 1 + fi + ;; + esac +done + +if echo "$checks" | grep -q "cc" ; then + echo "Error: The debug options --backtrace, --strace, and --valgrind cannot be used together." + echo " Please, use them one by one." + exit 1; +fi + +case "`uname -s`" in +NetBSD|OpenBSD|FreeBSD|DragonFly) +# this is a temporary hack until we can live with the default search paths + sd_prog1="$sd_prog/../basis-link/program" + sd_prog2="$sd_prog/../basis-link/ure-link/lib" + LD_LIBRARY_PATH=$sd_prog1:$sd_prog2${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} + JAVA_HOME=$(javaPathHelper -h libreoffice-java 2> /dev/null) + export LD_LIBRARY_PATH + if [ -n "${JAVA_HOME}" ]; then + export JAVA_HOME + fi + ;; +AIX) + LIBPATH=$sd_prog:$sd_prog/../basis-link/program:$sd_prog/../basis-link/ure-link/lib${LIBPATH:+:$LIBPATH} + export LIBPATH + ;; +esac + +# run soffice.bin directly when you want to get the backtrace +if [ -n "$GDBTRACECHECK" ] ; then + exec $GDBTRACECHECK "$sd_prog/soffice.bin" "$@" +fi + +# valgrind --log-file=valgrind.log does not work well with --trace-children=yes +if [ -n "$VALGRINDCHECK" ] ; then + echo "redirecting the standard and the error output to valgrind.log" + exec &>valgrind.log +fi + +# do not pass the request for command line help to oosplash +if test "$#" -eq 1; then + case "$1" in + -h | --h | --he | --hel | --help) + "$sd_prog/soffice.bin" -h + exit 0 + ;; + -V | --v | --ve | --ver | --vers | --versi | --versio | --version) + "$sd_prog/soffice.bin" -h | head -1 + exit 0 + ;; + *) + ;; + esac +fi + +# oosplash does the rest: forcing pages in, javaldx etc. are +exec $VALGRINDCHECK $STRACECHECK "$sd_prog/oosplash.bin" "$@" diff --git a/desktop/scripts/sweb.sh b/desktop/scripts/sweb.sh new file mode 100755 index 000000000000..a365392584b6 --- /dev/null +++ b/desktop/scripts/sweb.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" --web "$@" diff --git a/desktop/scripts/swriter.sh b/desktop/scripts/swriter.sh new file mode 100755 index 000000000000..3fa48c0d3eba --- /dev/null +++ b/desktop/scripts/swriter.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" --writer "$@" diff --git a/desktop/scripts/unoinfo.sh b/desktop/scripts/unoinfo.sh new file mode 100755 index 000000000000..a7566155aa0d --- /dev/null +++ b/desktop/scripts/unoinfo.sh @@ -0,0 +1,55 @@ +#!/bin/sh +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +set -e + +# resolve installation directory +sd_res=$0 +while [ -h "$sd_res" ] ; do + cd "`dirname "$sd_res"`" + sd_basename=`basename "$sd_res"` + sd_res=`ls -l "$sd_basename" | sed "s/.*$sd_basename -> //g"` +done +cd "`dirname "$sd_res"`" +sd_prog=`pwd` + +case $1 in +c++) + printf '%s' "$sd_prog/../basis-link/ure-link/lib" + ;; +java) + printf '0%s\0%s\0%s\0%s\0%s' \ + "$sd_prog/../basis-link/ure-link/share/java/ridl.jar" \ + "$sd_prog/../basis-link/ure-link/share/java/jurt.jar" \ + "$sd_prog/../basis-link/ure-link/share/java/juh.jar" \ + "$sd_prog/../basis-link/program/classes/unoil.jar" "$sd_prog" + ;; +*) + exit 1 + ;; +esac diff --git a/desktop/scripts/unopkg.sh b/desktop/scripts/unopkg.sh new file mode 100755 index 000000000000..4419ea077e98 --- /dev/null +++ b/desktop/scripts/unopkg.sh @@ -0,0 +1,115 @@ +#!/bin/sh +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +# enable file locking +SAL_ENABLE_FILE_LOCKING=1 +export SAL_ENABLE_FILE_LOCKING + +# resolve installation directory +sd_cwd=`pwd` +sd_res=$0 +while [ -h "$sd_res" ] ; do + cd "`dirname "$sd_res"`" + sd_basename=`basename "$sd_res"` + sd_res=`ls -l "$sd_basename" | sed "s/.*$sd_basename -> //g"` +done +cd "`dirname "$sd_res"`" +sd_prog=`pwd` +cd "$sd_cwd" + +# this is a temporary hack until we can live with the default search paths +case "`uname -s`" in +NetBSD|OpenBSD|FreeBSD|DragonFly) + sd_prog1="$sd_prog/../basis-link/program" + sd_prog2="$sd_prog/../basis-link/ure-link/lib" + LD_LIBRARY_PATH=$sd_prog1:$sd_prog2${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} + JAVA_HOME=$(javaPathHelper -h libreoffice-java 2> /dev/null) + export LD_LIBRARY_PATH + if [ -n "${JAVA_HOME}" ]; then + export JAVA_HOME + fi + ;; +AIX) + sd_prog1="$sd_prog/../basis-link/program" + sd_prog2="$sd_prog/../basis-link/ure-link/lib" + LIBPATH=$sd_prog1:$sd_prog2${LIBPATH:+:${LIBPATH}} + export LIBPATH + ;; +esac + +#collect all bootstrap variables specified on the command line +#so that they can be passed as arguments to javaldx later on +#Recognize the "sync" option. sync must be applied without any other +#options except bootstrap variables or the verbose option +for arg in $@ +do + case "$arg" in + -env:*) BOOTSTRAPVARS=$BOOTSTRAPVARS" ""$arg";; + sync) OPTSYNC=true;; + -v) VERBOSE=true;; + --verbose) VERBOSE=true;; + *) OPTOTHER=$arg;; + esac +done + +if [ "$OPTSYNC" = "true" ] && [ -z "$OPTOTHER" ] +then + JVMFWKPARAMS='-env:UNO_JAVA_JFW_INSTALL_DATA=$OOO_BASE_DIR/share/config/javasettingsunopkginstall.xml -env:JFW_PLUGIN_DO_NOT_CHECK_ACCESSIBILITY=1' +fi + +# extend the ld_library_path for java: javaldx checks the sofficerc for us +if [ -x "$sd_prog/../basis-link/ure-link/bin/javaldx" ] ; then + my_path=`"$sd_prog/../basis-link/ure-link/bin/javaldx" $BOOTSTRAPVARS $JVMFWKPARAMS \ + "-env:INIFILENAME=vnd.sun.star.pathname:$sd_prog/redirectrc"` + if [ -n "$my_path" ] ; then + sd_platform=`uname -s` + case $sd_platform in + AIX) + LIBPATH=$my_path${LIBPATH:+:$LIBPATH} + export LIBPATH + ;; + *) + LD_LIBRARY_PATH=$my_path${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} + export LD_LIBRARY_PATH + ;; + esac + fi +fi + +unset XENVIRONMENT + +# uncomment line below to disable anti aliasing of fonts +# SAL_ANTIALIAS_DISABLE=true; export SAL_ANTIALIAS_DISABLE + +# uncomment line below if you encounter problems starting soffice on your system +# SAL_NO_XINITTHREADS=true; export SAL_NO_XINITTHREADS + +# execute binary +exec "$sd_prog/unopkg.bin" "$@" "$JVMFWKPARAMS" \ + "-env:INIFILENAME=vnd.sun.star.pathname:$sd_prog/redirectrc" + diff --git a/desktop/scripts/ure-link b/desktop/scripts/ure-link new file mode 100755 index 000000000000..dd0ecb6115e8 --- /dev/null +++ b/desktop/scripts/ure-link @@ -0,0 +1 @@ +..\URE
\ No newline at end of file diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx new file mode 100644 index 000000000000..786ca4d1a511 --- /dev/null +++ b/desktop/source/app/app.cxx @@ -0,0 +1,3311 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <cstdlib> +#include <vector> + +#include <memory> +#include <unistd.h> +#include "app.hxx" +#include "desktop.hrc" +#include "appinit.hxx" +#include "officeipcthread.hxx" +#include "cmdlineargs.hxx" +#include "desktopresid.hxx" +#include "dispatchwatcher.hxx" +#include "configinit.hxx" +#include "lockfile.hxx" +#include "cmdlinehelp.hxx" +#include "userinstall.hxx" +#include "desktopcontext.hxx" +#include "exithelper.hxx" +#include "migration.hxx" + +#include <svtools/javacontext.hxx> +#include <com/sun/star/frame/XSessionManagerListener.hpp> +#include <com/sun/star/frame/XSynchronousDispatch.hpp> +#include <com/sun/star/document/CorruptedFilterConfigurationException.hpp> +#include <com/sun/star/configuration/CorruptedConfigurationException.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/util/XFlushable.hpp> +#include <com/sun/star/system/XSystemShellExecute.hpp> +#include <com/sun/star/system/SystemShellExecuteFlags.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/view/XPrintable.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/configuration/MissingBootstrapFileException.hpp> +#include <com/sun/star/configuration/InvalidBootstrapFileException.hpp> +#include <com/sun/star/configuration/InstallationIncompleteException.hpp> +#include <com/sun/star/configuration/backend/BackendSetupException.hpp> +#include <com/sun/star/configuration/backend/BackendAccessException.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/task/XJobExecutor.hpp> +#include <com/sun/star/task/XRestartManager.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/ui/XUIElementFactoryRegistration.hpp> +#include <com/sun/star/frame/XUIControllerRegistration.hpp> + +#include <com/sun/star/java/XJavaVM.hpp> +#include <tools/testtoolloader.hxx> +#include <tools/solar.h> +#include <toolkit/unohlp.hxx> +#include <osl/security.hxx> +#include <rtl/ref.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/configurationhelper.hxx> +#include <unotools/configmgr.hxx> +#include <unotools/configitem.hxx> +#include <unotools/confignode.hxx> +#include <unotools/ucbhelper.hxx> +#include <tools/tempfile.hxx> +#include <tools/urlobj.hxx> +#include <unotools/moduleoptions.hxx> +#include <osl/module.h> +#include <osl/file.hxx> +#include <osl/process.h> +#include <osl/signal.h> +#include <osl/thread.hxx> +#include <rtl/uuid.h> +#include <rtl/uri.hxx> +#include <unotools/pathoptions.hxx> +#include <svl/languageoptions.hxx> +#include <unotools/internaloptions.hxx> +#include <svtools/miscopt.hxx> +#include <svtools/menuoptions.hxx> +#include <unotools/syslocaleoptions.hxx> +#include <unotools/syslocale.hxx> +#include <svl/folderrestriction.hxx> +#include <unotools/tempfile.hxx> +#include <rtl/logfile.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/instance.hxx> +#include <unotools/configmgr.hxx> +#include <vcl/help.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/msgbox.hxx> +#include <sfx2/sfx.hrc> +#include <sfx2/app.hxx> +#include <svl/itemset.hxx> +#include <svl/eitem.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <unotools/bootstrap.hxx> +#include <cppuhelper/bootstrap.hxx> + +#include <svtools/fontsubstconfig.hxx> +#include <svtools/accessibilityoptions.hxx> +#include <svtools/apearcfg.hxx> +#include <unotools/misccfg.hxx> +#include <svtools/filter.hxx> +#include <unotools/regoptions.hxx> + +#include "langselect.hxx" + +#if defined MACOSX +#include <errno.h> +#include <sys/wait.h> +#endif + +#define DEFINE_CONST_UNICODE(CONSTASCII) UniString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII)) +#define U2S(STRING) ::rtl::OUStringToOString(STRING, RTL_TEXTENCODING_UTF8) + +using rtl::OUString; +using rtl::OUStringBuffer; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::view; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::system; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::container; + +namespace css = ::com::sun::star; + +ResMgr* desktop::Desktop::pResMgr = 0; + +namespace desktop +{ + +static oslSignalHandler pSignalHandler = 0; +static sal_Bool _bCrashReporterEnabled = sal_True; + +static ::rtl::OUString getBrandSharePreregBundledPathURL(); +// ---------------------------------------------------------------------------- + +ResMgr* Desktop::GetDesktopResManager() +{ + if ( !Desktop::pResMgr ) + { + // Create desktop resource manager and bootstrap process + // was successful. Use default way to get language specific message. + if ( Application::IsInExecute() ) + Desktop::pResMgr = ResMgr::CreateResMgr("dkt"); + + if ( !Desktop::pResMgr ) + { + // Use VCL to get the correct language specific message as we + // are in the bootstrap process and not able to get the installed + // language!! + OUString aUILocaleString = LanguageSelection::getLanguageString(); + sal_Int32 nIndex = 0; + OUString aLanguage = aUILocaleString.getToken( 0, '-', nIndex); + OUString aCountry = aUILocaleString.getToken( 0, '-', nIndex); + OUString aVariant = aUILocaleString.getToken( 0, '-', nIndex); + + ::com::sun::star::lang::Locale aLocale( aLanguage, aCountry, aVariant ); + + Desktop::pResMgr = ResMgr::SearchCreateResMgr( "dkt", aLocale); + AllSettings as = GetSettings(); + as.SetUILocale(aLocale); + SetSettings(as); + } + } + + return Desktop::pResMgr; +} + +// ---------------------------------------------------------------------------- +// Get a message string securely. There is a fallback string if the resource +// is not available. + +OUString Desktop::GetMsgString( sal_uInt16 nId, const OUString& aFaultBackMsg ) +{ + ResMgr* resMgr = GetDesktopResManager(); + if ( !resMgr ) + return aFaultBackMsg; + else + return OUString( String( ResId( nId, *resMgr ))); +} + +OUString MakeStartupErrorMessage(OUString const & aErrorMessage) +{ + OUStringBuffer aDiagnosticMessage( 100 ); + + ResMgr* pResMgr = Desktop::GetDesktopResManager(); + if ( pResMgr ) + aDiagnosticMessage.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CANNOT_START, *pResMgr))) ); + else + aDiagnosticMessage.appendAscii( "The program cannot be started." ); + + aDiagnosticMessage.appendAscii( "\n" ); + + aDiagnosticMessage.append( aErrorMessage ); + + return aDiagnosticMessage.makeStringAndClear(); +} + +OUString MakeStartupConfigAccessErrorMessage( OUString const & aInternalErrMsg ) +{ + OUStringBuffer aDiagnosticMessage( 200 ); + + ResMgr* pResMgr = Desktop::GetDesktopResManager(); + if ( pResMgr ) + aDiagnosticMessage.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CFG_DATAACCESS, *pResMgr ))) ); + else + aDiagnosticMessage.appendAscii( "The program cannot be started." ); + + if ( aInternalErrMsg.getLength() > 0 ) + { + aDiagnosticMessage.appendAscii( "\n\n" ); + if ( pResMgr ) + aDiagnosticMessage.append( OUString(String(ResId(STR_INTERNAL_ERRMSG, *pResMgr ))) ); + else + aDiagnosticMessage.appendAscii( "The following internal error has occurred:\n\n" ); + aDiagnosticMessage.append( aInternalErrMsg ); + } + + return aDiagnosticMessage.makeStringAndClear(); +} + +//============================================================================= +// shows a simple error box with the given message ... but exits from these process ! +// Fatal errors cant be solved by the process ... nor any recovery can help. +// Mostly the installation was damaged and must be repaired manually .. or by calling +// setup again. +// On the other side we must make sure that no further actions will be possible within +// the current office process ! No pipe requests, no menu/toolbar/shortuct actions +// are allowed. Otherwise we will force a "crash inside a crash". +// Thats why we have to use a special native message box here which does not use yield :-) +//============================================================================= +void FatalError(const ::rtl::OUString& sMessage) +{ + ::rtl::OUString sProductKey = ::utl::Bootstrap::getProductKey(); + if ( ! sProductKey.getLength()) + { + osl_getExecutableFile( &sProductKey.pData ); + + ::sal_uInt32 nLastIndex = sProductKey.lastIndexOf('/'); + if ( nLastIndex > 0 ) + sProductKey = sProductKey.copy( nLastIndex+1 ); + } + + ::rtl::OUStringBuffer sTitle (128); + sTitle.append (sProductKey ); + sTitle.appendAscii (" - Fatal Error"); + + Application::ShowNativeErrorBox (sTitle.makeStringAndClear (), sMessage); + _exit(ExitHelper::E_FATAL_ERROR); +} + +static bool ShouldSuppressUI(const CommandLineArgs& rCmdLine) +{ + return rCmdLine.IsInvisible() || + rCmdLine.IsHeadless() || + rCmdLine.IsQuickstart(); +} + +namespace +{ + struct theCommandLineArgs : public rtl::Static< CommandLineArgs, theCommandLineArgs > {}; +} + +CommandLineArgs& Desktop::GetCommandLineArgs() +{ + return theCommandLineArgs::get(); +} + +sal_Bool InitConfiguration() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (jb99855) ::InitConfiguration" ); + + Reference< XMultiServiceFactory > xProvider( CreateApplicationConfigurationProvider( ) ); + return xProvider.is(); +} + +namespace +{ + struct BrandName + : public rtl::Static< String, BrandName > {}; + struct Version + : public rtl::Static< String, Version > {}; + struct AboutBoxVersion + : public rtl::Static< String, AboutBoxVersion > {}; + struct OOOVendor + : public rtl::Static< String, OOOVendor > {}; + struct Extension + : public rtl::Static< String, Extension > {}; + struct XMLFileFormatName + : public rtl::Static< String, XMLFileFormatName > {}; + struct XMLFileFormatVersion + : public rtl::Static< String, XMLFileFormatVersion > {}; + struct WriterCompatibilityVersionOOo11 + : public rtl::Static< String, WriterCompatibilityVersionOOo11 > {}; +} + +void ReplaceStringHookProc( UniString& rStr ) +{ + static int nAll = 0, nPro = 0; + + nAll++; + if ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND ) + { + String &rBrandName = BrandName::get(); + String &rVersion = Version::get(); + String &rAboutBoxVersion = AboutBoxVersion::get(); + String &rExtension = Extension::get(); + String &rXMLFileFormatName = XMLFileFormatName::get(); + String &rXMLFileFormatVersion = XMLFileFormatVersion::get(); + + if ( !rBrandName.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ); + aRet >>= aTmp; + rBrandName = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTXMLFILEFORMATNAME ); + aRet >>= aTmp; + rXMLFileFormatName = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTXMLFILEFORMATVERSION ); + aRet >>= aTmp; + rXMLFileFormatVersion = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTVERSION ); + aRet >>= aTmp; + rVersion = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::ABOUTBOXPRODUCTVERSION ); + aRet >>= aTmp; + rAboutBoxVersion = aTmp; + + if ( !rExtension.Len() ) + { + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTEXTENSION ); + aRet >>= aTmp; + rExtension = aTmp; + } + } + + nPro++; + rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", rBrandName ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTVERSION", rVersion ); + rStr.SearchAndReplaceAllAscii( "%ABOUTBOXPRODUCTVERSION", rAboutBoxVersion ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTEXTENSION", rExtension ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATNAME", rXMLFileFormatName ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATVERSION", rXMLFileFormatVersion ); + } + if ( rStr.SearchAscii( "%OOOVENDOR" ) != STRING_NOTFOUND ) + { + String &rOOOVendor = OOOVendor::get(); + + if ( !rOOOVendor.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::OOOVENDOR ); + aRet >>= aTmp; + rOOOVendor = aTmp; + + } + rStr.SearchAndReplaceAllAscii( "%OOOVENDOR" ,rOOOVendor ); + } + + if ( rStr.SearchAscii( "%WRITERCOMPATIBILITYVERSIONOOO11" ) != STRING_NOTFOUND ) + { + String &rWriterCompatibilityVersionOOo11 = WriterCompatibilityVersionOOo11::get(); + if ( !rWriterCompatibilityVersionOOo11.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::WRITERCOMPATIBILITYVERSIONOOO11 ); + aRet >>= aTmp; + rWriterCompatibilityVersionOOo11 = aTmp; + } + + rStr.SearchAndReplaceAllAscii( "%WRITERCOMPATIBILITYVERSIONOOO11", + rWriterCompatibilityVersionOOo11 ); + } +} + +static const char pLastSyncFileName[] = "lastsynchronized"; +static const sal_Int32 nStrLenLastSync = 16; + +static bool needsSynchronization( + ::rtl::OUString const & baseSynchronizedURL, ::rtl::OUString const & userSynchronizedURL ) +{ + bool bNeedsSync( false ); + + ::osl::DirectoryItem itemUserFile; + ::osl::File::RC err1 = + ::osl::DirectoryItem::get(userSynchronizedURL, itemUserFile); + + //If it does not exist, then there is nothing to be done + if (err1 == ::osl::File::E_NOENT) + { + return true; + } + else if (err1 != ::osl::File::E_None) + { + OSL_FAIL("Cannot access lastsynchronized in user layer"); + return true; //sync just in case + } + + //If last synchronized does not exist in base layer, then do nothing + ::osl::DirectoryItem itemBaseFile; + ::osl::File::RC err2 = ::osl::DirectoryItem::get(baseSynchronizedURL, itemBaseFile); + if (err2 == ::osl::File::E_NOENT) + { + return true; + + } + else if (err2 != ::osl::File::E_None) + { + OSL_FAIL("Cannot access file lastsynchronized in base layer"); + return true; //sync just in case + } + + //compare the modification time of the extension folder and the last + //modified file + ::osl::FileStatus statUser(osl_FileStatus_Mask_ModifyTime); + ::osl::FileStatus statBase(osl_FileStatus_Mask_ModifyTime); + if (itemUserFile.getFileStatus(statUser) == ::osl::File::E_None) + { + if (itemBaseFile.getFileStatus(statBase) == ::osl::File::E_None) + { + TimeValue timeUser = statUser.getModifyTime(); + TimeValue timeBase = statBase.getModifyTime(); + + if (timeUser.Seconds < timeBase.Seconds) + bNeedsSync = true; + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + + return bNeedsSync; +} + +static ::rtl::OUString getBrandSharePreregBundledPathURL() +{ + ::rtl::OUString url( + RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/share/prereg/bundled")); + + ::rtl::Bootstrap::expandMacros(url); + return url; +} + +static ::rtl::OUString getUserBundledExtPathURL() +{ + ::rtl::OUString folder( RTL_CONSTASCII_USTRINGPARAM( "$BUNDLED_EXTENSIONS_USER" )); + ::rtl::Bootstrap::expandMacros(folder); + + return folder; +} + +static ::rtl::OUString getLastSyncFileURLFromBrandInstallation() +{ + ::rtl::OUString aURL = getBrandSharePreregBundledPathURL(); + ::sal_Int32 nLastIndex = aURL.lastIndexOf('/'); + + ::rtl::OUStringBuffer aTmp( aURL ); + + if ( nLastIndex != aURL.getLength()-1 ) + aTmp.appendAscii( "/" ); + aTmp.appendAscii( pLastSyncFileName ); + + return aTmp.makeStringAndClear(); +} + +static ::rtl::OUString getLastSyncFileURLFromUserInstallation() +{ + ::rtl::OUString aUserBundledPathURL = getUserBundledExtPathURL(); + ::sal_Int32 nLastIndex = aUserBundledPathURL.lastIndexOf('/'); + + ::rtl::OUStringBuffer aTmp( aUserBundledPathURL ); + + if ( nLastIndex != aUserBundledPathURL.getLength()-1 ) + aTmp.appendAscii( "/" ); + aTmp.appendAscii( pLastSyncFileName ); + + return aTmp.makeStringAndClear(); +} +//Checks if the argument src is the folder of the help or configuration +//backend in the prereg folder +static bool excludeTmpFilesAndFolders(const rtl::OUString & src) +{ + const char helpBackend[] = "com.sun.star.comp.deployment.help.PackageRegistryBackend"; + const char configBackend[] = "com.sun.star.comp.deployment.configuration.PackageRegistryBackend"; + if (src.endsWithAsciiL(helpBackend, sizeof(helpBackend) - 1 ) + || src.endsWithAsciiL(configBackend, sizeof(configBackend) - 1)) + { + return true; + } + return false; +} + +//If we are about to copy the contents of some special folder as determined +//by excludeTmpFilesAndFolders, then we omit those files or folders with a name +//derived from temporary folders. +static bool isExcludedFileOrFolder( const rtl::OUString & name) +{ + char const * allowed[] = { + "backenddb.xml", + "configmgr.ini", + "registered_packages.db" + }; + + const unsigned int size = sizeof(allowed) / sizeof (char const *); + bool bExclude = true; + for (unsigned int i= 0; i < size; i ++) + { + ::rtl::OUString allowedName = ::rtl::OUString::createFromAscii(allowed[i]); + if (allowedName.equals(name)) + { + bExclude = false; + break; + } + } + return bExclude; +} + +static osl::FileBase::RC copy_bundled_recursive( + const rtl::OUString& srcUnqPath, + const rtl::OUString& dstUnqPath, + sal_Int32 TypeToCopy ) +throw() +{ + osl::FileBase::RC err = osl::FileBase::E_None; + + if( TypeToCopy == -1 ) // Document + { + err = osl::File::copy( srcUnqPath,dstUnqPath ); + } + else if( TypeToCopy == +1 ) // Folder + { + err = osl::Directory::create( dstUnqPath ); + osl::FileBase::RC next = err; + if( err == osl::FileBase::E_None || err == osl::FileBase::E_EXIST ) + { + err = osl::FileBase::E_None; + + osl::Directory aDir( srcUnqPath ); + bool bExcludeFiles = excludeTmpFilesAndFolders(srcUnqPath); + if (aDir.open() == osl::FileBase::E_None) + { + sal_Int32 n_Mask = osl_FileStatus_Mask_FileURL | + osl_FileStatus_Mask_FileName | + osl_FileStatus_Mask_Type; + + osl::DirectoryItem aDirItem; + while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None ) + { + sal_Bool IsDoc = false; + sal_Bool bFilter = false; + osl::FileStatus aFileStatus( n_Mask ); + aDirItem.getFileStatus( aFileStatus ); + if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) ) + IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular; + + // Getting the information for the next recursive copy + sal_Int32 newTypeToCopy = IsDoc ? -1 : +1; + + rtl::OUString newSrcUnqPath; + if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) ) + newSrcUnqPath = aFileStatus.getFileURL(); + + rtl::OUString newDstUnqPath = dstUnqPath; + rtl::OUString tit; + if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) ) + { + ::rtl::OUString aFileName = aFileStatus.getFileName(); + tit = rtl::Uri::encode( aFileName, + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + + // Special treatment for "lastsychronized" file. Must not be + // copied from the bundled folder! + //Also do not copy *.tmp files and *.tmp_ folders. This affects the files/folders + //from the help and configuration backend + if ( IsDoc && (aFileName.equalsAscii( pLastSyncFileName ) + || (bExcludeFiles && isExcludedFileOrFolder(aFileName)))) + bFilter = true; + else if (!IsDoc && bExcludeFiles && isExcludedFileOrFolder(aFileName)) + bFilter = true; + } + + if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 ) + newDstUnqPath += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")); + + newDstUnqPath += tit; + + if (( newSrcUnqPath != dstUnqPath ) && !bFilter ) + err = copy_bundled_recursive( newSrcUnqPath,newDstUnqPath, newTypeToCopy ); + } + + if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT ) + err = next; + + aDir.close(); + } + } + } + + return err; +} + +Desktop::Desktop() +: m_bServicesRegistered( false ) +, m_aBootstrapError( BE_OK ) +, m_pLockfile( NULL ) +{ + RTL_LOGFILE_TRACE( "desktop (cd100003) ::Desktop::Desktop" ); +} + +Desktop::~Desktop() +{ +} + +void Desktop::Init() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Init" ); + SetBootstrapStatus(BS_OK); + + // Check for lastsynchronized file for bundled extensions in the user directory + // and test if synchronzation is necessary! + { + ::rtl::OUString aUserLastSyncFilePathURL = getLastSyncFileURLFromUserInstallation(); + ::rtl::OUString aPreregSyncFilePathURL = getLastSyncFileURLFromBrandInstallation(); + + if ( needsSynchronization( aPreregSyncFilePathURL, aUserLastSyncFilePathURL )) + { + rtl::OUString aUserPath = getUserBundledExtPathURL(); + rtl::OUString aPreregBundledPath = getBrandSharePreregBundledPathURL(); + + // copy bundled folder to the user directory + osl::FileBase::RC rc = osl::Directory::createPath(aUserPath); + (void) rc; + copy_bundled_recursive( aPreregBundledPath, aUserPath, +1 ); + } + } + + // We need to have service factory before going further. + if( !::comphelper::getProcessServiceFactory().is()) + { + OSL_FAIL("Service factory should have been crated in soffice_main()."); + SetBootstrapError( BE_UNO_SERVICEMANAGER ); + } + + if ( GetBootstrapError() == BE_OK ) + { + // prepare language + if ( !LanguageSelection::prepareLanguage() ) + { + if ( LanguageSelection::getStatus() == LanguageSelection::LS_STATUS_CANNOT_DETERMINE_LANGUAGE ) + SetBootstrapError( BE_LANGUAGE_MISSING ); + else + SetBootstrapError( BE_OFFICECONFIG_BROKEN ); + } + } + + if ( GetBootstrapError() == BE_OK ) + { + const CommandLineArgs& rCmdLineArgs = GetCommandLineArgs(); + // start ipc thread only for non-remote offices + RTL_LOGFILE_CONTEXT( aLog2, "desktop (cd100003) ::OfficeIPCThread::EnableOfficeIPCThread" ); + OfficeIPCThread::Status aStatus = OfficeIPCThread::EnableOfficeIPCThread(); + if ( aStatus == OfficeIPCThread::IPC_STATUS_BOOTSTRAP_ERROR ) + { + SetBootstrapError( BE_PATHINFO_MISSING ); + } + else if ( aStatus == OfficeIPCThread::IPC_STATUS_2ND_OFFICE ) + { + // 2nd office startup should terminate after sending cmdlineargs through pipe + SetBootstrapStatus(BS_TERMINATE); + } + else if ( rCmdLineArgs.IsHelp() ) + { + // disable IPC thread in an instance that is just showing a help message + OfficeIPCThread::DisableOfficeIPCThread(); + } + pSignalHandler = osl_addSignalHandler(SalMainPipeExchangeSignal_impl, NULL); + } +} + +void Desktop::InitFinished() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::InitFinished" ); + + CloseSplashScreen(); +} + +// GetCommandLineArgs() requires this code to work, otherwise it will abort, and +// on Unix command line args needs to be checked before Desktop::Init() +void Desktop::CreateProcessServiceFactory() +{ + Reference < XMultiServiceFactory > rSMgr = CreateApplicationServiceManager(); + if( rSMgr.is() ) + { + ::comphelper::setProcessServiceFactory( rSMgr ); + } +} + +void Desktop::DeInit() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::DeInit" ); + + try { + // instead of removing of the configManager just let it commit all the changes + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + utl::ConfigManager::GetConfigManager().StoreConfigItems(); + FlushConfiguration(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + + // close splashscreen if it's still open + CloseSplashScreen(); + Reference<XMultiServiceFactory> xXMultiServiceFactory(::comphelper::getProcessServiceFactory()); + DestroyApplicationServiceManager( xXMultiServiceFactory ); + // nobody should get a destroyd service factory... + ::comphelper::setProcessServiceFactory( NULL ); + + // clear lockfile + if (m_pLockfile != NULL) + { + delete m_pLockfile; + m_pLockfile = NULL; + } + + OfficeIPCThread::DisableOfficeIPCThread(); + if( pSignalHandler ) + osl_removeSignalHandler( pSignalHandler ); + } catch (RuntimeException&) { + // someone threw an exception during shutdown + // this will leave some garbage behind.. + } + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "FINISHED WITH Destop::DeInit" ); +} + +sal_Bool Desktop::QueryExit() +{ + try + { + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + utl::ConfigManager::GetConfigManager().StoreConfigItems(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + } + catch ( RuntimeException& ) + { + } + + const sal_Char SUSPEND_QUICKSTARTVETO[] = "SuspendQuickstartVeto"; + + Reference< ::com::sun::star::frame::XDesktop > + xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + UNO_QUERY ); + + Reference < ::com::sun::star::beans::XPropertySet > xPropertySet( xDesktop, UNO_QUERY ); + if ( xPropertySet.is() ) + { + Any a; + a <<= (sal_Bool)sal_True; + xPropertySet->setPropertyValue( OUSTRING(RTL_CONSTASCII_USTRINGPARAM( SUSPEND_QUICKSTARTVETO )), a ); + } + + sal_Bool bExit = ( !xDesktop.is() || xDesktop->terminate() ); + + + if ( !bExit && xPropertySet.is() ) + { + Any a; + a <<= (sal_Bool)sal_False; + xPropertySet->setPropertyValue( OUSTRING(RTL_CONSTASCII_USTRINGPARAM( SUSPEND_QUICKSTARTVETO )), a ); + } + else + { + FlushConfiguration(); + try + { + // it is no problem to call DisableOfficeIPCThread() more than once + // it also looks to be threadsafe + OfficeIPCThread::DisableOfficeIPCThread(); + } + catch ( RuntimeException& ) + { + } + + if (m_pLockfile != NULL) + { + delete m_pLockfile; + m_pLockfile = NULL; + } + + } + + return bExit; +} + +void Desktop::HandleBootstrapPathErrors( ::utl::Bootstrap::Status aBootstrapStatus, const OUString& aDiagnosticMessage ) +{ + if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK ) + { + ::rtl::OUString aProductKey; + ::rtl::OUString aTemp; + + osl_getExecutableFile( &aProductKey.pData ); + sal_uInt32 lastIndex = aProductKey.lastIndexOf('/'); + if ( lastIndex > 0 ) + aProductKey = aProductKey.copy( lastIndex+1 ); + + aTemp = ::utl::Bootstrap::getProductKey( aProductKey ); + if ( aTemp.getLength() > 0 ) + aProductKey = aTemp; + + OUString aMessage; + OUStringBuffer aBuffer( 100 ); + aBuffer.append( aDiagnosticMessage ); + + aBuffer.appendAscii( "\n" ); + + ErrorBox aBootstrapFailedBox( NULL, WB_OK, aMessage ); + aBootstrapFailedBox.SetText( aProductKey ); + aBootstrapFailedBox.Execute(); + } +} + +// Create a error message depending on bootstrap failure code and an optional file url +::rtl::OUString Desktop::CreateErrorMsgString( + utl::Bootstrap::FailureCode nFailureCode, + const ::rtl::OUString& aFileURL ) +{ + OUString aMsg; + OUString aFilePath; + sal_Bool bFileInfo = sal_True; + + switch ( nFailureCode ) + { + /// the shared installation directory could not be located + case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_PATH_INVALID, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The installation path is not available." )) ); + bFileInfo = sal_False; + } + break; + + /// the bootstrap INI file could not be found or read + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is missing." )) ); + } + break; + + /// the bootstrap INI is missing a required entry + /// the bootstrap INI contains invalid data + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY: + case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_CORRUPT, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is corrupt." )) ); + } + break; + + /// the version locator INI file could not be found or read + case ::utl::Bootstrap::MISSING_VERSION_FILE: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is missing." )) ); + } + break; + + /// the version locator INI has no entry for this version + case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SUPPORT, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The main configuration file \"$1\" does not support the current version." )) ); + } + break; + + /// the user installation directory does not exist + case ::utl::Bootstrap::MISSING_USER_DIRECTORY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_DIR_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration directory \"$1\" is missing." )) ); + } + break; + + /// some bootstrap data was invalid in unexpected ways + case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL, + OUString( RTL_CONSTASCII_USTRINGPARAM( "An internal failure occurred." )) ); + bFileInfo = sal_False; + } + break; + + case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY: + { + // This needs to be improved, see #i67575#: + aMsg = OUString( + RTL_CONSTASCII_USTRINGPARAM( "Invalid version file entry" ) ); + bFileInfo = sal_False; + } + break; + + case ::utl::Bootstrap::NO_FAILURE: + { + OSL_ASSERT(false); + } + break; + } + + if ( bFileInfo ) + { + String aMsgString( aMsg ); + + osl::File::getSystemPathFromFileURL( aFileURL, aFilePath ); + + aMsgString.SearchAndReplaceAscii( "$1", aFilePath ); + aMsg = aMsgString; + } + + return MakeStartupErrorMessage( aMsg ); +} + +void Desktop::HandleBootstrapErrors( BootstrapError aBootstrapError ) +{ + if ( aBootstrapError == BE_PATHINFO_MISSING ) + { + OUString aErrorMsg; + OUString aBuffer; + utl::Bootstrap::Status aBootstrapStatus; + utl::Bootstrap::FailureCode nFailureCode; + + aBootstrapStatus = ::utl::Bootstrap::checkBootstrapStatus( aBuffer, nFailureCode ); + if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK ) + { + switch ( nFailureCode ) + { + case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY: + case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA: + { + aErrorMsg = CreateErrorMsgString( nFailureCode, OUString() ); + } + break; + + /// the bootstrap INI file could not be found or read + /// the bootstrap INI is missing a required entry + /// the bootstrap INI contains invalid data + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY: + case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY: + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE: + { + OUString aBootstrapFileURL; + + utl::Bootstrap::locateBootstrapFile( aBootstrapFileURL ); + aErrorMsg = CreateErrorMsgString( nFailureCode, aBootstrapFileURL ); + } + break; + + /// the version locator INI file could not be found or read + /// the version locator INI has no entry for this version + /// the version locator INI entry is not a valid directory URL + case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY: + case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY: + case ::utl::Bootstrap::MISSING_VERSION_FILE: + { + OUString aVersionFileURL; + + utl::Bootstrap::locateVersionFile( aVersionFileURL ); + aErrorMsg = CreateErrorMsgString( nFailureCode, aVersionFileURL ); + } + break; + + /// the user installation directory does not exist + case ::utl::Bootstrap::MISSING_USER_DIRECTORY: + { + OUString aUserInstallationURL; + + utl::Bootstrap::locateUserInstallation( aUserInstallationURL ); + aErrorMsg = CreateErrorMsgString( nFailureCode, aUserInstallationURL ); + } + break; + + case ::utl::Bootstrap::NO_FAILURE: + { + OSL_ASSERT(false); + } + break; + } + + HandleBootstrapPathErrors( aBootstrapStatus, aErrorMsg ); + } + } + else if ( aBootstrapError == BE_UNO_SERVICEMANAGER || aBootstrapError == BE_UNO_SERVICE_CONFIG_MISSING ) + { + // Uno service manager is not available. VCL needs a uno service manager to display a message box!!! + // Currently we are not able to display a message box with a service manager due to this limitations inside VCL. + + // When UNO is not properly initialized, all kinds of things can fail + // and cause the process to crash (e.g., a call to GetMsgString may + // crash when somewhere deep within that call Any::operator <= is used + // with a PropertyValue, and no binary UNO type description for + // PropertyValue is available). To give the user a hint even if + // generating and displaying a message box below crashes, print a + // hard-coded message on stderr first: + fputs( + aBootstrapError == BE_UNO_SERVICEMANAGER + ? ("The application cannot be started. " "\n" + "The component manager is not available." "\n") + // STR_BOOTSTRAP_ERR_CANNOT_START, STR_BOOTSTRAP_ERR_NO_SERVICE + : ("The application cannot be started. " "\n" + "The configuration service is not available." "\n"), + // STR_BOOTSTRAP_ERR_CANNOT_START, + // STR_BOOTSTRAP_ERR_NO_CFG_SERVICE + stderr); + + // First sentence. We cannot bootstrap office further! + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + + OUString aErrorMsg; + + if ( aBootstrapError == BE_UNO_SERVICEMANAGER ) + aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SERVICE, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The service manager is not available." )) ); + else + aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_CFG_SERVICE, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration service is not available." )) ); + + aDiagnosticMessage.append( aErrorMsg ); + aDiagnosticMessage.appendAscii( "\n" ); + + // Due to the fact the we haven't a backup applicat.rdb file anymore it is not possible to + // repair the installation with the setup executable besides the office executable. Now + // we have to ask the user to start the setup on CD/installation directory manually!! + OUString aStartSetupManually( GetMsgString( + STR_ASK_START_SETUP_MANUALLY, + OUString( RTL_CONSTASCII_USTRINGPARAM( "Start setup application to repair the installation from CD, or the folder containing the installation packages." )) )); + + aDiagnosticMessage.append( aStartSetupManually ); + aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() ); + + FatalError( aMessage); + } + else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN ) + { + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + OUString aErrorMsg; + aErrorMsg = GetMsgString( STR_CONFIG_ERR_ACCESS_GENERAL, + OUString( RTL_CONSTASCII_USTRINGPARAM( "A general error occurred while accessing your central configuration." )) ); + aDiagnosticMessage.append( aErrorMsg ); + aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + else if ( aBootstrapError == BE_USERINSTALL_FAILED ) + { + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + OUString aErrorMsg; + aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL, + OUString( RTL_CONSTASCII_USTRINGPARAM( "User installation could not be completed" )) ); + aDiagnosticMessage.append( aErrorMsg ); + aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + else if ( aBootstrapError == BE_LANGUAGE_MISSING ) + { + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + OUString aErrorMsg; + aErrorMsg = GetMsgString( + //@@@ FIXME: should use an own resource string => #i36213# + STR_BOOTSTRAP_ERR_LANGUAGE_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( + "Language could not be determined." )) ); + aDiagnosticMessage.append( aErrorMsg ); + aMessage = MakeStartupErrorMessage( + aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + else if (( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE ) || + ( aBootstrapError == BE_USERINSTALL_NOWRITEACCESS )) + { + OUString aUserInstallationURL; + OUString aUserInstallationPath; + OUString aMessage; + OUString aErrorMsg; + OUStringBuffer aDiagnosticMessage( 100 ); + + utl::Bootstrap::locateUserInstallation( aUserInstallationURL ); + + if ( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE ) + aErrorMsg = GetMsgString( + STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE, + OUString( RTL_CONSTASCII_USTRINGPARAM( + "User installation could not be completed due to insufficient free disk space." )) ); + else + aErrorMsg = GetMsgString( + STR_BOOSTRAP_ERR_NOACCESSRIGHTS, + OUString( RTL_CONSTASCII_USTRINGPARAM( + "User installation could not be processed due to missing access rights." )) ); + + osl::File::getSystemPathFromFileURL( aUserInstallationURL, aUserInstallationPath ); + + aDiagnosticMessage.append( aErrorMsg ); + aDiagnosticMessage.append( aUserInstallationPath ); + aMessage = MakeStartupErrorMessage( + aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + + return; +} + + +void Desktop::retrieveCrashReporterState() +{ + static const ::rtl::OUString CFG_PACKAGE_RECOVERY(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Recovery/")); + static const ::rtl::OUString CFG_PATH_CRASHREPORTER(RTL_CONSTASCII_USTRINGPARAM("CrashReporter")); + static const ::rtl::OUString CFG_ENTRY_ENABLED(RTL_CONSTASCII_USTRINGPARAM("Enabled")); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + sal_Bool bEnabled(sal_False); + if ( xSMGR.is() ) + { + css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey( + xSMGR, + CFG_PACKAGE_RECOVERY, + CFG_PATH_CRASHREPORTER, + CFG_ENTRY_ENABLED, + ::comphelper::ConfigurationHelper::E_READONLY); + aVal >>= bEnabled; + } + _bCrashReporterEnabled = bEnabled; +} + +sal_Bool Desktop::isUIOnSessionShutdownAllowed() +{ + static const ::rtl::OUString CFG_PACKAGE_RECOVERY(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Recovery/")); + static const ::rtl::OUString CFG_PATH_SESSION(RTL_CONSTASCII_USTRINGPARAM("SessionShutdown")); + static const ::rtl::OUString CFG_ENTRY_UIENABLED(RTL_CONSTASCII_USTRINGPARAM("DocumentStoreUIEnabled")); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + sal_Bool bResult = sal_False; + if ( xSMGR.is() ) + { + css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey( + xSMGR, + CFG_PACKAGE_RECOVERY, + CFG_PATH_SESSION, + CFG_ENTRY_UIENABLED, + ::comphelper::ConfigurationHelper::E_READONLY); + aVal >>= bResult; + } + + return bResult; +} + +//----------------------------------------------- +/** @short check if crash reporter feature is enabled or + disabled. +*/ +sal_Bool Desktop::isCrashReporterEnabled() +{ + return _bCrashReporterEnabled; +} + +//----------------------------------------------- +/** @short check if recovery must be started or not. + + @param bCrashed [boolean ... out!] + the office crashed last times. + But may be there are no recovery data. + Usefull to trigger the error report tool without + showing the recovery UI. + + @param bRecoveryDataExists [boolean ... out!] + there exists some recovery data. + + @param bSessionDataExists [boolean ... out!] + there exists some session data. + Because the user may be logged out last time from it's + unix session... +*/ +void impl_checkRecoveryState(sal_Bool& bCrashed , + sal_Bool& bRecoveryDataExists, + sal_Bool& bSessionDataExists ) +{ + static const ::rtl::OUString SERVICENAME_RECOVERYCORE(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.AutoRecovery")); + static const ::rtl::OUString PROP_CRASHED(RTL_CONSTASCII_USTRINGPARAM("Crashed")); + static const ::rtl::OUString PROP_EXISTSRECOVERY(RTL_CONSTASCII_USTRINGPARAM("ExistsRecoveryData")); + static const ::rtl::OUString PROP_EXISTSSESSION(RTL_CONSTASCII_USTRINGPARAM("ExistsSessionData")); + + bCrashed = sal_False; + bRecoveryDataExists = sal_False; + bSessionDataExists = sal_False; + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + try + { + css::uno::Reference< css::beans::XPropertySet > xRecovery( + xSMGR->createInstance(SERVICENAME_RECOVERYCORE), + css::uno::UNO_QUERY_THROW); + + xRecovery->getPropertyValue(PROP_CRASHED ) >>= bCrashed ; + xRecovery->getPropertyValue(PROP_EXISTSRECOVERY) >>= bRecoveryDataExists; + xRecovery->getPropertyValue(PROP_EXISTSSESSION ) >>= bSessionDataExists ; + } + catch(const css::uno::Exception&) {} +} + +//----------------------------------------------- +/* @short start the recovery wizard. + + @param bEmergencySave + differs between EMERGENCY_SAVE and RECOVERY +*/ +sal_Bool impl_callRecoveryUI(sal_Bool bEmergencySave , + sal_Bool bCrashed , + sal_Bool bExistsRecoveryData) +{ + static ::rtl::OUString SERVICENAME_RECOVERYUI(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.svx.RecoveryUI")); + static ::rtl::OUString SERVICENAME_URLPARSER(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")); + static ::rtl::OUString COMMAND_EMERGENCYSAVE(RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.autorecovery:/doEmergencySave")); + static ::rtl::OUString COMMAND_RECOVERY(RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.autorecovery:/doAutoRecovery")); + static ::rtl::OUString COMMAND_CRASHREPORT(RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.autorecovery:/doCrashReport")); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + css::uno::Reference< css::frame::XSynchronousDispatch > xRecoveryUI( + xSMGR->createInstance(SERVICENAME_RECOVERYUI), + css::uno::UNO_QUERY_THROW); + + css::uno::Reference< css::util::XURLTransformer > xURLParser( + xSMGR->createInstance(SERVICENAME_URLPARSER), + css::uno::UNO_QUERY_THROW); + + css::util::URL aURL; + if (bEmergencySave) + aURL.Complete = COMMAND_EMERGENCYSAVE; + else + { + if (bExistsRecoveryData) + aURL.Complete = COMMAND_RECOVERY; + else + if (bCrashed && Desktop::isCrashReporterEnabled() ) + aURL.Complete = COMMAND_CRASHREPORT; + } + + sal_Bool bRet = sal_False; + if ( aURL.Complete.getLength() > 0 ) + { + xURLParser->parseStrict(aURL); + + css::uno::Any aRet = xRecoveryUI->dispatchWithReturnValue(aURL, css::uno::Sequence< css::beans::PropertyValue >()); + aRet >>= bRet; + } + return bRet; +} + +/* + * Save all open documents so they will be reopened + * the next time the application ist started + * + * returns sal_True if at least one document could be saved... + * + */ + +sal_Bool Desktop::_bTasksSaved = sal_False; + +sal_Bool Desktop::SaveTasks() +{ + return impl_callRecoveryUI( + sal_True , // sal_True => force emergency save + sal_False, // 2. and 3. param not used if 1. = true! + sal_False); +} + +namespace { + +void restartOnMac(bool passArguments) { +#if defined MACOSX + OfficeIPCThread::DisableOfficeIPCThread(); + rtl::OUString execUrl; + OSL_VERIFY(osl_getExecutableFile(&execUrl.pData) == osl_Process_E_None); + rtl::OUString execPath; + rtl::OString execPath8; + if ((osl::FileBase::getSystemPathFromFileURL(execUrl, execPath) + != osl::FileBase::E_None) || + !execPath.convertToString( + &execPath8, osl_getThreadTextEncoding(), + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + std::abort(); + } + std::vector< rtl::OString > args; + args.push_back(execPath8); + bool wait = false; + if (passArguments) { + sal_uInt32 n = osl_getCommandArgCount(); + for (sal_uInt32 i = 0; i < n; ++i) { + rtl::OUString arg; + OSL_VERIFY(osl_getCommandArg(i, &arg.pData) == osl_Process_E_None); + if (arg.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("-accept="))) { + wait = true; + } + rtl::OString arg8; + if (!arg.convertToString( + &arg8, osl_getThreadTextEncoding(), + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + std::abort(); + } + args.push_back(arg8); + } + } + std::vector< char const * > argPtrs; + for (std::vector< rtl::OString >::iterator i(args.begin()); i != args.end(); + ++i) + { + argPtrs.push_back(i->getStr()); + } + argPtrs.push_back(0); + execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0])); + if (errno == ENOTSUP) { // happens when multithreaded on OS X < 10.6 + pid_t pid = fork(); + if (pid == 0) { + execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0])); + } else if (pid > 0) { + // Two simultaneously running soffice processes lead to two dock + // icons, so avoid waiting here unless it must be assumed that the + // process invoking soffice itself wants to wait for soffice to + // finish: + if (!wait) { + return; + } + int stat; + if (waitpid(pid, &stat, 0) == pid && WIFEXITED(stat)) { + _exit(WEXITSTATUS(stat)); + } + } + } + std::abort(); +#else + (void) passArguments; // avoid warnings +#endif +} + +} + +sal_uInt16 Desktop::Exception(sal_uInt16 nError) +{ + // protect against recursive calls + static sal_Bool bInException = sal_False; + + sal_uInt16 nOldMode = Application::GetSystemWindowMode(); + Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE ); + Application::SetDefDialogParent( NULL ); + + if ( bInException ) + { + String aDoubleExceptionString; + Application::Abort( aDoubleExceptionString ); + } + + bInException = sal_True; + const CommandLineArgs& rArgs = GetCommandLineArgs(); + + // save all modified documents ... if it's allowed doing so. + sal_Bool bRestart = sal_False; + sal_Bool bAllowRecoveryAndSessionManagement = ( + ( !rArgs.IsNoRestore() ) && // some use cases of office must work without recovery + ( !rArgs.IsHeadless() ) && + ( !rArgs.IsServer() ) && + (( nError & EXC_MAJORTYPE ) != EXC_DISPLAY ) && // recovery cant work without UI ... but UI layer seams to be the reason for this crash + ( Application::IsInExecute() ) // crashes during startup and shutdown should be ignored (they indicates a corrupt installation ...) + ); + if ( bAllowRecoveryAndSessionManagement ) + bRestart = SaveTasks(); + + FlushConfiguration(); + + switch( nError & EXC_MAJORTYPE ) + { + case EXC_RSCNOTLOADED: + { + String aResExceptionString; + Application::Abort( aResExceptionString ); + break; + } + + case EXC_SYSOBJNOTCREATED: + { + String aSysResExceptionString; + Application::Abort( aSysResExceptionString ); + break; + } + + default: + { + if (m_pLockfile != NULL) + { + delete m_pLockfile; + m_pLockfile = NULL; + } + + if( bRestart ) + { + OfficeIPCThread::DisableOfficeIPCThread(); + if( pSignalHandler ) + osl_removeSignalHandler( pSignalHandler ); + + restartOnMac(false); + if ( m_rSplashScreen.is() ) + m_rSplashScreen->reset(); + + _exit( ExitHelper::E_CRASH_WITH_RESTART ); + } + else + { + Application::Abort( String() ); + } + + break; + } + } + + OSL_ASSERT(false); // unreachable + return 0; +} + +void Desktop::AppEvent( const ApplicationEvent& rAppEvent ) +{ + HandleAppEvent( rAppEvent ); +} + +namespace { + void SetDocumentExtendedStyle( const Reference< ::com::sun::star::awt::XWindow > &xContainerWindow ) + { + // set the WB_EXT_DOCUMENT style. Normally, this is done by the TaskCreator service when a "_blank" + // frame/window is created. Since we do not use the TaskCreator here, we need to mimic its behavior, + // otherwise documents loaded into this frame will later on miss functionality depending on the style. + Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow ); + OSL_ENSURE( pContainerWindow, "Desktop::Main: no implementation access to the frame's container window!" ); + if (!pContainerWindow) { + fprintf (stderr, "Error: It very much looks as if you have used 'linkoo' (or bin/ooinstall -l)\n" + "but have then forgotten to source 'ooenv' into your shell before running !\n" + "to save a crash, we will exit now with an error - please '. ./ooenv' first.\n"); + exit (1); + } + pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WB_EXT_DOCUMENT ); + } +} + +struct ExecuteGlobals +{ + Reference < css::document::XEventListener > xGlobalBroadcaster; + sal_Bool bRestartRequested; + sal_Bool bUseSystemFileDialog; + std::auto_ptr<SvtLanguageOptions> pLanguageOptions; + std::auto_ptr<SvtPathOptions> pPathOptions; + + ExecuteGlobals() + : bRestartRequested( sal_False ) + , bUseSystemFileDialog( sal_True ) + {} +}; + +static ExecuteGlobals* pExecGlobals = NULL; + +int Desktop::Main() +{ + pExecGlobals = new ExecuteGlobals(); + + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Main" ); + + // Remember current context object + com::sun::star::uno::ContextLayer layer( + com::sun::star::uno::getCurrentContext() ); + + BootstrapError eError = GetBootstrapError(); + if ( eError != BE_OK ) + { + HandleBootstrapErrors( eError ); + return EXIT_FAILURE; + } + + BootstrapStatus eStatus = GetBootstrapStatus(); + if (eStatus == BS_TERMINATE) { + return EXIT_FAILURE; + } + + // Detect desktop environment - need to do this as early as possible + com::sun::star::uno::setCurrentContext( + new DesktopContext( com::sun::star::uno::getCurrentContext() ) ); + + CommandLineArgs& rCmdLineArgs = GetCommandLineArgs(); + + // setup configuration error handling + ConfigurationErrorHandler aConfigErrHandler; + if (!ShouldSuppressUI(rCmdLineArgs)) + aConfigErrHandler.activate(); + + ResMgr::SetReadStringHook( ReplaceStringHookProc ); + + // Startup screen + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main { OpenSplashScreen" ); + OpenSplashScreen(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main } OpenSplashScreen" ); + + SetSplashScreenProgress(10); + { + UserInstall::UserInstallError instErr_fin = UserInstall::finalize(); + if ( instErr_fin != UserInstall::E_None) + { + OSL_FAIL("userinstall failed"); + if ( instErr_fin == UserInstall::E_NoDiskSpace ) + HandleBootstrapErrors( BE_USERINSTALL_NOTENOUGHDISKSPACE ); + else if ( instErr_fin == UserInstall::E_NoWriteAccess ) + HandleBootstrapErrors( BE_USERINSTALL_NOWRITEACCESS ); + else + HandleBootstrapErrors( BE_USERINSTALL_FAILED ); + return EXIT_FAILURE; + } + // refresh path information + utl::Bootstrap::reloadData(); + SetSplashScreenProgress(20); + } + + Reference< XMultiServiceFactory > xSMgr = + ::comphelper::getProcessServiceFactory(); + + Reference< XDesktop > xDesktop; + Reference< ::com::sun::star::task::XRestartManager > xRestartManager; + try + { + RegisterServices( xSMgr ); + + SetSplashScreenProgress(25); + +#ifndef UNX + if ( rCmdLineArgs.IsHelp() ) + { + displayCmdlineHelp(); + return EXIT_SUCCESS; + } +#endif + + // check user installation directory for lockfile so we can be sure + // there is no other instance using our data files from a remote host + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main -> Lockfile" ); + m_pLockfile = new Lockfile; + if ( !rCmdLineArgs.IsHeadless() && !rCmdLineArgs.IsInvisible() && + !rCmdLineArgs.IsNoLockcheck() && !m_pLockfile->check( Lockfile_execWarning )) + { + // Lockfile exists, and user clicked 'no' + return EXIT_FAILURE; + } + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main <- Lockfile" ); + + // check if accessibility is enabled but not working and allow to quit + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ GetEnableATToolSupport" ); + if( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() ) + { + sal_Bool bQuitApp; + + if( !InitAccessBridge( true, bQuitApp ) ) + if( bQuitApp ) + return EXIT_FAILURE; + } + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} GetEnableATToolSupport" ); + + // terminate if requested... + if( rCmdLineArgs.IsTerminateAfterInit() ) + return EXIT_SUCCESS; + + + // Read the common configuration items for optimization purpose + if ( !InitializeConfiguration() ) + return EXIT_FAILURE; + + SetSplashScreenProgress(30); + + // set static variable to enabled/disable crash reporter + retrieveCrashReporterState(); + if ( !isCrashReporterEnabled() ) + { + osl_setErrorReporting( sal_False ); + // disable stack trace feature + } + + // create title string + ::com::sun::star::lang::Locale aLocale; + String aMgrName = String::CreateFromAscii( "ofa" ); + ResMgr* pLabelResMgr = ResMgr::SearchCreateResMgr( "ofa", aLocale ); + String aTitle = pLabelResMgr ? String( ResId( RID_APPTITLE, *pLabelResMgr ) ) : String(); + delete pLabelResMgr; + +#ifdef DBG_UTIL + //include version ID in non product builds + ::rtl::OUString aDefault(RTL_CONSTASCII_USTRINGPARAM("development")); + aTitle += DEFINE_CONST_UNICODE(" ["); + String aVerId( utl::Bootstrap::getProductSource(aDefault)); + aTitle += aVerId; + aTitle += ']'; +#endif + + SetDisplayName( aTitle ); + SetSplashScreenProgress(35); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create SvtPathOptions and SvtLanguageOptions" ); + pExecGlobals->pPathOptions.reset( new SvtPathOptions); + SetSplashScreenProgress(40); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create SvtPathOptions and SvtLanguageOptions" ); + + // Check special env variable + std::vector< String > aUnrestrictedFolders; + svt::getUnrestrictedFolders( aUnrestrictedFolders ); + + if ( !aUnrestrictedFolders.empty() ) + { + // Set different working directory. The first entry is + // the new work path. + String aWorkPath = aUnrestrictedFolders[0]; + SvtPathOptions().SetWorkPath( aWorkPath ); + } + + xDesktop = Reference<XDesktop>( xSMgr->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))), UNO_QUERY ); + + // create service for loadin SFX (still needed in startup) + pExecGlobals->xGlobalBroadcaster = Reference < css::document::XEventListener > + ( xSMgr->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.frame.GlobalEventBroadcaster" ) ), UNO_QUERY ); + + /* ensure existance of a default window that messages can be dispatched to + This is for the benefit of testtool which uses PostUserEvent extensively + and else can deadlock while creating this window from another tread while + the main thread is not yet in the event loop. + */ + Application::GetDefaultDevice(); + + // initialize test-tool library (if available) + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ tools::InitTestToolLib" ); + tools::InitTestToolLib(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} tools::InitTestToolLib" ); + + // Check if bundled or shared extensions were added /removed + // and process those extensions (has to be done before checking + // the extension dependencies! + SynchronizeExtensionRepositories(); + bool bAbort = CheckExtensionDependencies(); + if ( bAbort ) + return EXIT_FAILURE; + + { + ::comphelper::ComponentContext aContext( xSMgr ); + xRestartManager.set( aContext.getSingleton( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.OfficeRestartManager" ) ) ), UNO_QUERY ); + } + + // check whether the shutdown is caused by restart + pExecGlobals->bRestartRequested = ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) ); + + Migration::migrateSettingsIfNecessary(); + + // keep a language options instance... + pExecGlobals->pLanguageOptions.reset( new SvtLanguageOptions(sal_True)); + + if (pExecGlobals->xGlobalBroadcaster.is()) + { + css::document::EventObject aEvent; + aEvent.EventName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnStartApp")); + pExecGlobals->xGlobalBroadcaster->notifyEvent(aEvent); + } + + SetSplashScreenProgress(50); + + // Backing Component + sal_Bool bCrashed = sal_False; + sal_Bool bExistsRecoveryData = sal_False; + sal_Bool bExistsSessionData = sal_False; + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ impl_checkRecoveryState" ); + impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} impl_checkRecoveryState" ); + + { + ::comphelper::ComponentContext aContext( xSMgr ); + xRestartManager.set( aContext.getSingleton( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.OfficeRestartManager" ) ) ), UNO_QUERY ); + } + + // check whether the shutdown is caused by restart + pExecGlobals->bRestartRequested = ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) ); + + if ( rCmdLineArgs.IsHeadless() ) + { + // Ensure that we use not the system file dialogs as + // headless mode relies on Application::EnableHeadlessMode() + // which does only work for VCL dialogs!! + SvtMiscOptions aMiscOptions; + pExecGlobals->bUseSystemFileDialog = aMiscOptions.UseSystemFileDialog(); + aMiscOptions.SetUseSystemFileDialog( sal_False ); + } + + if ( !pExecGlobals->bRestartRequested ) + { + if ((!rCmdLineArgs.WantsToLoadDocument() && !rCmdLineArgs.IsInvisible() && !rCmdLineArgs.IsHeadless() && !rCmdLineArgs.IsQuickstart()) && + (SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE)) && + (!bExistsRecoveryData ) && + (!bExistsSessionData ) && + (!Application::AnyInput( INPUT_APPEVENT ) )) + { + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create BackingComponent" ); + Reference< XFrame > xDesktopFrame( xDesktop, UNO_QUERY ); + if (xDesktopFrame.is()) + { + SetSplashScreenProgress(60); + Reference< XFrame > xBackingFrame; + Reference< ::com::sun::star::awt::XWindow > xContainerWindow; + + xBackingFrame = xDesktopFrame->findFrame(OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" )), 0); + if (xBackingFrame.is()) + xContainerWindow = xBackingFrame->getContainerWindow(); + if (xContainerWindow.is()) + { + SetDocumentExtendedStyle(xContainerWindow); + SetSplashScreenProgress(75); + Sequence< Any > lArgs(1); + lArgs[0] <<= xContainerWindow; + + Reference< XController > xBackingComp( + xSMgr->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs), UNO_QUERY); + if (xBackingComp.is()) + { + Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY); + // Attention: You MUST(!) call setComponent() before you call attachFrame(). + // Because the backing component set the property "IsBackingMode" of the frame + // to true inside attachFrame(). But setComponent() reset this state everytimes ... + xBackingFrame->setComponent(xBackingWin, xBackingComp); + SetSplashScreenProgress(100); + xBackingComp->attachFrame(xBackingFrame); + CloseSplashScreen(); + xContainerWindow->setVisible(sal_True); + } + } + } + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create BackingComponent" ); + } + } + } + catch ( com::sun::star::lang::WrappedTargetException& wte ) + { + com::sun::star::uno::Exception te; + wte.TargetException >>= te; + FatalError( MakeStartupConfigAccessErrorMessage(wte.Message + te.Message) ); + return EXIT_FAILURE; + } + catch ( com::sun::star::uno::Exception& e ) + { + FatalError( MakeStartupErrorMessage(e.Message) ); + return EXIT_FAILURE; + } + SetSplashScreenProgress(55); + + SvtFontSubstConfig().Apply(); + + SvtTabAppearanceCfg aAppearanceCfg; + aAppearanceCfg.SetInitialized(); + aAppearanceCfg.SetApplicationDefaults( this ); + SvtAccessibilityOptions aOptions; + aOptions.SetVCLSettings(); + SetSplashScreenProgress(60); + + if ( !pExecGlobals->bRestartRequested ) + { + Application::SetFilterHdl( LINK( this, Desktop, ImplInitFilterHdl ) ); + sal_Bool bTerminateRequested = sal_False; + + // Preload function depends on an initialized sfx application! + SetSplashScreenProgress(75); + + // use system window dialogs + Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_DIALOG ); + + SetSplashScreenProgress(80); + + if ( !bTerminateRequested && !rCmdLineArgs.IsInvisible() && + !rCmdLineArgs.IsNoQuickstart() ) + InitializeQuickstartMode( xSMgr ); + + RTL_LOGFILE_CONTEXT( aLog2, "desktop (cd100003) createInstance com.sun.star.frame.Desktop" ); + try + { + if ( xDesktop.is() ) + xDesktop->addTerminateListener( new OfficeIPCThreadController ); + SetSplashScreenProgress(100); + } + catch ( com::sun::star::uno::Exception& e ) + { + FatalError( MakeStartupErrorMessage(e.Message) ); + return EXIT_FAILURE; + } + + // Release solar mutex just before we wait for our client to connect + int nAcquireCount = Application::ReleaseSolarMutex(); + + // Post user event to startup first application component window + // We have to send this OpenClients message short before execute() to + // minimize the risk that this message overtakes type detection contruction!! + Application::PostUserEvent( LINK( this, Desktop, OpenClients_Impl ) ); + + // Post event to enable acceptors + Application::PostUserEvent( LINK( this, Desktop, EnableAcceptors_Impl) ); + + // The configuration error handler currently is only for startup + aConfigErrHandler.deactivate(); + + // Acquire solar mutex just before we enter our message loop + if ( nAcquireCount ) + Application::AcquireSolarMutex( nAcquireCount ); + + // call Application::Execute to process messages in vcl message loop + RTL_LOGFILE_PRODUCT_TRACE( "PERFORMANCE - enter Application::Execute()" ); + + try + { + // The JavaContext contains an interaction handler which is used when + // the creation of a Java Virtual Machine fails + com::sun::star::uno::ContextLayer layer2( + new svt::JavaContext( com::sun::star::uno::getCurrentContext() ) ); + + // check whether the shutdown is caused by restart just before entering the Execute + pExecGlobals->bRestartRequested = pExecGlobals->bRestartRequested || ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) ); + + if ( !pExecGlobals->bRestartRequested ) + { + // if this run of the office is triggered by restart, some additional actions should be done + DoRestartActionsIfNecessary( !rCmdLineArgs.IsInvisible() && !rCmdLineArgs.IsNoQuickstart() ); + + Execute(); + } + } + catch(const com::sun::star::document::CorruptedFilterConfigurationException& exFilterCfg) + { + OfficeIPCThread::SetDowning(); + FatalError( MakeStartupErrorMessage(exFilterCfg.Message) ); + } + catch(const com::sun::star::configuration::CorruptedConfigurationException& exAnyCfg) + { + OfficeIPCThread::SetDowning(); + FatalError( MakeStartupErrorMessage(exAnyCfg.Message) ); + } + } + else + { + if (xDesktop.is()) + xDesktop->terminate(); + } + // CAUTION: you do not necessarily get here e.g. on the Mac. + // please put all deinitialization code into doShutdown + return doShutdown(); +} + +int Desktop::doShutdown() +{ + if( ! pExecGlobals ) + return EXIT_SUCCESS; + + if ( pExecGlobals->bRestartRequested ) + SetRestartState(); + + if (pExecGlobals->xGlobalBroadcaster.is()) + { + css::document::EventObject aEvent; + aEvent.EventName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnCloseApp")); + pExecGlobals->xGlobalBroadcaster->notifyEvent(aEvent); + } + + delete pResMgr, pResMgr = NULL; + // Restore old value + const CommandLineArgs& rCmdLineArgs = GetCommandLineArgs(); + if ( rCmdLineArgs.IsHeadless() ) + SvtMiscOptions().SetUseSystemFileDialog( pExecGlobals->bUseSystemFileDialog ); + + // remove temp directory + RemoveTemporaryDirectory(); + FlushConfiguration(); + // The acceptors in the AcceptorMap must be released (in DeregisterServices) + // with the solar mutex unlocked, to avoid deadlock: + sal_uLong nAcquireCount = Application::ReleaseSolarMutex(); + DeregisterServices(); + Application::AcquireSolarMutex(nAcquireCount); + tools::DeInitTestToolLib(); + // be sure that path/language options gets destroyed before + // UCB is deinitialized + RTL_LOGFILE_CONTEXT_TRACE( aLog, "-> dispose path/language options" ); + pExecGlobals->pLanguageOptions.reset( 0 ); + pExecGlobals->pPathOptions.reset( 0 ); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- dispose path/language options" ); + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "-> deinit ucb" ); + ::ucbhelper::ContentBroker::deinitialize(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- deinit ucb" ); + + sal_Bool bRR = pExecGlobals->bRestartRequested; + delete pExecGlobals, pExecGlobals = NULL; + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "FINISHED WITH Destop::Main" ); + if ( bRR ) + { + restartOnMac(true); + if ( m_rSplashScreen.is() ) + m_rSplashScreen->reset(); + + return ExitHelper::E_NORMAL_RESTART; + } + return EXIT_SUCCESS; +} + +IMPL_LINK( Desktop, ImplInitFilterHdl, ConvertData*, pData ) +{ + return GraphicFilter::GetGraphicFilter().GetFilterCallback().Call( pData ); +} + +sal_Bool Desktop::InitializeConfiguration() +{ + sal_Bool bOk = sal_False; + + try + { + bOk = InitConfiguration(); + } + catch( ::com::sun::star::lang::ServiceNotRegisteredException& ) + { + this->HandleBootstrapErrors( Desktop::BE_UNO_SERVICE_CONFIG_MISSING ); + } + catch( ::com::sun::star::configuration::MissingBootstrapFileException& e ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::MISSING_BOOTSTRAP_FILE, + e.BootstrapFileURL )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_USER_INSTALL, aMsg ); + } + catch( ::com::sun::star::configuration::InvalidBootstrapFileException& e ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY, + e.BootstrapFileURL )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg ); + } + catch( ::com::sun::star::configuration::InstallationIncompleteException& ) + { + OUString aVersionFileURL; + OUString aMsg; + utl::Bootstrap::PathStatus aPathStatus = utl::Bootstrap::locateVersionFile( aVersionFileURL ); + if ( aPathStatus == utl::Bootstrap::PATH_EXISTS ) + aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE_ENTRY, aVersionFileURL ); + else + aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE, aVersionFileURL ); + + HandleBootstrapPathErrors( ::utl::Bootstrap::MISSING_USER_INSTALL, aMsg ); + } + catch ( com::sun::star::configuration::backend::BackendAccessException& exception) + { + // [cm122549] It is assumed in this case that the message + // coming from InitConfiguration (in fact CreateApplicationConf...) + // is suitable for display directly. + FatalError( MakeStartupErrorMessage( exception.Message ) ); + } + catch ( com::sun::star::configuration::backend::BackendSetupException& exception) + { + // [cm122549] It is assumed in this case that the message + // coming from InitConfiguration (in fact CreateApplicationConf...) + // is suitable for display directly. + FatalError( MakeStartupErrorMessage( exception.Message ) ); + } + catch ( ::com::sun::star::configuration::CannotLoadConfigurationException& ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA, + OUString() )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg ); + } + catch( ::com::sun::star::uno::Exception& ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA, + OUString() )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg ); + } + + return bOk; +} + +void Desktop::FlushConfiguration() +{ + Reference < XFlushable > xCFGFlush( ::utl::ConfigManager::GetConfigManager().GetConfigurationProvider(), UNO_QUERY ); + if (xCFGFlush.is()) + { + xCFGFlush->flush(); + } + else + { + // because there is no method to flush the condiguration data, we must dispose the ConfigManager + Reference < XComponent > xCFGDispose( ::utl::ConfigManager::GetConfigManager().GetConfigurationProvider(), UNO_QUERY ); + if (xCFGDispose.is()) + xCFGDispose->dispose(); + } +} + +sal_Bool Desktop::shouldLaunchQuickstart() +{ + sal_Bool bQuickstart = GetCommandLineArgs().IsQuickstart(); + if (!bQuickstart) + { + const SfxPoolItem* pItem=0; + SfxItemSet aQLSet(SFX_APP()->GetPool(), SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER); + SFX_APP()->GetOptions(aQLSet); + SfxItemState eState = aQLSet.GetItemState(SID_ATTR_QUICKLAUNCHER, sal_False, &pItem); + if (SFX_ITEM_SET == eState) + bQuickstart = ((SfxBoolItem*)pItem)->GetValue(); + } + return bQuickstart; +} + + +sal_Bool Desktop::InitializeQuickstartMode( Reference< XMultiServiceFactory >& rSMgr ) +{ + try + { + // the shutdown icon sits in the systray and allows the user to keep + // the office instance running for quicker restart + // this will only be activated if -quickstart was specified on cmdline + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) createInstance com.sun.star.office.Quickstart" ); + + sal_Bool bQuickstart = shouldLaunchQuickstart(); + + // Try to instanciate quickstart service. This service is not mandatory, so + // do nothing if service is not available + + // #i105753# the following if was invented for performance + // unfortunately this broke the QUARTZ behavior which is to always run + // in quickstart mode since Mac applications do not usually quit + // when the last document closes + #ifndef QUARTZ + if ( bQuickstart ) + #endif + { + Sequence< Any > aSeq( 1 ); + aSeq[0] <<= bQuickstart; + Reference < XComponent > xQuickstart( rSMgr->createInstanceWithArguments( + DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" ), aSeq ), + UNO_QUERY ); + } + return sal_True; + } + catch( ::com::sun::star::uno::Exception& ) + { + return sal_False; + } +} + +void Desktop::SystemSettingsChanging( AllSettings& rSettings, Window* ) +{ + if ( !SvtTabAppearanceCfg::IsInitialized () ) + return; + +# define DRAGFULL_OPTION_ALL \ + ( DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE \ + | DRAGFULL_OPTION_OBJECTMOVE | DRAGFULL_OPTION_OBJECTSIZE \ + | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT \ + | DRAGFULL_OPTION_SCROLL ) +# define DRAGFULL_OPTION_NONE ((sal_uInt32)~DRAGFULL_OPTION_ALL) + + StyleSettings hStyleSettings = rSettings.GetStyleSettings(); + MouseSettings hMouseSettings = rSettings.GetMouseSettings(); + + sal_uInt32 nDragFullOptions = hStyleSettings.GetDragFullOptions(); + + SvtTabAppearanceCfg aAppearanceCfg; + sal_uInt16 nGet = aAppearanceCfg.GetDragMode(); + switch ( nGet ) + { + case DragFullWindow: + nDragFullOptions |= DRAGFULL_OPTION_ALL; + break; + case DragFrame: + nDragFullOptions &= DRAGFULL_OPTION_NONE; + break; + case DragSystemDep: + default: + break; + } + + sal_uInt32 nFollow = hMouseSettings.GetFollow(); + hMouseSettings.SetFollow( aAppearanceCfg.IsMenuMouseFollow() ? (nFollow|MOUSE_FOLLOW_MENU) : (nFollow&~MOUSE_FOLLOW_MENU)); + rSettings.SetMouseSettings(hMouseSettings); + + SvtMenuOptions aMenuOpt; + hStyleSettings.SetUseImagesInMenus(aMenuOpt.GetMenuIconsState()); + hStyleSettings.SetDragFullOptions( nDragFullOptions ); + rSettings.SetStyleSettings ( hStyleSettings ); +} + +// ======================================================================== +IMPL_LINK( Desktop, AsyncInitFirstRun, void*, EMPTYARG ) +{ + DoFirstRunInitializations(); + return 0L; +} + +// ======================================================================== + +class ExitTimer : public Timer +{ + public: + ExitTimer() + { + SetTimeout(500); + Start(); + } + virtual void Timeout() + { + exit(42); + } +}; + +IMPL_LINK( Desktop, OpenClients_Impl, void*, EMPTYARG ) +{ + RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "PERFORMANCE - DesktopOpenClients_Impl()" ); + + try { + OpenClients(); + + OfficeIPCThread::SetReady(); + + CloseSplashScreen(); + CheckFirstRun( ); + EnableOleAutomation(); + + if (getenv ("OOO_EXIT_POST_STARTUP")) + new ExitTimer(); + } catch (const ::com::sun::star::uno::Exception &e) { + String a( RTL_CONSTASCII_USTRINGPARAM( "UNO exception during client open:\n" ) ); + Application::Abort( a + e.Message ); + } + return 0; +} + +// enable acceptos +IMPL_LINK( Desktop, EnableAcceptors_Impl, void*, EMPTYARG ) +{ + enableAcceptors(); + return 0; +} + + +// Registers a COM class factory of the service manager with the windows operating system. +void Desktop::EnableOleAutomation() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (jl97489) ::Desktop::EnableOleAutomation" ); +#ifdef WNT + Reference< XMultiServiceFactory > xSMgr= comphelper::getProcessServiceFactory(); + xSMgr->createInstance(DEFINE_CONST_UNICODE("com.sun.star.bridge.OleApplicationRegistration")); + xSMgr->createInstance(DEFINE_CONST_UNICODE("com.sun.star.comp.ole.EmbedServer")); +#endif +} + +void Desktop::PreloadModuleData( const CommandLineArgs& rArgs ) +{ + Reference< XMultiServiceFactory > rFactory = ::comphelper::getProcessServiceFactory(); + + Sequence < com::sun::star::beans::PropertyValue > args(1); + args[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Hidden")); + args[0].Value <<= sal_True; + Reference < XComponentLoader > xLoader( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), UNO_QUERY ); + + if ( !xLoader.is() ) + return; + + if ( rArgs.IsWriter() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/swriter"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } + if ( rArgs.IsCalc() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/scalc"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } + if ( rArgs.IsDraw() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/sdraw"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } + if ( rArgs.IsImpress() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/simpress"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } +} + +void Desktop::PreloadConfigurationData() +{ + Reference< XMultiServiceFactory > rFactory = ::comphelper::getProcessServiceFactory(); + Reference< XNameAccess > xNameAccess( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.frame.UICommandDescription" )), UNO_QUERY ); + + rtl::OUString aWriterDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" )); + rtl::OUString aCalcDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" )); + rtl::OUString aDrawDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" )); + rtl::OUString aImpressDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" )); + + // preload commands configuration + if ( xNameAccess.is() ) + { + Any a; + Reference< XNameAccess > xCmdAccess; + + try + { + a = xNameAccess->getByName( aWriterDoc ); + a >>= xCmdAccess; + if ( xCmdAccess.is() ) + { + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:BasicShapes" )); + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:EditGlossary" )); + } + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + + try + { + a = xNameAccess->getByName( aCalcDoc ); + a >>= xCmdAccess; + if ( xCmdAccess.is() ) + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:InsertObjectStarMath" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + + try + { + // draw and impress share the same configuration file (DrawImpressCommands.xcu) + a = xNameAccess->getByName( aDrawDoc ); + a >>= xCmdAccess; + if ( xCmdAccess.is() ) + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:Polygon" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload window state configuration + xNameAccess = Reference< XNameAccess >( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.ui.WindowStateConfiguration" )), UNO_QUERY ); + if ( xNameAccess.is() ) + { + Any a; + Reference< XNameAccess > xWindowAccess; + try + { + a = xNameAccess->getByName( aWriterDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + try + { + a = xNameAccess->getByName( aCalcDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + try + { + a = xNameAccess->getByName( aDrawDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + try + { + a = xNameAccess->getByName( aImpressDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload user interface element factories + Sequence< Sequence< css::beans::PropertyValue > > aSeqSeqPropValue; + Reference< ::com::sun::star::ui::XUIElementFactoryRegistration > xUIElementFactory( + rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.ui.UIElementFactoryManager" )), + UNO_QUERY ); + if ( xUIElementFactory.is() ) + { + try + { + aSeqSeqPropValue = xUIElementFactory->getRegisteredFactories(); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload popup menu controller factories. As all controllers are in the same + // configuration file they also get preloaded! + Reference< ::com::sun::star::frame::XUIControllerRegistration > xPopupMenuControllerFactory( + rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.frame.PopupMenuControllerFactory" )), + UNO_QUERY ); + if ( xPopupMenuControllerFactory.is() ) + { + try + { + xPopupMenuControllerFactory->hasController( + DEFINE_CONST_UNICODE( ".uno:CharFontName" ), + OUString() ); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload filter configuration + Sequence< OUString > aSeq; + xNameAccess = Reference< XNameAccess >( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" )), UNO_QUERY ); + if ( xNameAccess.is() ) + { + try + { + aSeq = xNameAccess->getElementNames(); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload type detection configuration + xNameAccess = Reference< XNameAccess >( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" )), UNO_QUERY ); + if ( xNameAccess.is() ) + { + try + { + aSeq = xNameAccess->getElementNames(); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); + static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" ) ); + + // get configuration provider + Reference< XMultiServiceFactory > xConfigProvider; + xConfigProvider = Reference< XMultiServiceFactory > ( + rFactory->createInstance( sConfigSrvc ),UNO_QUERY ); + + if ( xConfigProvider.is() ) + { + // preload writer configuration + Sequence< Any > theArgs(1); + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Writer/MailMergeWizard")); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // WriterWeb + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.WriterWeb/Content")); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload compatibility + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Compatibility/WriterCompatibilityVersion")); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload calc configuration + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Calc/Content")); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload impress configuration + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.UI.Effects/UserInterface")); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Impress/Layout")); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload draw configuration + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Draw/Layout")); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload ui configuration + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.UI/FilterClassification")); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload addons configuration + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Addons/AddonUI")); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + } +} + +void Desktop::OpenClients() +{ + + // check if a document has been recovered - if there is one of if a document was loaded by cmdline, no default document + // should be created + Reference < XComponent > xFirst; + sal_Bool bLoaded = sal_False; + + const CommandLineArgs& rArgs = GetCommandLineArgs(); + SvtInternalOptions aInternalOptions; + + Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory(); + + if (!rArgs.IsQuickstart()) + { + sal_Bool bShowHelp = sal_False; + ::rtl::OUStringBuffer aHelpURLBuffer; + if (rArgs.IsHelpWriter()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start"); + } else if (rArgs.IsHelpCalc()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start"); + } else if (rArgs.IsHelpDraw()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start"); + } else if (rArgs.IsHelpImpress()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start"); + } else if (rArgs.IsHelpBase()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start"); + } else if (rArgs.IsHelpBasic()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start"); + } else if (rArgs.IsHelpMath()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start"); + } + if (bShowHelp) { + Help *pHelp = Application::GetHelp(); + + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::LOCALE ); + rtl::OUString aTmp; + aRet >>= aTmp; + aHelpURLBuffer.appendAscii("?Language="); + aHelpURLBuffer.append(aTmp); +#if defined UNX + aHelpURLBuffer.appendAscii("&System=UNX"); +#elif defined WNT + aHelpURLBuffer.appendAscii("&System=WIN"); +#endif + pHelp->Start(aHelpURLBuffer.makeStringAndClear(), NULL); + return; + } + } + else + { + OUString aIniName; + + osl_getExecutableFile( &aIniName.pData ); + sal_uInt32 lastIndex = aIniName.lastIndexOf('/'); + if ( lastIndex > 0 ) + { + aIniName = aIniName.copy( 0, lastIndex+1 ); + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "perftune" )); +#if defined(WNT) + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( ".ini" )); +#else + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "rc" )); +#endif + } + + rtl::Bootstrap aPerfTuneIniFile( aIniName ); + + OUString aDefault( RTL_CONSTASCII_USTRINGPARAM( "0" )); + OUString aPreloadData; + + aPerfTuneIniFile.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "QuickstartPreloadConfiguration" )), aPreloadData, aDefault ); + if ( aPreloadData.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "1" ) )) + { + if ( rArgs.IsWriter() || + rArgs.IsCalc() || + rArgs.IsDraw() || + rArgs.IsImpress() ) + { + PreloadModuleData( rArgs ); + } + + PreloadConfigurationData(); + } + } + + // Disable AutoSave feature in case "-norestore" or a similare command line switch is set on the command line. + // The reason behind: AutoSave/EmergencySave/AutoRecovery share the same data. + // But the require that all documents, which are saved as backup should exists inside + // memory. May be this mechanism will be inconsistent if the configuration exists ... + // but no document inside memory corrspond to this data. + // Furter it's not acceptable to recover such documents without any UI. It can + // need some time, where the user wont see any results and wait for finishing the office startup ... + sal_Bool bAllowRecoveryAndSessionManagement = ( + ( !rArgs.IsNoRestore() ) && + ( !rArgs.IsHeadless() ) && + ( !rArgs.IsServer() ) + ); + + if ( ! bAllowRecoveryAndSessionManagement ) + { + try + { + Reference< XDispatch > xRecovery( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.AutoRecovery")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + + Reference< XURLTransformer > xParser( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + + css::util::URL aCmd; + aCmd.Complete = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.autorecovery:/disableRecovery")); + xParser->parseStrict(aCmd); + + xRecovery->dispatch(aCmd, css::uno::Sequence< css::beans::PropertyValue >()); + } + catch(const css::uno::Exception& e) + { + OUString aMessage = OUString(RTL_CONSTASCII_USTRINGPARAM("Could not disable AutoRecovery.\n")) + + e.Message; + OSL_FAIL(OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + else + { + sal_Bool bCrashed = sal_False; + sal_Bool bExistsRecoveryData = sal_False; + sal_Bool bExistsSessionData = sal_False; + + impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData); + + if ( !getenv ("OOO_DISABLE_RECOVERY") && + ( ! bLoaded ) && + ( + ( bExistsRecoveryData ) || // => crash with files => recovery + ( bCrashed ) // => crash without files => error report + ) + ) + { + try + { + impl_callRecoveryUI( + sal_False , // false => force recovery instead of emergency save + bCrashed , + bExistsRecoveryData); + /* TODO we cant be shure, that at least one document could be recovered here successfully + So we set bLoaded=sal_True to supress opening of the default document. + But we should make it more safe. Otherwhise we have an office without an UI ... + ... + May be we can check the desktop if some documents are existing there. + */ + Reference< XFramesSupplier > xTasksSupplier( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY_THROW ); + if ( xList->hasElements() ) + bLoaded = sal_True; + } + catch(const css::uno::Exception& e) + { + OUString aMessage = OUString(RTL_CONSTASCII_USTRINGPARAM("Error during recovery\n")) + + e.Message; + OSL_FAIL(OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + + Reference< XInitialization > xSessionListener; + try + { + xSessionListener = Reference< XInitialization >(::comphelper::getProcessServiceFactory()->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.SessionListener"))), UNO_QUERY_THROW); + + // specifies whether the UI-interaction on Session shutdown is allowed + sal_Bool bAllowUI = isUIOnSessionShutdownAllowed(); + css::beans::NamedValue aProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AllowUserInteractionOnQuit" ) ), + css::uno::makeAny( bAllowUI ) ); + css::uno::Sequence< css::uno::Any > aArgs( 1 ); + aArgs[0] <<= aProperty; + + xSessionListener->initialize( aArgs ); + } + catch(const com::sun::star::uno::Exception& e) + { + OUString aMessage = OUString(RTL_CONSTASCII_USTRINGPARAM("Registration of session listener failed\n")) + + e.Message; + OSL_FAIL(OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + + if ( + ( ! bLoaded ) && + ( bExistsSessionData ) + ) + { + // session management + try + { + Reference< XSessionManagerListener > r(xSessionListener, UNO_QUERY_THROW); + bLoaded = r->doRestore(); + } + catch(const com::sun::star::uno::Exception& e) + { + OUString aMessage = OUString(RTL_CONSTASCII_USTRINGPARAM("Error in session management\n")) + + e.Message; + OSL_FAIL(OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + } + + OfficeIPCThread::EnableRequests(); + + sal_Bool bShutdown( sal_False ); + if ( !rArgs.IsServer() ) + { + ProcessDocumentsRequest aRequest(rArgs.getCwdUrl()); + aRequest.pcProcessed = NULL; + + rArgs.GetOpenList( aRequest.aOpenList ); + rArgs.GetViewList( aRequest.aViewList ); + rArgs.GetStartList( aRequest.aStartList ); + rArgs.GetPrintList( aRequest.aPrintList ); + rArgs.GetPrintToList( aRequest.aPrintToList ); + rArgs.GetPrinterName( aRequest.aPrinterName ); + rArgs.GetForceOpenList( aRequest.aForceOpenList ); + rArgs.GetForceNewList( aRequest.aForceNewList ); + rArgs.GetConversionList( aRequest.aConversionList ); + rArgs.GetConversionParams( aRequest.aConversionParams ); + rArgs.GetConversionOut( aRequest.aConversionOut ); + rArgs.GetInFilter( aRequest.aInFilter ); + + if ( aRequest.aOpenList.getLength() > 0 || + aRequest.aViewList.getLength() > 0 || + aRequest.aStartList.getLength() > 0 || + aRequest.aPrintList.getLength() > 0 || + aRequest.aForceOpenList.getLength() > 0 || + aRequest.aForceNewList.getLength() > 0 || + ( aRequest.aPrintToList.getLength() > 0 && aRequest.aPrinterName.getLength() > 0 ) || + aRequest.aConversionList.getLength() > 0 ) + { + bLoaded = sal_True; + + if ( rArgs.HasModuleParam() ) + { + SvtModuleOptions aOpt; + + // Support command line parameters to start a module (as preselection) + if ( rArgs.IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER ); + else if ( rArgs.IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC ); + else if ( rArgs.IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS ); + else if ( rArgs.IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW ); + } + + // check for printing disabled + if( ( aRequest.aPrintList.getLength() || aRequest.aPrintToList.getLength() ) + && Application::GetSettings().GetMiscSettings().GetDisablePrinting() ) + { + aRequest.aPrintList = rtl::OUString(); + aRequest.aPrintToList = rtl::OUString(); + ResMgr* pDtResMgr = GetDesktopResManager(); + if( pDtResMgr ) + { + ErrorBox aBox( NULL, ResId( EBX_ERR_PRINTDISABLED, *pDtResMgr ) ); + aBox.Execute(); + } + } + + // Process request + bShutdown = OfficeIPCThread::ExecuteCmdLineRequests( aRequest ); + } + } + + // Don't do anything if we have successfully called terminate at desktop + if ( bShutdown ) + return; + + // no default document if a document was loaded by recovery or by command line or if soffice is used as server + Reference< XFramesSupplier > xTasksSupplier( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY_THROW ); + if ( xList->hasElements() || rArgs.IsServer() ) + return; + + if ( rArgs.IsQuickstart() || rArgs.IsInvisible() || rArgs.IsBean() || Application::AnyInput( INPUT_APPEVENT ) ) + // soffice was started as tray icon ... + return; + { + OpenDefault(); + } +} + +void Desktop::OpenDefault() +{ + + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::OpenDefault" ); + + ::rtl::OUString aName; + SvtModuleOptions aOpt; + + const CommandLineArgs& rArgs = GetCommandLineArgs(); + if ( rArgs.IsNoDefault() ) return; + if ( rArgs.HasModuleParam() ) + { + // Support new command line parameters to start a module + if ( rArgs.IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER ); + else if ( rArgs.IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC ); + else if ( rArgs.IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS ); + else if ( rArgs.IsBase() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE ); + else if ( rArgs.IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW ); + else if ( rArgs.IsMath() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_MATH ); + else if ( rArgs.IsGlobal() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERGLOBAL ); + else if ( rArgs.IsWeb() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERWEB ); + } + + if ( !aName.getLength() ) + { + // Old way to create a default document + if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW ); + else + return; + } + + ProcessDocumentsRequest aRequest(rArgs.getCwdUrl()); + aRequest.pcProcessed = NULL; + aRequest.aOpenList = aName; + OfficeIPCThread::ExecuteCmdLineRequests( aRequest ); +} + + +String GetURL_Impl( + const String& rName, boost::optional< rtl::OUString > const & cwdUrl ) +{ + // if rName is a vnd.sun.star.script URL do not attempt to parse it + // as INetURLObj does not handle handle there URLs + if (rName.CompareToAscii("vnd.sun.star.script" , 19) == COMPARE_EQUAL) + { + return rName; + } + + // dont touch file urls, those should already be in internal form + // they won't get better here (#112849#) + if (rName.CompareToAscii("file:" , 5) == COMPARE_EQUAL) + { + return rName; + } + + if ( rName.CompareToAscii("service:" , 8) == COMPARE_EQUAL ) + { + return rName; + } + + // Add path seperator to these directory and make given URL (rName) absolute by using of current working directory + // Attention: "setFinalSlash()" is necessary for calling "smartRel2Abs()"!!! + // Otherwhise last part will be ignored and wrong result will be returned!!! + // "smartRel2Abs()" interpret given URL as file not as path. So he truncate last element to get the base path ... + // But if we add a seperator - he doesn't do it anymore. + INetURLObject aObj; + if (cwdUrl) { + aObj.SetURL(*cwdUrl); + aObj.setFinalSlash(); + } + + // Use the provided parameters for smartRel2Abs to support the usage of '%' in system paths. + // Otherwise this char won't get encoded and we are not able to load such files later, + bool bWasAbsolute; + INetURLObject aURL = aObj.smartRel2Abs( rName, bWasAbsolute, false, INetURLObject::WAS_ENCODED, + RTL_TEXTENCODING_UTF8, true ); + String aFileURL = aURL.GetMainURL(INetURLObject::NO_DECODE); + + ::osl::FileStatus aStatus( osl_FileStatus_Mask_FileURL ); + ::osl::DirectoryItem aItem; + if( ::osl::FileBase::E_None == ::osl::DirectoryItem::get( aFileURL, aItem ) && + ::osl::FileBase::E_None == aItem.getFileStatus( aStatus ) ) + aFileURL = aStatus.getFileURL(); + + return aFileURL; +} + +void Desktop::HandleAppEvent( const ApplicationEvent& rAppEvent ) +{ + if ( rAppEvent.GetEvent() == "APPEAR" && !GetCommandLineArgs().IsInvisible() ) + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + // find active task - the active task is always a visible task + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFramesSupplier > + xDesktop( xSMGR->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY ); + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xTask = xDesktop->getActiveFrame(); + if ( !xTask.is() ) + { + // get any task if there is no active one + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > xList( xDesktop->getFrames(), ::com::sun::star::uno::UNO_QUERY ); + if ( xList->getCount()>0 ) + xList->getByIndex(0) >>= xTask; + } + + if ( xTask.is() ) + { + Reference< com::sun::star::awt::XTopWindow > xTop( xTask->getContainerWindow(), UNO_QUERY ); + xTop->toFront(); + } + else + { + // no visible task that could be activated found + Reference< XFrame > xBackingFrame; + Reference< ::com::sun::star::awt::XWindow > xContainerWindow; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xDesktopFrame( xDesktop, UNO_QUERY ); + + xBackingFrame = xDesktopFrame->findFrame(OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" )), 0); + if (xBackingFrame.is()) + xContainerWindow = xBackingFrame->getContainerWindow(); + if (xContainerWindow.is()) + { + Sequence< Any > lArgs(1); + lArgs[0] <<= xContainerWindow; + Reference< XController > xBackingComp( + xSMGR->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs), + UNO_QUERY); + if (xBackingComp.is()) + { + Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY); + // Attention: You MUST(!) call setComponent() before you call attachFrame(). + // Because the backing component set the property "IsBackingMode" of the frame + // to true inside attachFrame(). But setComponent() reset this state everytimes ... + xBackingFrame->setComponent(xBackingWin, xBackingComp); + xBackingComp->attachFrame(xBackingFrame); + xContainerWindow->setVisible(sal_True); + + Window* pCompWindow = VCLUnoHelper::GetWindow(xBackingFrame->getComponentWindow()); + if (pCompWindow) + pCompWindow->Update(); + } + } + } + } + else if ( rAppEvent.GetEvent() == "QUICKSTART" && !GetCommandLineArgs().IsInvisible() ) + { + // If the office has been started the second time its command line arguments are sent through a pipe + // connection to the first office. We want to reuse the quickstart option for the first office. + // NOTICE: The quickstart service must be initialized inside the "main thread", so we use the + // application events to do this (they are executed inside main thread)!!! + // Don't start quickstart service if the user specified "-invisible" on the command line! + sal_Bool bQuickstart( sal_True ); + Sequence< Any > aSeq( 1 ); + aSeq[0] <<= bQuickstart; + + Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" )), + UNO_QUERY ); + if ( xQuickstart.is() ) + xQuickstart->initialize( aSeq ); + } + else if ( rAppEvent.GetEvent() == "ACCEPT" ) + { + // every time an accept parameter is used we create an acceptor + // with the corresponding accept-string + OUString aAcceptString(rAppEvent.GetData().GetBuffer()); + createAcceptor(aAcceptString); + } + else if ( rAppEvent.GetEvent() == "UNACCEPT" ) + { + // try to remove corresponding acceptor + OUString aUnAcceptString(rAppEvent.GetData().GetBuffer()); + destroyAcceptor(aUnAcceptString); + } + else if ( rAppEvent.GetEvent() == "SaveDocuments" ) + { + Desktop::_bTasksSaved = sal_False; + Desktop::_bTasksSaved = SaveTasks(); + } + else if ( rAppEvent.GetEvent() == "OPENHELPURL" ) + { + // start help for a specific URL + OUString aHelpURL(rAppEvent.GetData().GetBuffer()); + Help *pHelp = Application::GetHelp(); + pHelp->Start(aHelpURL, NULL); + } + else if ( rAppEvent.GetEvent() == APPEVENT_OPEN_STRING ) + { + OUString aOpenURL(rAppEvent.GetData().GetBuffer()); + + const CommandLineArgs& rCmdLine = GetCommandLineArgs(); + if ( !rCmdLine.IsInvisible() && !rCmdLine.IsTerminateAfterInit() ) + { + ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest( + rCmdLine.getCwdUrl()); + pDocsRequest->aOpenList = aOpenURL; + pDocsRequest->pcProcessed = NULL; + + OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest ); + delete pDocsRequest; + } + } + else if ( rAppEvent.GetEvent() == APPEVENT_PRINT_STRING ) + { + OUString aPrintURL(rAppEvent.GetData().GetBuffer()); + + const CommandLineArgs& rCmdLine = GetCommandLineArgs(); + if ( !rCmdLine.IsInvisible() && !rCmdLine.IsTerminateAfterInit() ) + { + ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest( + rCmdLine.getCwdUrl()); + pDocsRequest->aPrintList = aPrintURL; + pDocsRequest->pcProcessed = NULL; + + OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest ); + delete pDocsRequest; + } + } +#ifndef UNX + else if ( rAppEvent.GetEvent() == "HELP" ) + { + // in non unix version allow showing of cmdline help window + displayCmdlineHelp(); + } +#endif + else if ( rAppEvent.GetEvent() == "SHOWDIALOG" ) + { + // ignore all errors here. It's clicking a menu entry only ... + // The user will try it again, in case nothing happens .-) + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > + xDesktop( xSMGR->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY ); + + // check provider ... we know it's weak reference only + if ( ! xDesktop.is()) + return; + + css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))), css::uno::UNO_QUERY_THROW); + css::util::URL aCommand; + if( rAppEvent.GetData().EqualsAscii( "PREFERENCES" ) ) + aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:OptionsTreeDialog" ) ); + else if( rAppEvent.GetData().EqualsAscii( "ABOUT" ) ) + aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:About" ) ); + if( aCommand.Complete.getLength() ) + { + xParser->parseStrict(aCommand); + + css::uno::Reference< css::frame::XDispatch > xDispatch = xDesktop->queryDispatch(aCommand, rtl::OUString(), 0); + if (xDispatch.is()) + xDispatch->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >()); + } + } + catch(const css::uno::Exception&) + {} + } + else if( rAppEvent.GetEvent() == "PRIVATE:DOSHUTDOWN" ) + { + Desktop* pD = dynamic_cast<Desktop*>(GetpApp()); + OSL_ENSURE( pD, "no desktop ?!?" ); + if( pD ) + pD->doShutdown(); + } +} + +void Desktop::OpenSplashScreen() +{ + ::rtl::OUString aTmpString; + const CommandLineArgs &rCmdLine = GetCommandLineArgs(); + sal_Bool bVisible = sal_False; + // Show intro only if this is normal start (e.g. no server, no quickstart, no printing ) + if ( !rCmdLine.IsInvisible() && + !rCmdLine.IsHeadless() && + !rCmdLine.IsQuickstart() && + !rCmdLine.IsMinimized() && + !rCmdLine.IsNoLogo() && + !rCmdLine.IsTerminateAfterInit() && + !rCmdLine.GetPrintList( aTmpString ) && + !rCmdLine.GetPrintToList( aTmpString ) && + !rCmdLine.GetConversionList( aTmpString )) + { + // Determine application name from command line parameters + OUString aAppName; + if ( rCmdLine.IsWriter() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer" )); + else if ( rCmdLine.IsCalc() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc" )); + else if ( rCmdLine.IsDraw() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "draw" )); + else if ( rCmdLine.IsImpress() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress" )); + else if ( rCmdLine.IsBase() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "base" )); + else if ( rCmdLine.IsGlobal() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "global" )); + else if ( rCmdLine.IsMath() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "math" )); + else if ( rCmdLine.IsWeb() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "web" )); + + // Which splash to use + OUString aSplashService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.office.SplashScreen" )); + if ( rCmdLine.GetStringParam( CommandLineArgs::CMD_STRINGPARAM_SPLASHPIPE ).getLength() ) + aSplashService = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.office.PipeSplashScreen")); + + bVisible = sal_True; + Sequence< Any > aSeq( 2 ); + aSeq[0] <<= bVisible; + aSeq[1] <<= aAppName; + m_rSplashScreen = Reference<XStatusIndicator>( + comphelper::getProcessServiceFactory()->createInstanceWithArguments( + aSplashService, aSeq), UNO_QUERY); + + if(m_rSplashScreen.is()) + m_rSplashScreen->start(OUString(RTL_CONSTASCII_USTRINGPARAM("SplashScreen")), 100); + } + +} + +void Desktop::SetSplashScreenProgress(sal_Int32 iProgress) +{ + if(m_rSplashScreen.is()) + { + m_rSplashScreen->setValue(iProgress); + } +} + +void Desktop::SetSplashScreenText( const ::rtl::OUString& rText ) +{ + if( m_rSplashScreen.is() ) + { + m_rSplashScreen->setText( rText ); + } +} + +void Desktop::CloseSplashScreen() +{ + if(m_rSplashScreen.is()) + { + m_rSplashScreen->end(); + m_rSplashScreen = NULL; + } +} + +// ======================================================================== +void Desktop::DoFirstRunInitializations() +{ + try + { + Reference< XJobExecutor > xExecutor( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.JobExecutor")) ), UNO_QUERY ); + if( xExecutor.is() ) + xExecutor->trigger( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("onFirstRunInitialization")) ); + } + catch(const ::com::sun::star::uno::Exception&) + { + OSL_FAIL( "Desktop::DoFirstRunInitializations: caught an exception while trigger job executor ..." ); + } +} + +// ======================================================================== +void Desktop::CheckFirstRun( ) +{ + const ::rtl::OUString sCommonMiscNodeName(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Common/Misc")); + const ::rtl::OUString sFirstRunNodeName(RTL_CONSTASCII_USTRINGPARAM("FirstRun")); + + // -------------------------------------------------------------------- + // check if this is the first office start + + // for this, open the Common/Misc node where this info is stored + ::utl::OConfigurationTreeRoot aCommonMisc = ::utl::OConfigurationTreeRoot::createWithServiceFactory( + ::comphelper::getProcessServiceFactory( ), + sCommonMiscNodeName, + 2, + ::utl::OConfigurationTreeRoot::CM_UPDATABLE + ); + + // read the flag + OSL_ENSURE( aCommonMisc.isValid(), "Desktop::CheckFirstRun: could not open the config node needed!" ); + sal_Bool bIsFirstRun = sal_False; + aCommonMisc.getNodeValue( sFirstRunNodeName ) >>= bIsFirstRun; + + if ( !bIsFirstRun ) + // nothing to do .... + return; + + // -------------------------------------------------------------------- + // it is the first run + // this has once been done using a vos timer. this could lead to problems when + // the timer would trigger when the app is already going down again, since VCL would + // no longer be available. Since the old handler would do a postUserEvent to the main + // thread anyway, we can use a vcl timer here to prevent the race contition (#107197#) + m_firstRunTimer.SetTimeout(3000); // 3 sec. + m_firstRunTimer.SetTimeoutHdl(LINK(this, Desktop, AsyncInitFirstRun)); + m_firstRunTimer.Start(); + + // -------------------------------------------------------------------- + // reset the config flag + + // set the value + aCommonMisc.setNodeValue( sFirstRunNodeName, makeAny( (sal_Bool)sal_False ) ); + // commit the changes + aCommonMisc.commit(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/appfirststart.cxx b/desktop/source/app/appfirststart.cxx new file mode 100644 index 000000000000..a5a161181efa --- /dev/null +++ b/desktop/source/app/appfirststart.cxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <osl/file.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/ustring.hxx> +#include <tools/datetime.hxx> +#include <unotools/configmgr.hxx> + +#include <comphelper/processfactory.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> + +#include "app.hxx" + +using ::rtl::OUString; +using namespace ::desktop; +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; + +static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); +static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ); + +/* Local function - get access to the configuration */ +static Reference< XPropertySet > impl_getConfigurationAccess( const OUString& rPath ) +{ + Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + + // get configuration provider + Reference< XMultiServiceFactory > xConfigProvider = Reference< XMultiServiceFactory >( + xFactory->createInstance( sConfigSrvc ), UNO_QUERY_THROW ); + + Sequence< Any > aArgs( 1 ); + NamedValue aValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "NodePath" ) ), makeAny( rPath ) ); + aArgs[0] <<= aValue; + return Reference< XPropertySet >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, aArgs ), UNO_QUERY_THROW ); +} + +void Desktop::DoRestartActionsIfNecessary( sal_Bool bQuickStart ) +{ + if ( bQuickStart ) + { + try + { + Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) ); + + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM( "OfficeRestartInProgress" ) ); + Any aRestart = xPSet->getPropertyValue( sPropName ); + sal_Bool bRestart = sal_False; + if ( ( aRestart >>= bRestart ) && bRestart ) + { + xPSet->setPropertyValue( sPropName, makeAny( sal_False ) ); + Reference< util::XChangesBatch >( xPSet, UNO_QUERY_THROW )->commitChanges(); + + Sequence< Any > aSeq( 1 ); + sal_Bool bQuickstart = shouldLaunchQuickstart(); + aSeq[0] <<= bQuickstart; + + Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.office.Quickstart" ) ) ),UNO_QUERY_THROW ); + xQuickstart->initialize( aSeq ); + } + } + catch( uno::Exception& ) + { + // this is no critical operation so it should not prevent office from starting + } + } +} + +void Desktop::SetRestartState() +{ + try + { + Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) ); + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM( "OfficeRestartInProgress" ) ); + xPSet->setPropertyValue( sPropName, makeAny( sal_True ) ); + Reference< util::XChangesBatch >( xPSet, UNO_QUERY_THROW )->commitChanges(); + } + catch( uno::Exception& ) + { + // this is no critical operation, ignore the exception + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/appinit.cxx b/desktop/source/app/appinit.cxx new file mode 100644 index 000000000000..13624379bf5d --- /dev/null +++ b/desktop/source/app/appinit.cxx @@ -0,0 +1,464 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <algorithm> + +#include "app.hxx" +#include "cmdlineargs.hxx" +#include "desktopresid.hxx" +#include "desktop.hrc" +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/XCurrentContext.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> + + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/ucb/XContentProviderManager.hpp> +#include <com/sun/star/ucb/XContentProviderFactory.hpp> +#include <uno/current_context.hxx> +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <osl/file.hxx> +#include <osl/module.h> +#include <osl/security.hxx> +#include <rtl/uri.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/bootstrap.hxx> +#include <comphelper/regpathhelper.hxx> +#include <tools/debug.hxx> +#include <tools/tempfile.hxx> +#include <ucbhelper/configurationkeys.hxx> + +#include <cppuhelper/bootstrap.hxx> +#include <tools/urlobj.hxx> +#include <tools/rcid.h> + +#include <rtl/logfile.hxx> +#include <rtl/instance.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/localfilehelper.hxx> +#include <unotools/ucbhelper.hxx> +#include <unotools/tempfile.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <vcl/svapp.hxx> +#include <unotools/startoptions.hxx> +#include <unotools/pathoptions.hxx> +#include <unotools/internaloptions.hxx> + + +#define DEFINE_CONST_OUSTRING(CONSTASCII) OUString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII)) + +#define DESKTOP_TEMPDIRNAME "soffice.tmp" + +using namespace desktop; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star::ucb; + +using ::rtl::OUString; + +namespace desktop +{ + +// ----------------------------------------------------------------------------- + +static bool configureUcb(bool bServer, rtl::OUString const & rPortalConnect) +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (sb93797) ::configureUcb" ); + Reference< XMultiServiceFactory > + xServiceFactory( comphelper::getProcessServiceFactory() ); + if (!xServiceFactory.is()) + { + OSL_FAIL("configureUcb(): No XMultiServiceFactory"); + return false; + } + + rtl::OUString aPipe; + osl::Security().getUserIdent(aPipe); + + rtl::OUStringBuffer aPortal; + if (rPortalConnect.getLength() != 0) + { + aPortal.append(sal_Unicode(',')); + aPortal.append(rPortalConnect); + } + + Sequence< Any > aArgs(6); + aArgs[0] + <<= bServer ? rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UCB_CONFIGURATION_KEY1_SERVER)) : + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UCB_CONFIGURATION_KEY1_LOCAL)); + aArgs[1] + <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UCB_CONFIGURATION_KEY2_OFFICE)); + aArgs[2] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PIPE")); + aArgs[3] <<= aPipe; + aArgs[4] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PORTAL")); + aArgs[5] <<= aPortal.makeStringAndClear(); + + bool ret = + ::ucbhelper::ContentBroker::initialize( xServiceFactory, aArgs ) != false; + +#ifdef GNOME_VFS_ENABLED + // register GnomeUCP if necessary + ::ucbhelper::ContentBroker* cb = ::ucbhelper::ContentBroker::get(); + if(cb) { + try { + Reference< XCurrentContext > xCurrentContext( + getCurrentContext()); + if (xCurrentContext.is()) + { + Any aValue = xCurrentContext->getValueByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "system.desktop-environment" ) ) + ); + rtl::OUString aDesktopEnvironment; + if ((aValue >>= aDesktopEnvironment) + && aDesktopEnvironment.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("GNOME"))) + { + Reference<XContentProviderManager> xCPM = + cb->getContentProviderManagerInterface(); + + + //Instanciate GNOME-VFS-UCP in the thread that initialized + // GNOME in order to avoid a deadlock that may occure in case UCP gets initialized from + // a different thread. The latter may happen when calling the Office remotely via UNO. + // THIS IS NOT A FIX, JUST A WORKAROUND! + + try + { + Reference<XContentProvider> xCP( + xServiceFactory->createInstance( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.ucb.GnomeVFSContentProvider"))), + UNO_QUERY); + if(xCP.is()) + xCPM->registerContentProvider( + xCP, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".*")), + false); + } catch (...) + { + } + } + } + } catch (RuntimeException &e) { + } + } +#endif // GNOME_VFS_ENABLED + + return ret;; +} + +Reference< XMultiServiceFactory > Desktop::CreateApplicationServiceManager() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::createApplicationServiceManager" ); + + try + { + Reference<XComponentContext> xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext(); + Reference<XMultiServiceFactory> xMS(xComponentContext->getServiceManager(), UNO_QUERY); + + return xMS; + } + catch( ::com::sun::star::uno::Exception& ) + { + } + + return Reference< XMultiServiceFactory >(); +} + +void Desktop::DestroyApplicationServiceManager( Reference< XMultiServiceFactory >& xSMgr ) +{ + Reference< XPropertySet > xProps( xSMgr, UNO_QUERY ); + if ( xProps.is() ) + { + try + { + Reference< XComponent > xComp; + if (xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xComp ) + { + xComp->dispose(); + } + } + catch ( UnknownPropertyException& ) + { + } + } +} + +void Desktop::RegisterServices( Reference< XMultiServiceFactory >& xSMgr ) +{ + if( !m_bServicesRegistered ) + { + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::registerServices" ); + + // read command line parameters + ::rtl::OUString conDcp; + ::rtl::OUString aClientDisplay; + ::rtl::OUString aTmpString; + sal_Bool bHeadlessMode = sal_False; + + // interpret command line arguments + CommandLineArgs& rCmdLine = GetCommandLineArgs(); + + // read accept string from configuration + conDcp = SvtStartOptions().GetConnectionURL(); + + if ( rCmdLine.GetAcceptString( aTmpString )) + conDcp = aTmpString; + + // Headless mode for FAT Office + bHeadlessMode = rCmdLine.IsHeadless(); + if ( bHeadlessMode ) + Application::EnableHeadlessMode(); + + if ( conDcp.getLength() > 0 ) + { + // accept incoming connections (scripting and one rvp) + RTL_LOGFILE_CONTEXT( aLog, "desktop (lo119109) desktop::Desktop::createAcceptor()" ); + createAcceptor(conDcp); + } + + // improves parallel processing on Sun ONE Webtop + // servicemanager up -> copy user installation + if ( rCmdLine.IsServer() ) + { + // Check some mandatory environment states if "-server" is possible. Otherwise ignore + // this parameter. + Reference< com::sun::star::container::XContentEnumerationAccess > rContent( xSMgr , UNO_QUERY ); + if( rContent.is() ) + { + OUString sPortalService = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.portal.InstallUser" ) ); + Reference < com::sun::star::container::XEnumeration > rEnum = rContent->createContentEnumeration( sPortalService ); + if ( !rEnum.is() ) + { + // Reset server parameter so it is ignored in the furthermore startup process + rCmdLine.SetBoolParam( CommandLineArgs::CMD_BOOLPARAM_SERVER, sal_False ); + } + } + } + + ::rtl::OUString aPortalConnect; + bool bServer = (bool)rCmdLine.IsServer(); + + rCmdLine.GetPortalConnectString( aPortalConnect ); + if ( !configureUcb( bServer, aPortalConnect ) ) + { + OSL_FAIL( "Can't configure UCB" ); + throw com::sun::star::uno::Exception(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RegisterServices, configureUcb")), NULL); + } + + CreateTemporaryDirectory(); + m_bServicesRegistered = true; + } +} + +namespace +{ + struct acceptorMap : public rtl::Static< AcceptorMap, acceptorMap > {}; + struct CurrentTempURL : public rtl::Static< String, CurrentTempURL > {}; +} + +static sal_Bool bAccept = sal_False; + +void Desktop::createAcceptor(const OUString& aAcceptString) +{ + // check whether the requested acceptor already exists + AcceptorMap &rMap = acceptorMap::get(); + AcceptorMap::const_iterator pIter = rMap.find(aAcceptString); + if (pIter == rMap.end() ) { + + Sequence< Any > aSeq( 2 ); + aSeq[0] <<= aAcceptString; + aSeq[1] <<= bAccept; + Reference<XInitialization> rAcceptor( + ::comphelper::getProcessServiceFactory()->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.office.Acceptor" ))), UNO_QUERY ); + if ( rAcceptor.is() ) { + try{ + rAcceptor->initialize( aSeq ); + rMap.insert(AcceptorMap::value_type(aAcceptString, rAcceptor)); + } catch (com::sun::star::uno::Exception&) { + // no error handling needed... + // acceptor just won't come up + OSL_FAIL("Acceptor could not be created."); + } + } else { + // there is already an acceptor with this description + OSL_FAIL("Acceptor already exists."); + } + + } +} + +class enable +{ + private: + Sequence<Any> m_aSeq; + public: + enable() : m_aSeq(1) { + m_aSeq[0] <<= sal_True; + } + void operator() (const AcceptorMap::value_type& val) { + if (val.second.is()) { + val.second->initialize(m_aSeq); + } + } +}; + +void Desktop::enableAcceptors() +{ + RTL_LOGFILE_CONTEXT(aLog, "desktop (lo119109) Desktop::enableAcceptors"); + if (!bAccept) + { + // from now on, all new acceptors are enabled + bAccept = sal_True; + // enable existing acceptors by calling initialize(true) + // on all existing acceptors + AcceptorMap &rMap = acceptorMap::get(); + std::for_each(rMap.begin(), rMap.end(), enable()); + } +} + +void Desktop::destroyAcceptor(const OUString& aAcceptString) +{ + // special case stop all acceptors + AcceptorMap &rMap = acceptorMap::get(); + if (aAcceptString.compareToAscii("all") == 0) { + rMap.clear(); + + } else { + // try to remove acceptor from map + AcceptorMap::const_iterator pIter = rMap.find(aAcceptString); + if (pIter != rMap.end() ) { + // remove reference from map + // this is the last reference and the acceptor will be destructed + rMap.erase(aAcceptString); + } else { + OSL_FAIL("Found no acceptor to remove"); + } + } +} + + +void Desktop::DeregisterServices() +{ + // stop all acceptors by clearing the map + acceptorMap::get().clear(); +} + +void Desktop::CreateTemporaryDirectory() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::createTemporaryDirectory" ); + + ::rtl::OUString aTempBaseURL; + try + { + SvtPathOptions aOpt; + aTempBaseURL = aOpt.GetTempPath(); + } + catch ( RuntimeException& e ) + { + // Catch runtime exception here: We have to add language dependent info + // to the exception message. Fallback solution uses hard coded string. + OUString aMsg; + DesktopResId aResId( STR_BOOTSTRAP_ERR_NO_PATHSET_SERVICE ); + aResId.SetRT( RSC_STRING ); + if ( aResId.GetResMgr()->IsAvailable( aResId )) + aMsg = String( aResId ); + else + aMsg = OUString( RTL_CONSTASCII_USTRINGPARAM( "The path manager is not available.\n" )); + e.Message = aMsg + e.Message; + throw; + } + + // remove possible old directory and base directory + SvtInternalOptions aInternalOpt; + + // set temp base directory + sal_Int32 nLength = aTempBaseURL.getLength(); + if ( aTempBaseURL.matchAsciiL( "/", 1, nLength-1 ) ) + aTempBaseURL = aTempBaseURL.copy( 0, nLength - 1 ); + + String aOldTempURL = aInternalOpt.GetCurrentTempURL(); + if ( aOldTempURL.Len() > 0 ) + { + // remove old temporary directory + ::utl::UCBContentHelper::Kill( aOldTempURL ); + } + + String aRet; + ::rtl::OUString aTempPath( aTempBaseURL ); + + // create new current temporary directory + ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTempBaseURL, aRet ); + ::osl::FileBase::getFileURLFromSystemPath( aRet, aTempPath ); + aTempPath = ::utl::TempFile::SetTempNameBaseDirectory( aTempPath ); + if ( !aTempPath.getLength() ) + { + ::osl::File::getTempDirURL( aTempBaseURL ); + + nLength = aTempBaseURL.getLength(); + if ( aTempBaseURL.matchAsciiL( "/", 1, nLength-1 ) ) + aTempBaseURL = aTempBaseURL.copy( 0, nLength - 1 ); + + aTempPath = aTempBaseURL; + ::osl::FileBase::getFileURLFromSystemPath( aRet, aTempPath ); + aTempPath = ::utl::TempFile::SetTempNameBaseDirectory( aTempPath ); + } + + // set new current temporary directory + ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aTempPath, aRet ); + aInternalOpt.SetCurrentTempURL( aRet ); + CurrentTempURL::get() = aRet; +} + +void Desktop::RemoveTemporaryDirectory() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::removeTemporaryDirectory" ); + + // remove current temporary directory + String &rCurrentTempURL = CurrentTempURL::get(); + if ( rCurrentTempURL.Len() > 0 ) + { + if ( ::utl::UCBContentHelper::Kill( rCurrentTempURL ) ) + SvtInternalOptions().SetCurrentTempURL( String() ); + } +} + +} // namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/appinit.hxx b/desktop/source/app/appinit.hxx new file mode 100644 index 000000000000..b4a756aa31ee --- /dev/null +++ b/desktop/source/app/appinit.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_APPINIT_HXX_ +#define _DESKTOP_APPINIT_HXX_ + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +namespace desktop +{ + +::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > createApplicationServiceManager(); + +sal_Bool InitializeInstallation( const rtl::OUString& rAppFilename ); +void registerServices( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xSMgr ); +void deregisterServices(); + +void destroyApplicationServiceManager( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xSMgr ); + +void createTemporaryDirectory(); +void removeTemporaryDirectory(); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/appsys.cxx b/desktop/source/app/appsys.cxx new file mode 100644 index 000000000000..47c7778e56e1 --- /dev/null +++ b/desktop/source/app/appsys.cxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "appsys.hxx" + +#ifdef WNT + +#include <rtl/ustring.hxx> +#include <tools/solar.h> +#include <tools/urlobj.hxx> + +#include <windows.h> + + +#define U2S(STRING) ::rtl::OUStringToOString(STRING, RTL_TEXTENCODING_UTF8) + +namespace desktop +{ + +void FATToVFat_Impl( String& aName ) +{ + INetURLObject aObj( aName ); + if ( aObj.GetProtocol() == INET_PROT_FILE ) + { + WIN32_FIND_DATA aData; + HANDLE h = FindFirstFile( U2S(aName).getStr(), &aData ); + if ( h ) + { + // Change FAT short filename into VFAT long filename + aObj.removeSegment(); + aObj.insertName( String::CreateFromAscii( aData.cFileName ) ); + aName = aObj.PathToFileName(); + FindClose( h ); + } + } +} + +} + +#endif // WNT + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/appsys.hxx b/desktop/source/app/appsys.hxx new file mode 100644 index 000000000000..d2f13ff0aace --- /dev/null +++ b/desktop/source/app/appsys.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_APPSYS_HXX_ +#define _DESKTOP_APPSYS_HXX_ + +#include <tools/string.hxx> + +namespace desktop +{ + +#ifdef WNT +void FATToVFat_Impl( String& aName ); +#endif + +} + +#endif // _DESKTOP_APPSYS_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/check_ext_deps.cxx b/desktop/source/app/check_ext_deps.cxx new file mode 100644 index 000000000000..fbc5136518c3 --- /dev/null +++ b/desktop/source/app/check_ext_deps.cxx @@ -0,0 +1,432 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "osl/file.hxx" +#include "osl/mutex.hxx" + +#include <rtl/bootstrap.hxx> +#include <rtl/ustring.hxx> +#include <rtl/logfile.hxx> +#include "cppuhelper/compbase3.hxx" + +#include "vcl/wrkwin.hxx" +#include "vcl/timer.hxx" + +#include <unotools/configmgr.hxx> +#include "toolkit/helper/vclunohelper.hxx" + +#include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/ui/LicenseDialog.hpp" +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/task/XJobExecutor.hpp> +#include <com/sun/star/task/XInteractionApprove.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" +#include <com/sun/star/util/XChangesBatch.hpp> + +#include "app.hxx" + +#include "../deployment/inc/dp_misc.h" + +using rtl::OUString; +using namespace desktop; +using namespace com::sun::star; + +#define UNISTRING(s) OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +namespace +{ +//For use with XExtensionManager.synchronize +class SilentCommandEnv + : public ::cppu::WeakImplHelper3< ucb::XCommandEnvironment, + task::XInteractionHandler, + ucb::XProgressHandler > +{ + Desktop *mpDesktop; + sal_Int32 mnLevel; + sal_Int32 mnProgress; + +public: + SilentCommandEnv( Desktop* pDesktop ); + virtual ~SilentCommandEnv(); + + // XCommandEnvironment + virtual uno::Reference<task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (uno::RuntimeException); + virtual uno::Reference<ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (uno::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + uno::Reference<task::XInteractionRequest > const & xRequest ) + throw (uno::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( uno::Any const & Status ) + throw (uno::RuntimeException); + virtual void SAL_CALL update( uno::Any const & Status ) + throw (uno::RuntimeException); + virtual void SAL_CALL pop() throw (uno::RuntimeException); +}; + +//----------------------------------------------------------------------------- +SilentCommandEnv::SilentCommandEnv( Desktop* pDesktop ) +{ + mpDesktop = pDesktop; + mnLevel = 0; + mnProgress = 25; +} + +//----------------------------------------------------------------------------- +SilentCommandEnv::~SilentCommandEnv() +{ + mpDesktop->SetSplashScreenText( OUString() ); +} + +//----------------------------------------------------------------------------- +Reference<task::XInteractionHandler> SilentCommandEnv::getInteractionHandler() + throw (uno::RuntimeException) +{ + return this; +} + +//----------------------------------------------------------------------------- +Reference<ucb::XProgressHandler> SilentCommandEnv::getProgressHandler() + throw (uno::RuntimeException) +{ + return this; +} + +//----------------------------------------------------------------------------- +// XInteractionHandler +void SilentCommandEnv::handle( Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + deployment::LicenseException licExc; + + uno::Any request( xRequest->getRequest() ); + bool bApprove = true; + + if ( request >>= licExc ) + { + uno::Reference< uno::XComponentContext > xContext = comphelper_getProcessComponentContext(); + uno::Reference< ui::dialogs::XExecutableDialog > xDialog( + deployment::ui::LicenseDialog::create( + xContext, VCLUnoHelper::GetInterface( NULL ), + licExc.ExtensionName, licExc.Text ) ); + sal_Int16 res = xDialog->execute(); + if ( res == ui::dialogs::ExecutableDialogResults::CANCEL ) + bApprove = false; + else if ( res == ui::dialogs::ExecutableDialogResults::OK ) + bApprove = true; + else + { + OSL_ASSERT(0); + } + } + + // We approve everything here + uno::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 ( bApprove ) + { + uno::Reference< task::XInteractionApprove > xInteractionApprove( pConts[ pos ], uno::UNO_QUERY ); + if ( xInteractionApprove.is() ) + xInteractionApprove->select(); + } + else + { + uno::Reference< task::XInteractionAbort > xInteractionAbort( pConts[ pos ], uno::UNO_QUERY ); + if ( xInteractionAbort.is() ) + xInteractionAbort->select(); + } + } +} + +//----------------------------------------------------------------------------- +// XProgressHandler +void SilentCommandEnv::push( uno::Any const & rStatus ) + throw (uno::RuntimeException) +{ + OUString sText; + mnLevel += 1; + + if ( rStatus.hasValue() && ( rStatus >>= sText) ) + { + if ( mnLevel <= 3 ) + mpDesktop->SetSplashScreenText( sText ); + else + mpDesktop->SetSplashScreenProgress( ++mnProgress ); + } +} + +//----------------------------------------------------------------------------- +void SilentCommandEnv::update( uno::Any const & rStatus ) + throw (uno::RuntimeException) +{ + OUString sText; + if ( rStatus.hasValue() && ( rStatus >>= sText) ) + { + mpDesktop->SetSplashScreenText( sText ); + } +} + +//----------------------------------------------------------------------------- +void SilentCommandEnv::pop() throw (uno::RuntimeException) +{ + mnLevel -= 1; +} + +} // end namespace + +//----------------------------------------------------------------------------- +static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); +static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ); +//------------------------------------------------------------------------------ +static sal_Int16 impl_showExtensionDialog( uno::Reference< uno::XComponentContext > &xContext ) +{ + rtl::OUString sServiceName = UNISTRING("com.sun.star.deployment.ui.UpdateRequiredDialog"); + uno::Reference< uno::XInterface > xService; + sal_Int16 nRet = 0; + + uno::Reference< lang::XMultiComponentFactory > xServiceManager( xContext->getServiceManager() ); + if( !xServiceManager.is() ) + throw uno::RuntimeException( + UNISTRING( "impl_showExtensionDialog(): unable to obtain service manager from component context" ), uno::Reference< uno::XInterface > () ); + + xService = xServiceManager->createInstanceWithContext( sServiceName, xContext ); + uno::Reference< ui::dialogs::XExecutableDialog > xExecuteable( xService, uno::UNO_QUERY ); + if ( xExecuteable.is() ) + nRet = xExecuteable->execute(); + + return nRet; +} + +//------------------------------------------------------------------------------ +// Check dependencies of all packages +//------------------------------------------------------------------------------ +static bool impl_checkDependencies( const uno::Reference< uno::XComponentContext > &xContext ) +{ + uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages; + uno::Reference< deployment::XExtensionManager > xExtensionManager = deployment::ExtensionManager::get( xContext ); + + if ( !xExtensionManager.is() ) + { + OSL_FAIL( "Could not get the Extension Manager!" ); + return true; + } + + try { + xAllPackages = xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(), + uno::Reference< ucb::XCommandEnvironment >() ); + } + catch ( deployment::DeploymentException & ) { return true; } + catch ( ucb::CommandFailedException & ) { return true; } + catch ( ucb::CommandAbortedException & ) { return true; } + catch ( lang::IllegalArgumentException & e ) { + throw uno::RuntimeException( e.Message, e.Context ); + } + + sal_Int32 nMax = 2; +#ifdef DEBUG + nMax = 3; +#endif + + for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i ) + { + uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i]; + + for ( sal_Int32 j = 0; (j<nMax) && (j < xPackageList.getLength()); ++j ) + { + uno::Reference< deployment::XPackage > xPackage = xPackageList[j]; + if ( xPackage.is() ) + { + bool bRegistered = false; + try { + beans::Optional< beans::Ambiguous< sal_Bool > > option( xPackage->isRegistered( uno::Reference< task::XAbortChannel >(), + uno::Reference< ucb::XCommandEnvironment >() ) ); + if ( option.IsPresent ) + { + ::beans::Ambiguous< sal_Bool > const & reg = option.Value; + if ( reg.IsAmbiguous ) + bRegistered = false; + else + bRegistered = reg.Value ? true : false; + } + else + bRegistered = false; + } + catch ( uno::RuntimeException & ) { throw; } + catch ( uno::Exception & exc) { + (void) exc; + OSL_FAIL( ::rtl::OUStringToOString( exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + if ( bRegistered ) + { + bool bDependenciesValid = false; + try { + bDependenciesValid = xPackage->checkDependencies( uno::Reference< ucb::XCommandEnvironment >() ); + } + catch ( deployment::DeploymentException & ) {} + if ( ! bDependenciesValid ) + { + return false; + } + } + } + } + } + return true; +} + +//------------------------------------------------------------------------------ +// resets the 'check needed' flag (needed, if aborted) +//------------------------------------------------------------------------------ +static void impl_setNeedsCompatCheck() +{ + try { + Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + // get configuration provider + Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >( + xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW); + + Sequence< Any > theArgs(1); + beans::NamedValue v( OUString(RTL_CONSTASCII_USTRINGPARAM("NodePath")), + makeAny( OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Setup/Office")) ) ); + theArgs[0] <<= v; + Reference< beans::XPropertySet > pset = Reference< beans::XPropertySet >( + theConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY_THROW ); + + Any value = makeAny( OUString(RTL_CONSTASCII_USTRINGPARAM("never")) ); + + pset->setPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("LastCompatibilityCheckID")), value ); + Reference< util::XChangesBatch >( pset, UNO_QUERY_THROW )->commitChanges(); + } + catch (const Exception&) {} +} + +//------------------------------------------------------------------------------ +static bool impl_check() +{ + uno::Reference< uno::XComponentContext > xContext = comphelper_getProcessComponentContext(); + + bool bDependenciesValid = impl_checkDependencies( xContext ); + + short nRet = 0; + + if ( !bDependenciesValid ) + nRet = impl_showExtensionDialog( xContext ); + + if ( nRet == -1 ) + { + impl_setNeedsCompatCheck(); + return true; + } + else + return false; +} + +//------------------------------------------------------------------------------ +// to check if we need checking the dependencies of the extensions again, we compare +// the build id of the office with the one of the last check +//------------------------------------------------------------------------------ +static bool impl_needsCompatCheck() +{ + bool bNeedsCheck = false; + rtl::OUString aLastCheckBuildID; + rtl::OUString aCurrentBuildID( UNISTRING( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" ) ); + rtl::Bootstrap::expandMacros( aCurrentBuildID ); + + try { + Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + // get configuration provider + Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >( + xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW); + + Sequence< Any > theArgs(1); + beans::NamedValue v( OUString(RTL_CONSTASCII_USTRINGPARAM("NodePath")), + makeAny( OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Setup/Office")) ) ); + theArgs[0] <<= v; + Reference< beans::XPropertySet > pset = Reference< beans::XPropertySet >( + theConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY_THROW ); + + Any result = pset->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("LastCompatibilityCheckID")) ); + + result >>= aLastCheckBuildID; + if ( aLastCheckBuildID != aCurrentBuildID ) + { + bNeedsCheck = true; + result <<= aCurrentBuildID; + pset->setPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("LastCompatibilityCheckID")), result ); + Reference< util::XChangesBatch >( pset, UNO_QUERY_THROW )->commitChanges(); + } +#ifdef DEBUG + bNeedsCheck = true; +#endif + } + catch (const Exception&) {} + + return bNeedsCheck; +} + +//------------------------------------------------------------------------------ +// Do we need to check the dependencies of the extensions? +// When there are unresolved issues, we can't continue with startup +sal_Bool Desktop::CheckExtensionDependencies() +{ + sal_Bool bAbort = false; + + if ( impl_needsCompatCheck() ) + bAbort = impl_check(); + + return bAbort; +} + +void Desktop::SynchronizeExtensionRepositories() +{ + RTL_LOGFILE_CONTEXT(aLog,"desktop (jl) ::Desktop::SynchronizeExtensionRepositories"); + dp_misc::syncRepositories( new SilentCommandEnv( this ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx new file mode 100644 index 000000000000..6885021718bc --- /dev/null +++ b/desktop/source/app/cmdlineargs.cxx @@ -0,0 +1,1008 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <cmdlineargs.hxx> +#include <vcl/svapp.hxx> +#include <rtl/uri.hxx> +#include <rtl/ustring.hxx> +#include "rtl/process.h" +#include <comphelper/processfactory.hxx> +#include <com/sun/star/uri/XExternalUriReferenceTranslator.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include "tools/getprocessworkingdir.hxx" + +#include <svl/documentlockfile.hxx> + +#include <cstdio> + +using namespace com::sun::star::lang; +using namespace com::sun::star::uri; +using namespace com::sun::star::uno; + +using ::rtl::OUString; + +namespace desktop +{ + +namespace { + +class ExtCommandLineSupplier: public CommandLineArgs::Supplier { +public: + explicit ExtCommandLineSupplier(): + m_count(rtl_getAppCommandArgCount()), + m_index(0) + { + rtl::OUString url; + if (tools::getProcessWorkingDir(url)) { + m_cwdUrl.reset(url); + } + } + + virtual ~ExtCommandLineSupplier() {} + + virtual boost::optional< rtl::OUString > getCwdUrl() { return m_cwdUrl; } + + virtual bool next(rtl::OUString * argument) { + OSL_ASSERT(argument != NULL); + if (m_index < m_count) { + rtl_getAppCommandArg(m_index++, &argument->pData); + return true; + } else { + return false; + } + } + +private: + boost::optional< rtl::OUString > m_cwdUrl; + sal_uInt32 m_count; + sal_uInt32 m_index; +}; + +} + +static CommandLineArgs::BoolParam aModuleGroupDefinition[] = +{ + CommandLineArgs::CMD_BOOLPARAM_WRITER, + CommandLineArgs::CMD_BOOLPARAM_CALC, + CommandLineArgs::CMD_BOOLPARAM_DRAW, + CommandLineArgs::CMD_BOOLPARAM_IMPRESS, + CommandLineArgs::CMD_BOOLPARAM_GLOBAL, + CommandLineArgs::CMD_BOOLPARAM_MATH, + CommandLineArgs::CMD_BOOLPARAM_WEB, + CommandLineArgs::CMD_BOOLPARAM_BASE +}; + +CommandLineArgs::GroupDefinition CommandLineArgs::m_pGroupDefinitions[ CommandLineArgs::CMD_GRPID_COUNT ] = +{ + { 8, aModuleGroupDefinition } +}; + +CommandLineArgs::Supplier::Exception::Exception() {} + +CommandLineArgs::Supplier::Exception::Exception(Exception const &) {} + +CommandLineArgs::Supplier::Exception::~Exception() {} + +CommandLineArgs::Supplier::Exception & +CommandLineArgs::Supplier::Exception::operator =(Exception const &) +{ return *this; } + +CommandLineArgs::Supplier::~Supplier() {} + +// intialize class with command line parameters from process environment +CommandLineArgs::CommandLineArgs() +{ + ResetParamValues(); + ExtCommandLineSupplier s; + ParseCommandLine_Impl( s ); +} + +CommandLineArgs::CommandLineArgs( Supplier& supplier ) +{ + ResetParamValues(); + ParseCommandLine_Impl( supplier ); +} + +// ---------------------------------------------------------------------------- + +void CommandLineArgs::ParseCommandLine_Impl( Supplier& supplier ) +{ + m_cwdUrl = supplier.getCwdUrl(); + Reference<XMultiServiceFactory> xMS(comphelper::getProcessServiceFactory(), UNO_QUERY); + OSL_ENSURE(xMS.is(), "CommandLineArgs: no ProcessServiceFactory."); + + Reference< XExternalUriReferenceTranslator > xTranslator( + xMS->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.uri.ExternalUriReferenceTranslator"))), + UNO_QUERY); + + // parse command line arguments + bool bOpenEvent(true); + bool bPrintEvent(false); + bool bViewEvent(false); + bool bStartEvent(false); + bool bPrintToEvent(false); + bool bPrinterName(false); + bool bForceOpenEvent(false); + bool bForceNewEvent(false); + bool bDisplaySpec(false); + bool bOpenDoc(false); + bool bConversionEvent(false); + bool bConversionParamsEvent(false); + bool bBatchPrintEvent(false); + bool bBatchPrinterNameEvent(false); + bool bConversionOutEvent(false); + + m_eArgumentCount = NONE; + + for (;;) + { + ::rtl::OUString aArg; + if ( !supplier.next( &aArg ) ) + { + break; + } + // convert file URLs to internal form + if (aArg.indexOfAsciiL(RTL_CONSTASCII_STRINGPARAM("file:"))==0 && + xTranslator.is()) + { + OUString tmp(xTranslator->translateToInternal(aArg)); + if (tmp.getLength() > 0) + aArg = tmp; + } + + if ( aArg.getLength() > 0 ) + { + m_eArgumentCount = m_eArgumentCount == NONE ? ONE : MANY; + ::rtl::OUString oArg; + if ( !InterpretCommandLineParameter( aArg, oArg )) + { + if ( aArg.toChar() == '-' ) + { + // handle this argument as an option + if ( aArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("-n"))) + { + // force new documents based on the following documents + bForceNewEvent = true; + bOpenEvent = false; + bForceOpenEvent = false; + bPrintToEvent = false; + bPrintEvent = false; + bViewEvent = false; + bStartEvent = false; + bDisplaySpec = false; + } + else if ( aArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM( "-o" ))) + { + // force open documents regardless if they are templates or not + bForceOpenEvent = true; + bOpenEvent = false; + bForceNewEvent = false; + bPrintToEvent = false; + bPrintEvent = false; + bViewEvent = false; + bStartEvent = false; + bDisplaySpec = false; + } + else if ( aArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM( "-pt" ))) + { + // Print to special printer + bPrintToEvent = true; + bPrinterName = true; + bPrintEvent = false; + bOpenEvent = false; + bForceNewEvent = false; + bViewEvent = false; + bStartEvent = false; + bDisplaySpec = false; + bForceOpenEvent = false; + } + else if ( aArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM( "-p" ))) + { + // Print to default printer + bPrintEvent = true; + bPrintToEvent = false; + bOpenEvent = false; + bForceNewEvent = false; + bForceOpenEvent = false; + bViewEvent = false; + bStartEvent = false; + bDisplaySpec = false; + } + else if ( aArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM( "-view" ))) + { + // open in viewmode + bOpenEvent = false; + bPrintEvent = false; + bPrintToEvent = false; + bForceNewEvent = false; + bForceOpenEvent = false; + bViewEvent = true; + bStartEvent = false; + bDisplaySpec = false; + } + else if ( aArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM( "-show" ))) + { + // open in viewmode + bOpenEvent = false; + bViewEvent = false; + bStartEvent = true; + bPrintEvent = false; + bPrintToEvent = false; + bForceNewEvent = false; + bForceOpenEvent = false; + bDisplaySpec = false; + } + else if ( oArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("display"))) + { + // set display + bOpenEvent = false; + bPrintEvent = false; + bForceOpenEvent = false; + bPrintToEvent = false; + bForceNewEvent = false; + bViewEvent = false; + bStartEvent = false; + bDisplaySpec = true; + } + else if ( oArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("language"))) + { + bOpenEvent = false; + bPrintEvent = false; + bForceOpenEvent = false; + bPrintToEvent = false; + bForceNewEvent = false; + bViewEvent = false; + bStartEvent = false; + bDisplaySpec = false; + } + else if ( oArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("convert-to"))) + { + bOpenEvent = false; + bConversionEvent = true; + bConversionParamsEvent = true; + } + else if ( oArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("print-to-file"))) + { + bOpenEvent = false; + bBatchPrintEvent = true; + } + else if ( oArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("printer-name")) && + bBatchPrintEvent ) + { + bBatchPrinterNameEvent = true; + } + else if ( oArg.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("outdir")) && + (bConversionEvent || bBatchPrintEvent) ) + { + bConversionOutEvent = true; + } + } + else + { + if ( bPrinterName && bPrintToEvent ) + { + // first argument after "-pt" this must be the printer name + AddStringListParam_Impl( CMD_STRINGPARAM_PRINTERNAME, aArg ); + bPrinterName = false; + } + else if ( bConversionParamsEvent && bConversionEvent ) + { + // first argument must be the the params + AddStringListParam_Impl( CMD_STRINGPARAM_CONVERSIONPARAMS, aArg ); + bConversionParamsEvent = false; + } + else if ( bBatchPrinterNameEvent && bBatchPrintEvent ) + { + // first argument is the printer name + AddStringListParam_Impl( CMD_STRINGPARAM_PRINTERNAME, aArg ); + bBatchPrinterNameEvent = false; + } + else if ( (bConversionEvent || bBatchPrintEvent) && bConversionOutEvent ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_CONVERSIONOUT, aArg ); + bConversionOutEvent = false; + } + else + { + if( bOpenEvent || bViewEvent || bForceNewEvent || bForceOpenEvent ) + { + if( aArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("::ODMA")) ) + { + ::rtl::OUString sArg(RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.odma:/")); + sArg += aArg; + aArg = sArg; + } + } + // handle this argument as a filename + if ( bOpenEvent ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_OPENLIST, aArg ); + bOpenDoc = true; + } + else if ( bViewEvent ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_VIEWLIST, aArg ); + bOpenDoc = true; + } + else if ( bStartEvent ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_STARTLIST, aArg ); + bOpenDoc = true; + } + else if ( bPrintEvent ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_PRINTLIST, aArg ); + bOpenDoc = true; + } + else if ( bPrintToEvent ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_PRINTTOLIST, aArg ); + bOpenDoc = true; + } + else if ( bForceNewEvent ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_FORCENEWLIST, aArg ); + bOpenDoc = true; + } + else if ( bForceOpenEvent ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_FORCEOPENLIST, aArg ); + bOpenDoc = true; + } + else if ( bDisplaySpec ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_DISPLAY, aArg ); + bDisplaySpec = false; // only one display, not a lsit + bOpenEvent = true; // set back to standard + } + else if ( bConversionEvent || bBatchPrintEvent ) + AddStringListParam_Impl( CMD_STRINGPARAM_CONVERSIONLIST, aArg ); + } + } + } + } + } + + if ( bOpenDoc ) + m_bDocumentArgs = true; +} + +void CommandLineArgs::AddStringListParam_Impl( StringParam eParam, const rtl::OUString& aParam ) +{ + OSL_ASSERT( eParam >= 0 && eParam < CMD_STRINGPARAM_COUNT ); + if ( m_aStrParams[eParam].getLength() ) + m_aStrParams[eParam] += ::rtl::OUString::valueOf( (sal_Unicode)APPEVENT_PARAM_DELIMITER ); + m_aStrParams[eParam] += aParam; + m_aStrSetParams[eParam] = sal_True; +} + +void CommandLineArgs::SetBoolParam_Impl( BoolParam eParam, sal_Bool bValue ) +{ + OSL_ASSERT( eParam >= 0 && eParam < CMD_BOOLPARAM_COUNT ); + m_aBoolParams[eParam] = bValue; +} + +sal_Bool CommandLineArgs::InterpretCommandLineParameter( const ::rtl::OUString& aArg, ::rtl::OUString& oArg ) +{ + bool bDeprecated = false; + if (aArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("--"))) + { + oArg = ::rtl::OUString(aArg.getStr()+2, aArg.getLength()-2); + } + else if (aArg.toChar() == '-') + { + bDeprecated = true; + oArg = ::rtl::OUString(aArg.getStr()+1, aArg.getLength()-1); + } + else + { + return sal_False; + } + + if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "minimized" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_MINIMIZED, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "invisible" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_INVISIBLE, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "norestore" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NORESTORE, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "nodefault" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NODEFAULT, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "bean" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_BEAN, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "plugin" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_PLUGIN, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "server" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_SERVER, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "headless" )) == sal_True ) + { + // Headless means also invisibile, so set this parameter to true! + SetBoolParam_Impl( CMD_BOOLPARAM_HEADLESS, sal_True ); + SetBoolParam_Impl( CMD_BOOLPARAM_INVISIBLE, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "quickstart" )) == sal_True ) + { +#if defined(ENABLE_QUICKSTART_APPLET) + SetBoolParam_Impl( CMD_BOOLPARAM_QUICKSTART, sal_True ); +#endif + SetBoolParam_Impl( CMD_BOOLPARAM_NOQUICKSTART, sal_False ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "quickstart=no" ))) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NOQUICKSTART, sal_True ); + SetBoolParam_Impl( CMD_BOOLPARAM_QUICKSTART, sal_False ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "terminate_after_init" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_TERMINATEAFTERINIT, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "nofirststartwizard" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NOFIRSTSTARTWIZARD, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "nologo" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NOLOGO, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "nolockcheck" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NOLOCKCHECK, sal_True ); + // Workaround for automated testing + ::svt::DocumentLockFile::AllowInteraction( sal_False ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "help" )) + || aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-h" )) + || aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-?" ))) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELP, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "helpwriter" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPWRITER, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "helpcalc" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPCALC, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "helpdraw" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPDRAW, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "helpimpress" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPIMPRESS, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "helpbase" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPBASE, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "helpbasic" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPBASIC, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "helpmath" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPMATH, sal_True ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "version" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_VERSION, sal_True ); + } + else if ( oArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("splash-pipe=")) ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_SPLASHPIPE, oArg.copy(RTL_CONSTASCII_LENGTH("splash-pipe=")) ); + } +#ifdef MACOSX + /* #i84053# ignore -psn on Mac + Platform dependent #ifdef here is ugly, however this is currently + the only platform dependent parameter. Should more appear + we should find a better solution + */ + else if ( aArg.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("-psn")) ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_PSN, sal_True ); + return sal_True; + } +#endif + else if ( oArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("infilter="))) + { + AddStringListParam_Impl( CMD_STRINGPARAM_INFILTER, oArg.copy(RTL_CONSTASCII_LENGTH("infilter=")) ); + } + else if ( oArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("accept="))) + { + AddStringListParam_Impl( CMD_STRINGPARAM_ACCEPT, oArg.copy(RTL_CONSTASCII_LENGTH("accept=")) ); + } + else if ( oArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("unaccept="))) + { + AddStringListParam_Impl( CMD_STRINGPARAM_UNACCEPT, oArg.copy(RTL_CONSTASCII_LENGTH("unaccept=")) ); + } + else if ( oArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("portal,"))) + { + AddStringListParam_Impl( CMD_STRINGPARAM_PORTAL, oArg.copy(RTL_CONSTASCII_LENGTH("portal,")) ); + } + else if ( oArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("userid"))) + { + if ( oArg.getLength() > RTL_CONSTASCII_LENGTH("userid")+1 ) + { + AddStringListParam_Impl( + CMD_STRINGPARAM_USERDIR, + ::rtl::Uri::decode( oArg.copy(RTL_CONSTASCII_LENGTH("userid")+1), + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8 ) ); + } + } + else if ( oArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("clientdisplay="))) + { + AddStringListParam_Impl( CMD_STRINGPARAM_CLIENTDISPLAY, oArg.copy(RTL_CONSTASCII_LENGTH("clientdisplay=")) ); + } + else if ( oArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("version="))) + { + AddStringListParam_Impl( CMD_STRINGPARAM_VERSION, oArg.copy(RTL_CONSTASCII_LENGTH("version=")) ); + } + else if ( oArg.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("language="))) + { + AddStringListParam_Impl( CMD_STRINGPARAM_LANGUAGE, oArg.copy(RTL_CONSTASCII_LENGTH("language=")) ); + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "writer" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_WRITER ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_WRITER, sal_True ); + m_bDocumentArgs = true; + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "calc" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_CALC ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_CALC, sal_True ); + m_bDocumentArgs = true; + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "draw" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_DRAW ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_DRAW, sal_True ); + m_bDocumentArgs = true; + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "impress" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_IMPRESS ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_IMPRESS, sal_True ); + m_bDocumentArgs = true; + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "base" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_BASE ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_BASE, sal_True ); + m_bDocumentArgs = true; + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "global" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_GLOBAL ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_GLOBAL, sal_True ); + m_bDocumentArgs = true; + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "math" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_MATH ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_MATH, sal_True ); + m_bDocumentArgs = true; + } + else if ( oArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "web" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_WEB ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_WEB, sal_True ); + m_bDocumentArgs = true; + } + else + return sal_False; + + if (bDeprecated) + { + rtl::OString sArg(rtl::OUStringToOString(aArg, RTL_TEXTENCODING_UTF8)); + fprintf(stderr, "Warning: %s is deprecated. Use -%s instead.\n", sArg.getStr(), sArg.getStr()); + } + return sal_True; +} + +sal_Bool CommandLineArgs::CheckGroupMembers( GroupParamId nGroupId, BoolParam nExcludeMember ) const +{ + // Check if at least one bool param out of a group is set. An exclude member can be provided. + for ( int i = 0; i < m_pGroupDefinitions[nGroupId].nCount; i++ ) + { + BoolParam nParam = m_pGroupDefinitions[nGroupId].pGroupMembers[i]; + if ( nParam != nExcludeMember && m_aBoolParams[nParam] ) + return sal_True; + } + + return sal_False; +} + +void CommandLineArgs::ResetParamValues() +{ + int i; + for ( i = 0; i < CMD_BOOLPARAM_COUNT; i++ ) + m_aBoolParams[i] = sal_False; + for ( i = 0; i < CMD_STRINGPARAM_COUNT; i++ ) + m_aStrSetParams[i] = sal_False; + m_eArgumentCount = NONE; + m_bDocumentArgs = false; +} + +void CommandLineArgs::SetBoolParam( BoolParam eParam, sal_Bool bNewValue ) +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + + OSL_ASSERT( ( eParam >= 0 && eParam < CMD_BOOLPARAM_COUNT ) ); + m_aBoolParams[eParam] = bNewValue; +} + +const rtl::OUString& CommandLineArgs::GetStringParam( StringParam eParam ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + + OSL_ASSERT( ( eParam >= 0 && eParam < CMD_STRINGPARAM_COUNT ) ); + return m_aStrParams[eParam]; +} + +sal_Bool CommandLineArgs::IsMinimized() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_MINIMIZED ]; +} + +sal_Bool CommandLineArgs::IsInvisible() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_INVISIBLE ]; +} + +sal_Bool CommandLineArgs::IsNoRestore() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NORESTORE ]; +} + +sal_Bool CommandLineArgs::IsNoDefault() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NODEFAULT ]; +} + +sal_Bool CommandLineArgs::IsBean() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_BEAN ]; +} + +sal_Bool CommandLineArgs::IsServer() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_SERVER ]; +} + +sal_Bool CommandLineArgs::IsHeadless() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HEADLESS ]; +} + +sal_Bool CommandLineArgs::IsQuickstart() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_QUICKSTART ]; +} + +sal_Bool CommandLineArgs::IsNoQuickstart() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NOQUICKSTART ]; +} + +sal_Bool CommandLineArgs::IsTerminateAfterInit() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_TERMINATEAFTERINIT ]; +} + +sal_Bool CommandLineArgs::IsNoLogo() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NOLOGO ]; +} + +sal_Bool CommandLineArgs::IsNoLockcheck() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NOLOCKCHECK ]; +} + +sal_Bool CommandLineArgs::IsHelp() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELP ]; +} +sal_Bool CommandLineArgs::IsHelpWriter() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPWRITER ]; +} + +sal_Bool CommandLineArgs::IsHelpCalc() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPCALC ]; +} + +sal_Bool CommandLineArgs::IsHelpDraw() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPDRAW ]; +} + +sal_Bool CommandLineArgs::IsHelpImpress() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPIMPRESS ]; +} + +sal_Bool CommandLineArgs::IsHelpBase() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPBASE ]; +} +sal_Bool CommandLineArgs::IsHelpMath() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPMATH ]; +} +sal_Bool CommandLineArgs::IsHelpBasic() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPBASIC ]; +} + +sal_Bool CommandLineArgs::IsWriter() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_WRITER ]; +} + +sal_Bool CommandLineArgs::IsCalc() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_CALC ]; +} + +sal_Bool CommandLineArgs::IsDraw() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_DRAW ]; +} + +sal_Bool CommandLineArgs::IsImpress() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_IMPRESS ]; +} + +sal_Bool CommandLineArgs::IsBase() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_BASE ]; +} + +sal_Bool CommandLineArgs::IsGlobal() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_GLOBAL ]; +} + +sal_Bool CommandLineArgs::IsMath() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_MATH ]; +} + +sal_Bool CommandLineArgs::IsWeb() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_WEB ]; +} + +sal_Bool CommandLineArgs::IsVersion() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_VERSION ]; +} + +sal_Bool CommandLineArgs::HasModuleParam() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_COUNT ); +} + +sal_Bool CommandLineArgs::GetPortalConnectString( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_PORTAL ]; + return m_aStrSetParams[ CMD_STRINGPARAM_PORTAL ]; +} + +sal_Bool CommandLineArgs::GetAcceptString( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_ACCEPT ]; + return m_aStrSetParams[ CMD_STRINGPARAM_ACCEPT ]; +} + +sal_Bool CommandLineArgs::GetUnAcceptString( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_UNACCEPT ]; + return m_aStrSetParams[ CMD_STRINGPARAM_UNACCEPT ]; +} + +sal_Bool CommandLineArgs::GetOpenList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_OPENLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_OPENLIST ]; +} + +sal_Bool CommandLineArgs::GetViewList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_VIEWLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_VIEWLIST ]; +} + +sal_Bool CommandLineArgs::GetStartList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_STARTLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_STARTLIST ]; +} + +sal_Bool CommandLineArgs::GetForceOpenList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_FORCEOPENLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_FORCEOPENLIST ]; +} + +sal_Bool CommandLineArgs::GetForceNewList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_FORCENEWLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_FORCENEWLIST ]; +} + +sal_Bool CommandLineArgs::GetPrintList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_PRINTLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_PRINTLIST ]; +} + +sal_Bool CommandLineArgs::GetPrintToList( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_PRINTTOLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_PRINTTOLIST ]; +} + +sal_Bool CommandLineArgs::GetPrinterName( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_PRINTERNAME ]; + return m_aStrSetParams[ CMD_STRINGPARAM_PRINTERNAME ]; +} + +sal_Bool CommandLineArgs::GetLanguage( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_LANGUAGE ]; + return m_aStrSetParams[ CMD_STRINGPARAM_LANGUAGE ]; +} + +sal_Bool CommandLineArgs::GetInFilter( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_INFILTER ]; + return m_aStrSetParams[ CMD_STRINGPARAM_INFILTER ]; +} + +sal_Bool CommandLineArgs::GetConversionList( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_CONVERSIONLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_CONVERSIONLIST ]; +} + +sal_Bool CommandLineArgs::GetConversionParams( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_CONVERSIONPARAMS ]; + return m_aStrSetParams[ CMD_STRINGPARAM_CONVERSIONPARAMS ]; +} +sal_Bool CommandLineArgs::GetConversionOut( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_CONVERSIONOUT ]; + return m_aStrSetParams[ CMD_STRINGPARAM_CONVERSIONOUT ]; +} + +sal_Bool CommandLineArgs::IsEmpty() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_eArgumentCount == NONE; +} + +sal_Bool CommandLineArgs::IsEmptyOrAcceptOnly() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + + return m_eArgumentCount == NONE || + ( ( m_eArgumentCount == ONE ) && ( m_aStrParams[ CMD_STRINGPARAM_SPLASHPIPE ].getLength() )) || + ( ( m_eArgumentCount == ONE ) && ( m_aStrParams[ CMD_STRINGPARAM_ACCEPT ].getLength() )) || + ( ( m_eArgumentCount == ONE ) && m_aBoolParams[ CMD_BOOLPARAM_PSN ] ); +} + +sal_Bool CommandLineArgs::WantsToLoadDocument() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_bDocumentArgs; +} + +} // namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/cmdlineargs.hxx b/desktop/source/app/cmdlineargs.hxx new file mode 100644 index 000000000000..bd7e24a81147 --- /dev/null +++ b/desktop/source/app/cmdlineargs.hxx @@ -0,0 +1,230 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_COMMANDLINEARGS_HXX_ +#define _DESKTOP_COMMANDLINEARGS_HXX_ + +#include <rtl/ustring.hxx> +#include <osl/mutex.hxx> +#include "boost/optional.hpp" + +namespace desktop +{ + +class CommandLineArgs +{ + public: + enum BoolParam // must be zero based! + { + CMD_BOOLPARAM_MINIMIZED = 0, + CMD_BOOLPARAM_INVISIBLE, + CMD_BOOLPARAM_NORESTORE, + CMD_BOOLPARAM_BEAN, + CMD_BOOLPARAM_PLUGIN, + CMD_BOOLPARAM_SERVER, + CMD_BOOLPARAM_HEADLESS, + CMD_BOOLPARAM_QUICKSTART, + CMD_BOOLPARAM_NOQUICKSTART, + CMD_BOOLPARAM_TERMINATEAFTERINIT, + CMD_BOOLPARAM_NOFIRSTSTARTWIZARD, + CMD_BOOLPARAM_NOLOGO, + CMD_BOOLPARAM_NOLOCKCHECK, + CMD_BOOLPARAM_NODEFAULT, + CMD_BOOLPARAM_HELP, + CMD_BOOLPARAM_WRITER, + CMD_BOOLPARAM_CALC, + CMD_BOOLPARAM_DRAW, + CMD_BOOLPARAM_IMPRESS, + CMD_BOOLPARAM_GLOBAL, + CMD_BOOLPARAM_MATH, + CMD_BOOLPARAM_WEB, + CMD_BOOLPARAM_BASE, + CMD_BOOLPARAM_HELPWRITER, + CMD_BOOLPARAM_HELPCALC, + CMD_BOOLPARAM_HELPDRAW, + CMD_BOOLPARAM_HELPBASIC, + CMD_BOOLPARAM_HELPMATH, + CMD_BOOLPARAM_HELPIMPRESS, + CMD_BOOLPARAM_HELPBASE, + CMD_BOOLPARAM_PSN, + CMD_BOOLPARAM_VERSION, + CMD_BOOLPARAM_COUNT // must be last element! + }; + + enum StringParam // must be zero based! + { + CMD_STRINGPARAM_PORTAL = 0, + CMD_STRINGPARAM_SPLASHPIPE, + CMD_STRINGPARAM_ACCEPT, + CMD_STRINGPARAM_UNACCEPT, + CMD_STRINGPARAM_USERDIR, + CMD_STRINGPARAM_CLIENTDISPLAY, + CMD_STRINGPARAM_OPENLIST, + CMD_STRINGPARAM_VIEWLIST, + CMD_STRINGPARAM_STARTLIST, + CMD_STRINGPARAM_FORCEOPENLIST, + CMD_STRINGPARAM_FORCENEWLIST, + CMD_STRINGPARAM_PRINTLIST, + CMD_STRINGPARAM_VERSION, + CMD_STRINGPARAM_PRINTTOLIST, + CMD_STRINGPARAM_PRINTERNAME, + CMD_STRINGPARAM_CONVERSIONLIST, + CMD_STRINGPARAM_CONVERSIONPARAMS, + CMD_STRINGPARAM_CONVERSIONOUT, + CMD_STRINGPARAM_INFILTER, + CMD_STRINGPARAM_DISPLAY, + CMD_STRINGPARAM_LANGUAGE, + CMD_STRINGPARAM_COUNT // must be last element! + }; + + enum GroupParamId + { + CMD_GRPID_MODULE = 0, + CMD_GRPID_COUNT + }; + + struct Supplier + { + // Thrown from constructors and next: + class Exception { + public: + Exception(); + Exception(Exception const &); + virtual ~Exception(); + Exception & operator =(Exception const &); + }; + + virtual ~Supplier(); + virtual boost::optional< rtl::OUString > getCwdUrl() = 0; + virtual bool next(rtl::OUString * argument) = 0; + }; + + CommandLineArgs(); + CommandLineArgs( Supplier& supplier ); + + boost::optional< rtl::OUString > getCwdUrl() const { return m_cwdUrl; } + + // generic methods to access parameter + void SetBoolParam( BoolParam eParam, sal_Bool bNewValue ); + + const rtl::OUString& GetStringParam( StringParam eParam ) const; + + // Access to bool parameters + sal_Bool IsMinimized() const; + sal_Bool IsInvisible() const; + sal_Bool IsNoRestore() const; + sal_Bool IsNoDefault() const; + sal_Bool IsBean() const; + sal_Bool IsServer() const; + sal_Bool IsHeadless() const; + sal_Bool IsQuickstart() const; + sal_Bool IsNoQuickstart() const; + sal_Bool IsTerminateAfterInit() const; + sal_Bool IsNoLogo() const; + sal_Bool IsNoLockcheck() const; + sal_Bool IsHelp() const; + sal_Bool IsHelpWriter() const; + sal_Bool IsHelpCalc() const; + sal_Bool IsHelpDraw() const; + sal_Bool IsHelpImpress() const; + sal_Bool IsHelpBase() const; + sal_Bool IsHelpMath() const; + sal_Bool IsHelpBasic() const; + sal_Bool IsWriter() const; + sal_Bool IsCalc() const; + sal_Bool IsDraw() const; + sal_Bool IsImpress() const; + sal_Bool IsBase() const; + sal_Bool IsGlobal() const; + sal_Bool IsMath() const; + sal_Bool IsWeb() const; + sal_Bool IsVersion() const; + sal_Bool HasModuleParam() const; + sal_Bool WantsToLoadDocument() const; + + // Access to string parameters + sal_Bool GetPortalConnectString( ::rtl::OUString& rPara) const; + sal_Bool GetAcceptString( ::rtl::OUString& rPara) const; + sal_Bool GetUnAcceptString( ::rtl::OUString& rPara) const; + sal_Bool GetOpenList( ::rtl::OUString& rPara) const; + sal_Bool GetViewList( ::rtl::OUString& rPara) const; + sal_Bool GetStartList( ::rtl::OUString& rPara) const; + sal_Bool GetForceOpenList( ::rtl::OUString& rPara) const; + sal_Bool GetForceNewList( ::rtl::OUString& rPara) const; + sal_Bool GetPrintList( ::rtl::OUString& rPara) const; + sal_Bool GetPrintToList( ::rtl::OUString& rPara ) const; + sal_Bool GetPrinterName( ::rtl::OUString& rPara ) const; + sal_Bool GetLanguage( ::rtl::OUString& rPara ) const; + sal_Bool GetInFilter( ::rtl::OUString& rPara ) const; + sal_Bool GetConversionList( ::rtl::OUString& rPara ) const; + sal_Bool GetConversionParams( ::rtl::OUString& rPara ) const; + sal_Bool GetConversionOut( ::rtl::OUString& rPara ) const; + + // Special analyzed states (does not match directly to a command line parameter!) + sal_Bool IsPrinting() const; + sal_Bool IsEmpty() const; + sal_Bool IsEmptyOrAcceptOnly() const; + + private: + enum Count { NONE, ONE, MANY }; + + struct GroupDefinition + { + sal_Int32 nCount; + BoolParam* pGroupMembers; + }; + + // no copy and operator= + CommandLineArgs( const CommandLineArgs& ); + CommandLineArgs operator=( const CommandLineArgs& ); + + sal_Bool InterpretCommandLineParameter( const ::rtl::OUString&, ::rtl::OUString& ); + void ParseCommandLine_Impl( Supplier& supplier ); + void ResetParamValues(); + sal_Bool CheckGroupMembers( GroupParamId nGroup, BoolParam nExcludeMember ) const; + + void AddStringListParam_Impl( StringParam eParam, const rtl::OUString& aParam ); + void SetBoolParam_Impl( BoolParam eParam, sal_Bool bValue ); + + boost::optional< rtl::OUString > m_cwdUrl; + sal_Bool m_aBoolParams[ CMD_BOOLPARAM_COUNT ]; // Stores boolean parameters + rtl::OUString m_aStrParams[ CMD_STRINGPARAM_COUNT ]; // Stores string parameters + sal_Bool m_aStrSetParams[ CMD_STRINGPARAM_COUNT ]; // Stores if string parameters are provided on cmdline + Count m_eArgumentCount; // Number of Args + bool m_bDocumentArgs; // A document creation/open/load arg is used + mutable ::osl::Mutex m_aMutex; + + // static definition for groups where only one member can be true + static GroupDefinition m_pGroupDefinitions[ CMD_GRPID_COUNT ]; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/cmdlinehelp.cxx b/desktop/source/app/cmdlinehelp.cxx new file mode 100644 index 000000000000..82c9eb560178 --- /dev/null +++ b/desktop/source/app/cmdlinehelp.cxx @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <stdlib.h> +#ifdef UNX +#include <stdio.h> +#endif +#include <sal/types.h> +#include <tools/string.hxx> +#include <vcl/msgbox.hxx> +#include <rtl/bootstrap.hxx> +#include <app.hxx> + +#include "desktopresid.hxx" +#include "desktop.hrc" +#include "cmdlinehelp.hxx" + +namespace desktop +{ + // to be able to display the help nicely in a dialog box with propotional font, + // we need to split it in chunks... + // ___HEAD___ + // LEFT RIGHT + // LEFT RIGHT + // LEFT RIGHT + // __BOTTOM__ + // [OK] + + const char *aCmdLineHelp_version = + "%PRODUCTNAME %PRODUCTVERSION %PRODUCTEXTENSION\n"\ + "\n"; + const char *aCmdLineHelp_head = + "Usage: %CMDNAME [options] [documents...]\n"\ + "\n"\ + "Options:\n"; + const char *aCmdLineHelp_left = + "--minimized \n"\ + "--invisible \n"\ + "--norestore \n"\ + "--quickstart \n"\ + "--nologo \n"\ + "--nolockcheck \n"\ + "--nodefault \n"\ + "--headless \n"\ + "--help/-h/-? \n"\ + "--version \n"\ + "--writer \n"\ + "--calc \n"\ + "--draw \n"\ + "--impress \n"\ + "--base \n"\ + "--math \n"\ + "--global \n"\ + "--web \n"\ + "-o \n"\ + "-n \n"; + const char *aCmdLineHelp_right = + "keep startup bitmap minimized.\n"\ + "no startup screen, no default document and no UI.\n"\ + "suppress restart/restore after fatal errors.\n"\ + "starts the quickstart service\n"\ + "don't show startup screen.\n"\ + "don't check for remote instances using the installation\n"\ + "don't start with an empty document\n"\ + "like invisible but no userinteraction at all.\n"\ + "show this message and exit.\n"\ + "display the version information.\n"\ + "create new text document.\n"\ + "create new spreadsheet document.\n"\ + "create new drawing.\n"\ + "create new presentation.\n"\ + "create new database.\n"\ + "create new formula.\n"\ + "create new global document.\n"\ + "create new HTML document.\n"\ + "open documents regardless whether they are templates or not.\n"\ + "always open documents as new files (use as template).\n"; + const char *aCmdLineHelp_bottom = + "--display <display>\n"\ + " Specify X-Display to use in Unix/X11 versions.\n" + "-p <documents...>\n"\ + " print the specified documents on the default printer.\n"\ + "--pt <printer> <documents...>\n"\ + " print the specified documents on the specified printer.\n"\ + "--view <documents...>\n"\ + " open the specified documents in viewer-(readonly-)mode.\n"\ + "--show <presentation>\n"\ + " open the specified presentation and start it immediately\n"\ + "--accept=<accept-string>\n"\ + " Specify an UNO connect-string to create an UNO acceptor through which\n"\ + " other programs can connect to access the API\n"\ + "--unaccept=<accept-string>\n"\ + " Close an acceptor that was created with -accept=<accept-string>\n"\ + " Use -unnaccept=all to close all open acceptors\n"\ + "--infilter=<filter>\n"\ + " Force an input filter type if possible\n"\ + " Eg. -infilter=\"Calc Office Open XML\"\n"\ + "--convert-to output_file_extension[:output_filter_name] [-outdir ouput_dir] files\n"\ + " Batch convert files.\n"\ + " If -outdir is not specified then current working dir is used as output_dir.\n"\ + " Eg. -convert-to pdf *.doc\n"\ + " -convert-to pdf:writer_pdf_Export -outdir /home/user *.doc\n"\ + "--print-to-file [-printer-name printer_name] [-outdir ouput_dir] files\n"\ + " Batch print files to file.\n"\ + " If -outdir is not specified then current working dir is used as output_dir.\n"\ + " Eg. -print-to-file *.doc\n"\ + " -print-to-file -printer-name nasty_lowres_printer -outdir /home/user *.doc\n"\ + "\nRemaining arguments will be treated as filenames or URLs of documents to open.\n\n"; + + void ReplaceStringHookProc( UniString& rStr ); + + void displayCmdlineHelp() + { + // if you put variables in other chunks don't forget to call the replace routines + // for those chunks... + String aHelpMessage_version(aCmdLineHelp_version, RTL_TEXTENCODING_ASCII_US); + String aHelpMessage_head(aCmdLineHelp_head, RTL_TEXTENCODING_ASCII_US); + String aHelpMessage_left(aCmdLineHelp_left, RTL_TEXTENCODING_ASCII_US); + String aHelpMessage_right(aCmdLineHelp_right, RTL_TEXTENCODING_ASCII_US); + String aHelpMessage_bottom(aCmdLineHelp_bottom, RTL_TEXTENCODING_ASCII_US); + ReplaceStringHookProc(aHelpMessage_version); + aHelpMessage_head.SearchAndReplaceAscii( "%CMDNAME", String( "soffice", RTL_TEXTENCODING_ASCII_US) ); +#ifdef UNX + // on unix use console for output + fprintf(stdout, "%s%s", + ByteString(aHelpMessage_version, RTL_TEXTENCODING_ASCII_US).GetBuffer(), + ByteString(aHelpMessage_head, RTL_TEXTENCODING_ASCII_US).GetBuffer()); + // merge left and right column + int n = aHelpMessage_left.GetTokenCount ('\n'); + ByteString bsLeft(aHelpMessage_left, RTL_TEXTENCODING_ASCII_US); + ByteString bsRight(aHelpMessage_right, RTL_TEXTENCODING_ASCII_US); + for ( int i = 0; i < n; i++ ) + { + fprintf(stdout, "%s", bsLeft.GetToken(i, '\n').GetBuffer()); + fprintf(stdout, "%s\n", bsRight.GetToken(i, '\n').GetBuffer()); + } + fprintf(stdout, "%s", ByteString(aHelpMessage_bottom, + RTL_TEXTENCODING_ASCII_US).GetBuffer()); +#else + // rest gets a dialog box + CmdlineHelpDialog aDlg; + String head = aHelpMessage_version; + head.Append(aHelpMessage_head); + aDlg.m_ftHead.SetText(head); + aDlg.m_ftLeft.SetText(aHelpMessage_left); + aDlg.m_ftRight.SetText(aHelpMessage_right); + aDlg.m_ftBottom.SetText(aHelpMessage_bottom); + aDlg.Execute(); +#endif + } + + void displayVersion() + { + String aVersionMsg(aCmdLineHelp_version, RTL_TEXTENCODING_ASCII_US); + ReplaceStringHookProc(aVersionMsg); +#ifdef UNX + fprintf(stdout, "%s", rtl::OUStringToOString(aVersionMsg, RTL_TEXTENCODING_ASCII_US).getStr()); +#else + // Just re-use the help dialog for now. + CmdlineHelpDialog aDlg; + aDlg.m_ftHead.SetText(aVersionMsg); + aDlg.Execute(); +#endif + } + +#ifndef UNX + CmdlineHelpDialog::CmdlineHelpDialog (void) + : ModalDialog( NULL, DesktopResId( DLG_CMDLINEHELP ) ) + , m_ftHead( this, DesktopResId( TXT_DLG_CMDLINEHELP_HEADER ) ) + , m_ftLeft( this, DesktopResId( TXT_DLG_CMDLINEHELP_LEFT ) ) + , m_ftRight( this, DesktopResId( TXT_DLG_CMDLINEHELP_RIGHT ) ) + , m_ftBottom( this, DesktopResId( TXT_DLG_CMDLINEHELP_BOTTOM ) ) + , m_btOk( this, DesktopResId( BTN_DLG_CMDLINEHELP_OK ) ) + { + FreeResource(); + } +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/cmdlinehelp.hxx b/desktop/source/app/cmdlinehelp.hxx new file mode 100644 index 000000000000..5c92512ea1e9 --- /dev/null +++ b/desktop/source/app/cmdlinehelp.hxx @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include <vcl/dialog.hxx> +#include <vcl/fixed.hxx> +#include <vcl/button.hxx> + +namespace desktop +{ + void displayCmdlineHelp( void ); + void displayVersion(); +#ifndef UNX + class CmdlineHelpDialog : public ModalDialog + { + public: + CmdlineHelpDialog ( void ); + + FixedText m_ftHead; + FixedText m_ftLeft; + FixedText m_ftRight; + FixedText m_ftBottom; + OKButton m_btOk; + }; +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/configinit.cxx b/desktop/source/app/configinit.cxx new file mode 100644 index 000000000000..16ef67f3b3d7 --- /dev/null +++ b/desktop/source/app/configinit.cxx @@ -0,0 +1,304 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "configinit.hxx" + +#include "desktop.hrc" +#include "app.hxx" +#include <comphelper/processfactory.hxx> +#include <uno/current_context.hxx> +#include <cppuhelper/implbase1.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <stdio.h> +#include <map> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/configuration/CannotLoadConfigurationException.hpp> +#include <com/sun/star/configuration/InvalidBootstrapFileException.hpp> +#include <com/sun/star/configuration/backend/BackendSetupException.hpp> +#include <com/sun/star/configuration/backend/CannotConnectException.hpp> + +// ---------------------------------------------------------------------------- + +namespace uno = ::com::sun::star::uno; +namespace lang = ::com::sun::star::lang; +namespace configuration = ::com::sun::star::configuration; +namespace backend = ::com::sun::star::configuration::backend; +using rtl::OUString; +using uno::UNO_QUERY; +using desktop::Desktop; + +// ---------------------------------------------------------------------------- +static char const CONFIGURATION_PROVIDER[] = "com.sun.star.configuration.ConfigurationProvider"; + +static char const CONFIGURATION_ERROR_HANDLER[] = "com.sun.star.configuration.backend.InteractionHandler"; + +// must be aligned with configmgr/source/misc/configinteractionhandler +static char const CONFIG_ERROR_HANDLER[] = "configuration.interaction-handler"; +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +#define arraysize( arr ) ( sizeof (arr)/sizeof *(arr) ) + +typedef uno::Reference< lang::XMultiServiceFactory > ConfigurationProvider; + +#define OUSTRING( constascii ) OUString( RTL_CONSTASCII_USTRINGPARAM( constascii ) ) + +#define OU2O( ustr, enc ) rtl::OUStringToOString( (ustr), RTL_TEXTENCODING_ ## enc ) + +#define k_PROVIDER OUSTRING( CONFIGURATION_PROVIDER ) +#define k_ERRORHANDLER OUSTRING( CONFIGURATION_ERROR_HANDLER ) +// ---------------------------------------------------------------------------- +// Get a message string securely. There is a fallback string if the resource +// is not available. Adapted from Desktop::GetMsgString() + +OUString getMsgString( sal_uInt16 nId, char const * aFallBackMsg ) +{ + ResMgr* pResMgr = Desktop::GetDesktopResManager(); + if ( !pResMgr || !nId ) + return OUString::createFromAscii(aFallBackMsg); + else + return OUString( String(ResId( nId, *pResMgr ))); +} +// ---------------------------------------------------------------------------- +/** Creates the normal configuration provider. + +*/ +static +ConfigurationProvider createDefaultConfigurationProvider( ) +{ + uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + + OSL_ENSURE( xServiceManager.is(),"No ServiceManager set for CreateApplicationConfigurationProvider"); + + ConfigurationProvider xProvider; + + if (xServiceManager.is()) + { + + xProvider.set( xServiceManager->createInstance(k_PROVIDER), UNO_QUERY); + } + + if (!xProvider.is()) + { + OUString const sMsg = OUSTRING("Service \"") + k_PROVIDER + + OUSTRING("\" is not available at the service manager."); + + throw lang::ServiceNotRegisteredException(sMsg, xServiceManager); + } + + return xProvider; +} +// ---------------------------------------------------------------------------- +/// @attention this method must be called from a catch statement! +static void handleGeneralException(uno::Exception& aException, + const rtl::OUString& aMessage) +{ + aException.Message = aMessage ; + throw ; +} +// ---------------------------------------------------------------------------- + +uno::Reference< lang::XMultiServiceFactory > CreateApplicationConfigurationProvider( ) +{ + uno::Reference< lang::XMultiServiceFactory > xProvider; + + try + { + xProvider = createDefaultConfigurationProvider( ); + } + catch (configuration::InvalidBootstrapFileException & exception) + { + handleGeneralException(exception, + getMsgString( STR_CONFIG_ERR_SETTINGS_INCOMPLETE, + "The startup settings for your configuration settings are incomplete. ")); + } + catch (backend::CannotConnectException & exception) + { + handleGeneralException(exception, + getMsgString( STR_CONFIG_ERR_CANNOT_CONNECT, + "A connection to your configuration settings could not be established. ")); + } + catch (backend::BackendSetupException & exception) + { + handleGeneralException(exception, + getMsgString( STR_CONFIG_ERR_CANNOT_CONNECT, + "A connection to your configuration settings could not be established. ")); + } + catch (configuration::CannotLoadConfigurationException & exception) + { + handleGeneralException(exception, + getMsgString( STR_CONFIG_ERR_CANNOT_CONNECT, + "A connection to your configuration settings could not be established. ")); + } + catch (uno::Exception & exception) + { + handleGeneralException(exception, + getMsgString( STR_CONFIG_ERR_ACCESS_GENERAL, + "A general error occurred while accessing your configuration settings.")); + } + + + return xProvider ; +} +// ---------------------------------------------------------------------------- + + + + +// ---------------------------------------------------------------------------- +// ConfigurationErrorHandler +// ---------------------------------------------------------------------------- + +namespace +{ + typedef uno::Reference< uno::XCurrentContext > CurrentContext; + class SimpleCurrentContext : public cppu::WeakImplHelper1< uno::XCurrentContext > + { + CurrentContext m_xChainedContext; + public: + explicit + SimpleCurrentContext(const CurrentContext & xChainedContext) + : m_xChainedContext(xChainedContext) + {} + + void install() { uno::setCurrentContext(this); } + void deinstall() { uno::setCurrentContext(m_xChainedContext); } + + uno::Any getChainedValueByName( OUString const & aName) const + { + return m_xChainedContext.is() + ? m_xChainedContext->getValueByName(aName) + : uno::Any(); + } + + // XCurrentContext + virtual uno::Any SAL_CALL + getValueByName( OUString const & aName) + throw (uno::RuntimeException); + }; + + uno::Any SAL_CALL + SimpleCurrentContext::getValueByName( OUString const & aName) + throw (uno::RuntimeException) + { + return getChainedValueByName(aName); + } + +} + +// ---------------------------------------------------------------------------- +class ConfigurationErrorHandler::Context : public SimpleCurrentContext +{ +public: + Context() + : SimpleCurrentContext( uno::getCurrentContext() ) + { + } + + ~Context() + { + } + + // XCurrentContext + virtual uno::Any SAL_CALL + getValueByName( OUString const & aName) + throw (uno::RuntimeException); + +private: + InteractionHandler m_xHandler; +}; + +//------------------------------------------------------------------------------ +uno::Any SAL_CALL ConfigurationErrorHandler::Context::getValueByName( OUString const & aName) + throw (uno::RuntimeException) +{ + if ( aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(CONFIG_ERROR_HANDLER)) ) + { + if ( !m_xHandler.is() ) + m_xHandler = ConfigurationErrorHandler::getDefaultInteractionHandler(); + return uno::Any( m_xHandler ); + } + return SimpleCurrentContext::getValueByName( aName ); +} + +//------------------------------------------------------------------------------ +ConfigurationErrorHandler::~ConfigurationErrorHandler() +{ + deactivate(); +} + +//------------------------------------------------------------------------------ +/// installs the handler into the current context +void ConfigurationErrorHandler::activate() +{ + if (!m_pContext) + { + m_pContext = new Context; + m_pContext->acquire(); + } + m_pContext->install(); +} + +//------------------------------------------------------------------------------ +/// deinstalls the handler from the current context, restoring the previous context +void ConfigurationErrorHandler::deactivate() +{ + if (m_pContext) + { + m_pContext->deinstall(); + m_pContext->release(); + m_pContext = 0; + } +} +//------------------------------------------------------------------------------ + +ConfigurationErrorHandler::InteractionHandler ConfigurationErrorHandler::getDefaultInteractionHandler() +{ + uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + + OSL_ENSURE( xServiceManager.is(),"No ServiceManager set for ConfigurationErrorHandler"); + + InteractionHandler xHandler; + + if (xServiceManager.is()) + { + xHandler.set( xServiceManager->createInstance(k_ERRORHANDLER), UNO_QUERY ); + } + + return xHandler; +} +//------------------------------------------------------------------------------ + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/configinit.hxx b/desktop/source/app/configinit.hxx new file mode 100644 index 000000000000..24fb01881396 --- /dev/null +++ b/desktop/source/app/configinit.hxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#ifndef _DESKTOP_CONFIGINIT_HXX_ +#define _DESKTOP_CONFIGINIT_HXX_ + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <rtl/ustring.hxx> + +/** creates a ConfigurationProvider instance +Important: exceptions thrown from that method will contain a readily +displayable message. + + @return + The default configuration provider for the application or<br/> + <NULL/>, if startup was canceled + + @throw com::sun::star::configuration::CannotLoadConfigurationException + if the configuration provider can't be created + + @throw com::sun::star::lang::ServiceNotRegisteredException + if the ConfigurationProvider service is unknwon + + @throw com::sun::star::lang::WrappedTargetException + if the configuration backend could be created, + but incurred a failure later + +*/ +extern +com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + CreateApplicationConfigurationProvider( ); + +//----------------------------------------------------------------------------- +#include <com/sun/star/task/XInteractionHandler.hpp> + +/** + sets an InteractionHandler for configuration errors in the current context. + + */ + class ConfigurationErrorHandler + { + public: + typedef com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > InteractionHandler; + + /// Constructor: Uses the default interaction handler + ConfigurationErrorHandler() + : m_pContext(0), m_xHandler() + {} + + /// Constructor: Uses an externally provided interaction handler + ConfigurationErrorHandler(const InteractionHandler & xHandler) + : m_pContext(0), m_xHandler( xHandler ) + {} + + ~ConfigurationErrorHandler(); + + static InteractionHandler getDefaultInteractionHandler(); + + /// installs the handler into the current context + void activate(); + /// deinstalls the handler from the current context, restoring the previous context + void deactivate(); + private: + class Context; + Context * m_pContext; + InteractionHandler m_xHandler; + private: + // not implemented - suppress copy + ConfigurationErrorHandler(const ConfigurationErrorHandler&); + void operator=(const ConfigurationErrorHandler&); + }; + +//----------------------------------------------------------------------------- +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/copyright_ascii_ooo.c b/desktop/source/app/copyright_ascii_ooo.c new file mode 100755 index 000000000000..3984a81f26e5 --- /dev/null +++ b/desktop/source/app/copyright_ascii_ooo.c @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + + /* + * copyright text to see as text in the soffice binary + * + */ + +extern const char copyright_text_1[]; + +const char copyright_text_1[] = "Copyright 2000, 2010 Oracle and/or its affiliates, All rights reserved."; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/copyright_ascii_sun.c b/desktop/source/app/copyright_ascii_sun.c new file mode 100755 index 000000000000..c7d6e7e3c08d --- /dev/null +++ b/desktop/source/app/copyright_ascii_sun.c @@ -0,0 +1,10 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + + /* + * copyright text to see as text in the soffice binary + * + */ + +const char copyright_text_1[] = "Copyright 2000, 2010 Oracle and/or its affiliates, All rights reserved."; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/desktop.hrc b/desktop/source/app/desktop.hrc new file mode 100755 index 000000000000..9c68d7b9fd2d --- /dev/null +++ b/desktop/source/app/desktop.hrc @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_HRC_ +#define _DESKTOP_HRC_ + +#ifndef _SOLAR_HRC +#include <svl/solar.hrc> +#endif + +#define RID_DESKTOP_DIALOG_START 2000 +#define RID_FIRSTSTSTART_START 3000 +#define RID_DESKTOP_STRING_START 10000 + + +#define INFOBOX_CMDLINEHELP (RID_DESKTOP_DIALOG_START+51) +#define INFOBOX_EXPIRED (RID_DESKTOP_DIALOG_START+52) + +#define QBX_USERDATALOCKED (RID_DESKTOP_DIALOG_START+100) + +#define DLG_CMDLINEHELP (RID_DESKTOP_DIALOG_START+101) +#define TXT_DLG_CMDLINEHELP_HEADER (RID_DESKTOP_DIALOG_START+102) +#define TXT_DLG_CMDLINEHELP_LEFT (RID_DESKTOP_DIALOG_START+103) +#define TXT_DLG_CMDLINEHELP_RIGHT (RID_DESKTOP_DIALOG_START+104) +#define TXT_DLG_CMDLINEHELP_BOTTOM (RID_DESKTOP_DIALOG_START+105) +#define BTN_DLG_CMDLINEHELP_OK (RID_DESKTOP_DIALOG_START+106) + +#define QBX_CONFIG_IMPORTSETTINGS (RID_DESKTOP_DIALOG_START+180) + +#define EBX_ERR_PRINTDISABLED (RID_DESKTOP_DIALOG_START+190) + +#define STR_RECOVER_QUERY (RID_DESKTOP_STRING_START+0) +#define STR_RECOVER_TITLE (RID_DESKTOP_STRING_START+1) +#define STR_RECOVER_PREPARED (RID_DESKTOP_STRING_START+2) + +#define STR_BOOTSTRAP_ERR_CANNOT_START (RID_DESKTOP_STRING_START+100) +#define STR_BOOTSTRAP_ERR_DIR_MISSING (RID_DESKTOP_STRING_START+101) +#define STR_BOOTSTRAP_ERR_PATH_INVALID (RID_DESKTOP_STRING_START+102) +#define STR_BOOTSTRAP_ERR_NO_PATH (RID_DESKTOP_STRING_START+103) +#define STR_BOOTSTRAP_ERR_INTERNAL (RID_DESKTOP_STRING_START+104) +#define STR_BOOTSTRAP_ERR_FILE_CORRUPT (RID_DESKTOP_STRING_START+105) +#define STR_BOOTSTRAP_ERR_FILE_MISSING (RID_DESKTOP_STRING_START+106) +#define STR_BOOTSTRAP_ERR_NO_SUPPORT (RID_DESKTOP_STRING_START+107) +#define STR_BOOTSTRAP_ERR_LANGUAGE_MISSING (RID_DESKTOP_STRING_START+108) + +#define STR_BOOTSTRAP_ERR_NO_SERVICE (RID_DESKTOP_STRING_START+120) +#define STR_BOOTSTRAP_ERR_NO_CFG_SERVICE (RID_DESKTOP_STRING_START+121) +#define STR_BOOTSTRAP_ERR_CFG_DATAACCESS (RID_DESKTOP_STRING_START+122) +#define STR_BOOTSTRAP_ERR_NO_PATHSET_SERVICE (RID_DESKTOP_STRING_START+123) + +#define STR_ASK_START_SETUP_MANUALLY (RID_DESKTOP_STRING_START+152) + +#define STR_INTERNAL_ERRMSG (RID_DESKTOP_STRING_START+161) + +#define STR_CONFIG_ERR_SETTINGS_INCOMPLETE (RID_DESKTOP_STRING_START+182) +#define STR_CONFIG_ERR_CANNOT_CONNECT (RID_DESKTOP_STRING_START+183) +#define STR_CONFIG_ERR_RIGHTS_MISSING (RID_DESKTOP_STRING_START+184) +#define STR_CONFIG_ERR_ACCESS_GENERAL (RID_DESKTOP_STRING_START+187) +#define STR_CONFIG_ERR_NO_WRITE_ACCESS (RID_DESKTOP_STRING_START+188) + +#define STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE (RID_DESKTOP_STRING_START+189) +#define STR_BOOSTRAP_ERR_NOACCESSRIGHTS (RID_DESKTOP_STRING_START+190) + +#define STR_TITLE_USERDATALOCKED (RID_DESKTOP_STRING_START+206) +#define STR_TITLE_EXPIRED (RID_DESKTOP_STRING_START+207) + +#endif // _DESKTOP_HRC_ diff --git a/desktop/source/app/desktop.src b/desktop/source/app/desktop.src new file mode 100644 index 000000000000..98ee68685917 --- /dev/null +++ b/desktop/source/app/desktop.src @@ -0,0 +1,235 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "desktop.hrc" + + +String STR_RECOVER_QUERY +{ + Text [ en-US ] = "Should the file \"$1\" be restored?" ; +}; + +String STR_RECOVER_TITLE +{ + Text [ en-US ] = "File Recovery" ; +}; + +WarningBox STR_RECOVER_PREPARED +{ + Message [ en-US ] = "An unrecoverable error has occurred.\n\nAll modified files have been saved and can\nprobably be recovered at program restart." ; +}; + +String STR_BOOTSTRAP_ERR_CANNOT_START +{ + Text [ en-US ] = "The application cannot be started. "; +}; + +String STR_BOOTSTRAP_ERR_DIR_MISSING +{ + Text [ en-US ] = "The configuration directory \"$1\" could not be found."; +}; + +String STR_BOOTSTRAP_ERR_PATH_INVALID +{ + Text [ en-US ] = "The installation path is invalid."; +}; + +String STR_BOOTSTRAP_ERR_NO_PATH +{ + Text [ en-US ] = "The installation path is not available."; +}; + +String STR_BOOTSTRAP_ERR_INTERNAL +{ + Text [ en-US ] = "An internal error occurred."; +}; + +String STR_BOOTSTRAP_ERR_FILE_CORRUPT +{ + Text [ en-US ] = "The configuration file \"$1\" is corrupt."; +}; + +String STR_BOOTSTRAP_ERR_FILE_MISSING +{ + Text [ en-US ] = "The configuration file \"$1\" was not found."; +}; + +String STR_BOOTSTRAP_ERR_NO_SUPPORT +{ + Text [ en-US ] = "The configuration file \"$1\" does not support the current version."; +}; + +String STR_BOOTSTRAP_ERR_LANGUAGE_MISSING +{ + Text [ en-US ] = "The user interface language cannot be determined."; +}; + +String STR_BOOTSTRAP_ERR_NO_SERVICE +{ + Text [ en-US ] = "The component manager is not available."; +}; + +String STR_BOOTSTRAP_ERR_NO_CFG_SERVICE +{ + Text [ en-US ] = "The configuration service is not available."; +}; + +String STR_ASK_START_SETUP_MANUALLY +{ + Text [ en-US ] = "Start the setup application to repair the installation from the CD or the folder containing the installation packages."; +}; + +String STR_CONFIG_ERR_SETTINGS_INCOMPLETE +{ + Text [ en-US ] = "The startup settings for accessing the central configuration are incomplete. "; +}; + +String STR_CONFIG_ERR_CANNOT_CONNECT +{ + Text [ en-US ] = "A connection to the central configuration could not be established. "; +}; + +String STR_CONFIG_ERR_RIGHTS_MISSING +{ + Text [ en-US ] = "You cannot access the central configuration because of missing access rights. "; +}; + +String STR_CONFIG_ERR_ACCESS_GENERAL +{ + Text [ en-US ] = "A general error occurred while accessing your central configuration. "; +}; + +String STR_CONFIG_ERR_NO_WRITE_ACCESS +{ + Text [ en-US ] = "The changes to your personal settings cannot be stored centrally because of missing access rights. "; +}; + +String STR_BOOTSTRAP_ERR_CFG_DATAACCESS +{ + Text [ en-US ] = "%PRODUCTNAME cannot be started due to an error in accessing the %PRODUCTNAME configuration data.\n\nPlease contact your system administrator." ; +}; + +String STR_INTERNAL_ERRMSG +{ + Text [ en-US ] = "The following internal error has occurred: " ; +}; + +QueryBox QBX_USERDATALOCKED +{ + Buttons = WB_YES_NO ; + DefButton = WB_DEF_NO ; + Message [ en-US ] = "Either another instance of %PRODUCTNAME is accessing your personal settings or your personal settings are locked.\nSimultaneous access can lead to inconsistencies in your personal settings. Before continuing, you should make sure user '$u' closes %PRODUCTNAME on host '$h'.\n\nDo you really want to continue?"; +}; + +String STR_TITLE_USERDATALOCKED +{ + Text [ en-US ] = "%PRODUCTNAME %PRODUCTVERSION"; +}; + +InfoBox INFOBOX_CMDLINEHELP +{ + Buttons = WB_OK ; + DefButton = WB_DEF_OK ; + Message = ""; +}; + +ModalDialog DLG_CMDLINEHELP +{ + HelpID = "desktop:ModalDialog:DLG_CMDLINEHELP"; + Text = "Help Message..."; + Size = MAP_APPFONT(250, 365); + Border = True; + SVLook = True; + Moveable = True; + + FixedText TXT_DLG_CMDLINEHELP_HEADER + { + Size = MAP_APPFONT(240, 50); + Pos = MAP_APPFONT(5, 5); + Text = "HEADER"; + }; + FixedText TXT_DLG_CMDLINEHELP_LEFT + { + Size = MAP_APPFONT(50, 150); + Pos = MAP_APPFONT(5, 50); + Text = "LEFT"; + }; + FixedText TXT_DLG_CMDLINEHELP_RIGHT + { + Size = MAP_APPFONT(190, 150); + Pos = MAP_APPFONT(60, 50); + Text = "RIGHT"; + }; + FixedText TXT_DLG_CMDLINEHELP_BOTTOM + { + Size = MAP_APPFONT(240, 145); + Pos = MAP_APPFONT(5, 200); + Text = "BOTTOM"; + }; + OKButton BTN_DLG_CMDLINEHELP_OK + { + Size = MAP_APPFONT ( 50 , 14 ) ; + Pos = MAP_APPFONT(95, 345); + TabStop = TRUE ; + DefButton = TRUE ; + }; +}; + +ErrorBox EBX_ERR_PRINTDISABLED +{ + Buttons = WB_OK ; + DefButton = WB_DEF_OK ; + Message [ en-US ] = "Printing is disabled. No documents can be printed."; +}; + +InfoBox INFOBOX_EXPIRED +{ + Buttons = WB_OK ; + DefButton = WB_DEF_OK ; + Message [ en-US ] = "This Evaluation Version has expired. To find out more about %PRODUCTNAME,\nvisit http://www.oracle.com/us/products/applications/open-office."; +}; + +String STR_TITLE_EXPIRED +{ + Text [ en-US ] = "%PRODUCTNAME %PRODUCTVERSION"; +}; + +String STR_BOOTSTRAP_ERR_NO_PATHSET_SERVICE +{ + Text [ en-US ] = "The path manager is not available.\n"; +}; + +String STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE +{ + Text [ en-US ] = "%PRODUCTNAME user installation could not be completed due to insufficient free disk space. Please free more disc space at the following location and restart %PRODUCTNAME:\n\n"; +}; + +String STR_BOOSTRAP_ERR_NOACCESSRIGHTS +{ + Text [ en-US ] = "%PRODUCTNAME user installation could not be processed due to missing access rights. Please make sure that you have sufficient access rights for the following location and restart %PRODUCTNAME:\n\n"; +}; + diff --git a/desktop/source/app/desktopcontext.cxx b/desktop/source/app/desktopcontext.cxx new file mode 100644 index 000000000000..2a8ed7ef628c --- /dev/null +++ b/desktop/source/app/desktopcontext.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "desktopcontext.hxx" + +#include <vcl/svapp.hxx> +#include <svtools/javainteractionhandler.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::task; + +using ::rtl::OUString; + +namespace desktop +{ + +DesktopContext::DesktopContext( const Reference< XCurrentContext > & ctx ) + : m_xNextContext( ctx ) +{ +} + +Any SAL_CALL DesktopContext::getValueByName( const OUString& Name) throw (RuntimeException) +{ + Any retVal; + + if (Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(JAVA_INTERACTION_HANDLER_NAME))) + { + retVal = makeAny( Reference< XInteractionHandler >( new svt::JavaInteractionHandler()) ); + } + else if( m_xNextContext.is() ) + { + // Call next context in chain if found + retVal = m_xNextContext->getValueByName( Name ); + } + return retVal; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/desktopcontext.hxx b/desktop/source/app/desktopcontext.hxx new file mode 100644 index 000000000000..b68a73cd9cf9 --- /dev/null +++ b/desktop/source/app/desktopcontext.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_DESKTOPCONTEXT_HXX_ +#define _DESKTOP_DESKTOPCONTEXT_HXX_ + +#include <cppuhelper/implbase1.hxx> +#include <uno/current_context.hxx> + +namespace desktop +{ + class DesktopContext: public cppu::WeakImplHelper1< com::sun::star::uno::XCurrentContext > + { + public: + DesktopContext( const com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > & ctx); + + // XCurrentContext + virtual com::sun::star::uno::Any SAL_CALL getValueByName( const rtl::OUString& Name ) + throw (com::sun::star::uno::RuntimeException); + + private: + com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > m_xNextContext; + }; +} + +#endif // _DESKTOP_DESKTOPCONTEXT_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/desktopresid.cxx b/desktop/source/app/desktopresid.cxx new file mode 100644 index 000000000000..ac8799a95a23 --- /dev/null +++ b/desktop/source/app/desktopresid.cxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "desktopresid.hxx" +#include "app.hxx" + +// ----------------------------------------------------------------------- +namespace desktop +{ + +DesktopResId::DesktopResId( sal_uInt16 nId ) : + ResId( nId, *Desktop::GetDesktopResManager() ) +{ +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/desktopresid.hxx b/desktop/source/app/desktopresid.hxx new file mode 100644 index 000000000000..14d45a493f0c --- /dev/null +++ b/desktop/source/app/desktopresid.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_RESID_HXX_ +#define _DESKTOP_RESID_HXX_ + +#include <tools/resid.hxx> + +namespace desktop +{ + +class DesktopResId : public ResId +{ + public: + DesktopResId( sal_uInt16 nId ); +}; + +} + +#endif // _DESKTOP_RESID_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/dispatchwatcher.cxx b/desktop/source/app/dispatchwatcher.cxx new file mode 100644 index 000000000000..59ac06621aaf --- /dev/null +++ b/desktop/source/app/dispatchwatcher.cxx @@ -0,0 +1,670 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/fcontnr.hxx> +#include "osl/file.hxx" +#include "sfx2/app.hxx" +#include <svl/fstathelper.hxx> + +#include "dispatchwatcher.hxx" +#include <rtl/ustring.hxx> +#include <tools/string.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/synchronousdispatch.hxx> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/util/CloseVetoException.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/view/XPrintable.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/document/UpdateDocMode.hpp> +#include <com/sun/star/frame/XStorable.hpp> + +#include <tools/urlobj.hxx> +#include <comphelper/mediadescriptor.hxx> + +#include <vector> +#include <osl/thread.hxx> +#include <rtl/instance.hxx> + +using ::rtl::OUString; +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::view; + +namespace desktop +{ + +String GetURL_Impl( + const String& rName, boost::optional< rtl::OUString > const & cwdUrl ); + +struct DispatchHolder +{ + DispatchHolder( const URL& rURL, Reference< XDispatch >& rDispatch ) : + aURL( rURL ), xDispatch( rDispatch ) {} + + URL aURL; + rtl::OUString cwdUrl; + Reference< XDispatch > xDispatch; +}; + +static String impl_GetFilterFromExt( OUString aUrl, SfxFilterFlags nFlags, + String aAppl ) +{ + String aFilter; + SfxMedium* pMedium = new SfxMedium( aUrl, + STREAM_STD_READ, sal_False ); + + const SfxFilter *pSfxFilter = NULL; + if( nFlags == SFX_FILTER_EXPORT ) + { + SfxFilterMatcher( aAppl ).GuessFilterIgnoringContent( *pMedium, &pSfxFilter, nFlags, 0 ); + } + else + { + SFX_APP()->GetFilterMatcher().GuessFilter( *pMedium, &pSfxFilter, nFlags, 0 ); + } + + if( pSfxFilter ) + aFilter = ( nFlags == SFX_FILTER_EXPORT ) ? pSfxFilter->GetFilterName() : + pSfxFilter->GetServiceName(); + + delete pMedium; + return aFilter; +} +static OUString impl_GuessFilter( OUString aUrlIn, OUString aUrlOut ) +{ + /* aAppl can also be set to Factory like scalc, swriter... */ + String aAppl; + aAppl = impl_GetFilterFromExt( aUrlIn, SFX_FILTER_IMPORT, aAppl ); + return impl_GetFilterFromExt( aUrlOut, SFX_FILTER_EXPORT, aAppl ); +} + +namespace +{ + class theWatcherMutex : public rtl::Static<Mutex, theWatcherMutex> {}; +} + +Mutex& DispatchWatcher::GetMutex() +{ + return theWatcherMutex::get(); +} + +// Create or get the dispatch watcher implementation. This implementation must be +// a singleton to prevent access to the framework after it wants to terminate. +DispatchWatcher* DispatchWatcher::GetDispatchWatcher() +{ + static Reference< XInterface > xDispatchWatcher; + static DispatchWatcher* pDispatchWatcher = NULL; + + if ( !xDispatchWatcher.is() ) + { + ::osl::MutexGuard aGuard( GetMutex() ); + + if ( !xDispatchWatcher.is() ) + { + pDispatchWatcher = new DispatchWatcher(); + + // We have to hold a reference to ourself forever to prevent our own destruction. + xDispatchWatcher = static_cast< cppu::OWeakObject *>( pDispatchWatcher ); + } + } + + return pDispatchWatcher; +} + + +DispatchWatcher::DispatchWatcher() + : m_nRequestCount(0) +{ +} + + +DispatchWatcher::~DispatchWatcher() +{ +} + + +sal_Bool DispatchWatcher::executeDispatchRequests( const DispatchList& aDispatchRequestsList, bool bNoTerminate ) +{ + Reference< XComponentLoader > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + UNO_QUERY ); + + DispatchList::const_iterator p; + std::vector< DispatchHolder > aDispatches; + ::rtl::OUString aAsTemplateArg( RTL_CONSTASCII_USTRINGPARAM( "AsTemplate")); + sal_Bool bSetInputFilter = sal_False; + ::rtl::OUString aForcedInputFilter; + + for ( p = aDispatchRequestsList.begin(); p != aDispatchRequestsList.end(); ++p ) + { + const DispatchRequest& aDispatchRequest = *p; + + // create parameter array + sal_Int32 nCount = 4; + if ( aDispatchRequest.aPreselectedFactory.getLength() ) + nCount++; + + // Set Input Filter + if ( aDispatchRequest.aRequestType == REQUEST_INFILTER ) + { + bSetInputFilter = sal_True; + aForcedInputFilter = aDispatchRequest.aURL; + OfficeIPCThread::RequestsCompleted( 1 ); + continue; + } + + // we need more properties for a print/print to request + if ( aDispatchRequest.aRequestType == REQUEST_PRINT || + aDispatchRequest.aRequestType == REQUEST_PRINTTO || + aDispatchRequest.aRequestType == REQUEST_BATCHPRINT || + aDispatchRequest.aRequestType == REQUEST_CONVERSION) + nCount++; + + Sequence < PropertyValue > aArgs( nCount ); + + // mark request as user interaction from outside + aArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Referer")); + aArgs[0].Value <<= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:OpenEvent")); + + if ( aDispatchRequest.aRequestType == REQUEST_PRINT || + aDispatchRequest.aRequestType == REQUEST_PRINTTO || + aDispatchRequest.aRequestType == REQUEST_BATCHPRINT || + aDispatchRequest.aRequestType == REQUEST_CONVERSION) + { + aArgs[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")); + aArgs[2].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OpenNewView")); + aArgs[3].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Hidden")); + aArgs[4].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Silent")); + } + else + { + Reference < com::sun::star::task::XInteractionHandler > xInteraction( + ::comphelper::getProcessServiceFactory()->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.InteractionHandler")) ), + com::sun::star::uno::UNO_QUERY ); + + aArgs[1].Name = OUString(RTL_CONSTASCII_USTRINGPARAM( "InteractionHandler" )); + aArgs[1].Value <<= xInteraction; + + sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG; + aArgs[2].Name = OUString(RTL_CONSTASCII_USTRINGPARAM( "MacroExecutionMode" )); + aArgs[2].Value <<= nMacroExecMode; + + sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG; + aArgs[3].Name = OUString(RTL_CONSTASCII_USTRINGPARAM( "UpdateDocMode" )); + aArgs[3].Value <<= nUpdateDoc; + } + + if ( aDispatchRequest.aPreselectedFactory.getLength() ) + { + aArgs[nCount-1].Name = ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(); + aArgs[nCount-1].Value <<= aDispatchRequest.aPreselectedFactory; + } + + String aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) ); + ::rtl::OUString aTarget( RTL_CONSTASCII_USTRINGPARAM("_default") ); + + if ( aDispatchRequest.aRequestType == REQUEST_PRINT || + aDispatchRequest.aRequestType == REQUEST_PRINTTO || + aDispatchRequest.aRequestType == REQUEST_BATCHPRINT || + aDispatchRequest.aRequestType == REQUEST_CONVERSION) + { + // documents opened for printing are opened readonly because they must be opened as a new document and this + // document could be open already + aArgs[1].Value <<= sal_True; + + // always open a new document for printing, because it must be disposed afterwards + aArgs[2].Value <<= sal_True; + + // printing is done in a hidden view + aArgs[3].Value <<= sal_True; + + // load document for printing without user interaction + aArgs[4].Value <<= sal_True; + + // hidden documents should never be put into open tasks + aTarget = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_blank") ); + } + // load the document ... if they are loadable! + // Otherwise try to dispatch it ... + Reference < XPrintable > xDoc; + if( + ( aName.CompareToAscii( ".uno" , 4 ) == COMPARE_EQUAL ) || + ( aName.CompareToAscii( "slot:" , 5 ) == COMPARE_EQUAL ) || + ( aName.CompareToAscii( "macro:", 6 ) == COMPARE_EQUAL ) || + ( aName.CompareToAscii("vnd.sun.star.script", 19) == COMPARE_EQUAL) + ) + { + // Attention: URL must be parsed full. Otherwise some detections on it will fail! + // It doesnt matter, if parser isn't available. Because; We try loading of URL then ... + URL aURL ; + aURL.Complete = aName; + + Reference < XDispatch > xDispatcher ; + Reference < XDispatchProvider > xProvider ( xDesktop, UNO_QUERY ); + Reference < XURLTransformer > xParser ( ::comphelper::getProcessServiceFactory()->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ), ::com::sun::star::uno::UNO_QUERY ); + + if( xParser.is() == sal_True ) + xParser->parseStrict( aURL ); + + if( xProvider.is() == sal_True ) + xDispatcher = xProvider->queryDispatch( aURL, ::rtl::OUString(), 0 ); + + if( xDispatcher.is() == sal_True ) + { + { + ::osl::ClearableMutexGuard aGuard( GetMutex() ); + // Remember request so we can find it in statusChanged! + m_aRequestContainer.insert( DispatchWatcherHashMap::value_type( aURL.Complete, (sal_Int32)1 ) ); + m_nRequestCount++; + } + + // Use local vector to store dispatcher because we have to fill our request container before + // we can dispatch. Otherwise it would be possible that statusChanged is called before we dispatched all requests!! + aDispatches.push_back( DispatchHolder( aURL, xDispatcher )); + } + } + else if ( ( aName.CompareToAscii( "service:" , 8 ) == COMPARE_EQUAL ) ) + { + // TODO: the dispatch has to be done for loadComponentFromURL as well. Please ask AS for more details. + URL aURL ; + aURL.Complete = aName; + + Reference < XDispatch > xDispatcher ; + Reference < XDispatchProvider > xProvider ( xDesktop, UNO_QUERY ); + Reference < XURLTransformer > xParser ( ::comphelper::getProcessServiceFactory()->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ), ::com::sun::star::uno::UNO_QUERY ); + + if( xParser.is() == sal_True ) + xParser->parseStrict( aURL ); + + if( xProvider.is() == sal_True ) + xDispatcher = xProvider->queryDispatch( aURL, ::rtl::OUString(), 0 ); + + if( xDispatcher.is() == sal_True ) + { + try + { + // We have to be listener to catch errors during dispatching URLs. + // Otherwise it would be possible to have an office running without an open + // window!! + Sequence < PropertyValue > aArgs2(1); + aArgs2[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SynchronMode")); + aArgs2[0].Value <<= sal_True; + Reference < XNotifyingDispatch > xDisp( xDispatcher, UNO_QUERY ); + if ( xDisp.is() ) + xDisp->dispatchWithNotification( aURL, aArgs2, DispatchWatcher::GetDispatchWatcher() ); + else + xDispatcher->dispatch( aURL, aArgs2 ); + } + catch (const ::com::sun::star::uno::Exception&) + { + OUString aMsg = OUString(RTL_CONSTASCII_USTRINGPARAM( + "Desktop::OpenDefault() IllegalArgumentException while calling XNotifyingDispatch: ")); + OSL_FAIL( OUStringToOString(aMsg, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + } + else + { + INetURLObject aObj( aName ); + if ( aObj.GetProtocol() == INET_PROT_PRIVATE ) + aTarget = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_default") ); + + // Set "AsTemplate" argument according to request type + if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW || + aDispatchRequest.aRequestType == REQUEST_FORCEOPEN ) + { + sal_Int32 nIndex = aArgs.getLength(); + aArgs.realloc( nIndex+1 ); + aArgs[nIndex].Name = aAsTemplateArg; + if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ) + aArgs[nIndex].Value <<= sal_True; + else + aArgs[nIndex].Value <<= sal_False; + } + + // if we are called in viewmode, open document read-only + if(aDispatchRequest.aRequestType == REQUEST_VIEW) { + sal_Int32 nIndex = aArgs.getLength(); + aArgs.realloc(nIndex+1); + aArgs[nIndex].Name = OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")); + aArgs[nIndex].Value <<= sal_True; + } + + // if we are called with -start set Start in mediadescriptor + if(aDispatchRequest.aRequestType == REQUEST_START) { + sal_Int32 nIndex = aArgs.getLength(); + aArgs.realloc(nIndex+1); + aArgs[nIndex].Name = OUString(RTL_CONSTASCII_USTRINGPARAM("StartPresentation")); + aArgs[nIndex].Value <<= sal_True; + } + + // Force input filter, if possible + if( bSetInputFilter ) + { + sal_Int32 nIndex = aArgs.getLength(); + aArgs.realloc(nIndex+1); + aArgs[nIndex].Name = OUString(RTL_CONSTASCII_USTRINGPARAM("FilterName")); + aArgs[nIndex].Value <<= aForcedInputFilter; + } + + // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism. + try + { + xDoc = Reference < XPrintable >( ::comphelper::SynchronousDispatch::dispatch( xDesktop, aName, aTarget, 0, aArgs ), UNO_QUERY ); + } + catch (const ::com::sun::star::lang::IllegalArgumentException& iae) + { + OUString aMsg = OUString(RTL_CONSTASCII_USTRINGPARAM( + "Dispatchwatcher IllegalArgumentException while calling loadComponentFromURL: ")) + + iae.Message; + OSL_FAIL( OUStringToOString(aMsg, RTL_TEXTENCODING_ASCII_US).getStr()); + } + catch (const com::sun::star::io::IOException& ioe) + { + OUString aMsg = OUString(RTL_CONSTASCII_USTRINGPARAM( + "Dispatchwatcher IOException while calling loadComponentFromURL: ")) + + ioe.Message; + OSL_FAIL( OUStringToOString(aMsg, RTL_TEXTENCODING_ASCII_US).getStr()); + } + if ( aDispatchRequest.aRequestType == REQUEST_OPEN || + aDispatchRequest.aRequestType == REQUEST_VIEW || + aDispatchRequest.aRequestType == REQUEST_START || + aDispatchRequest.aRequestType == REQUEST_FORCEOPEN || + aDispatchRequest.aRequestType == REQUEST_FORCENEW ) + { + // request is completed + OfficeIPCThread::RequestsCompleted( 1 ); + } + else if ( aDispatchRequest.aRequestType == REQUEST_PRINT || + aDispatchRequest.aRequestType == REQUEST_PRINTTO || + aDispatchRequest.aRequestType == REQUEST_BATCHPRINT || + aDispatchRequest.aRequestType == REQUEST_CONVERSION ) + { + if ( xDoc.is() ) + { + if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION ) { + Reference< XStorable > xStorable( xDoc, UNO_QUERY ); + if ( xStorable.is() ) { + rtl::OUString aParam = aDispatchRequest.aPrinterName; + sal_Int32 nPathIndex = aParam.lastIndexOfAsciiL( ";", 1 ); + sal_Int32 nFilterIndex = aParam.indexOfAsciiL( ":", 1 ); + if( nPathIndex < nFilterIndex ) + nFilterIndex = -1; + rtl::OUString aFilterOut=aParam.copy( nPathIndex+1 ); + rtl::OUString aFilter; + rtl::OUString aFilterExt; + sal_Bool bGuess = sal_False; + + if( nFilterIndex >= 0 ) + { + aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 ); + aFilterExt = aParam.copy( 0, nFilterIndex ); + } + else + { + // Guess + bGuess = sal_True; + aFilterExt = aParam.copy( 0, nPathIndex ); + } + INetURLObject aOutFilename( aObj ); + aOutFilename.SetExtension( aFilterExt ); + FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut ); + rtl::OUString aOutFile = aFilterOut+ + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "/" ))+ + aOutFilename.getName(); + + if ( bGuess ) + { + aFilter = impl_GuessFilter( aName, aOutFile ); + } + + Sequence<PropertyValue> conversionProperties( 2 ); + conversionProperties[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Overwrite" )); + conversionProperties[0].Value <<= sal_True; + + conversionProperties[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "FilterName" )); + conversionProperties[1].Value <<= aFilter; + + rtl::OUString aTempName; + FileBase::getSystemPathFromFileURL( aName, aTempName ); + rtl::OString aSource8 = ::rtl::OUStringToOString ( aTempName, RTL_TEXTENCODING_UTF8 ); + FileBase::getSystemPathFromFileURL( aOutFile, aTempName ); + rtl::OString aTargetURL8 = ::rtl::OUStringToOString(aTempName, RTL_TEXTENCODING_UTF8 ); + printf("convert %s -> %s using %s\n", aSource8.getStr(), aTargetURL8.getStr(), + ::rtl::OUStringToOString( aFilter, RTL_TEXTENCODING_UTF8 ).getStr()); + if( FStatHelper::IsDocument(aOutFile) ) + printf("Overwriting: %s\n",::rtl::OUStringToOString( aTempName, RTL_TEXTENCODING_UTF8 ).getStr() ); + try + { + xStorable->storeToURL( aOutFile, conversionProperties ); + } + catch (const Exception&) + { + fprintf( stderr, "Error: Please reverify input parameters...\n" ); + } + } + } else if ( aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ) { + rtl::OUString aParam = aDispatchRequest.aPrinterName; + sal_Int32 nPathIndex = aParam.lastIndexOfAsciiL( ";", 1 ); + + rtl::OUString aFilterOut; + rtl::OUString aPrinterName; + if( nPathIndex != -1 ) + aFilterOut=aParam.copy( nPathIndex+1 ); + if( nPathIndex != 0 ) + aPrinterName=aParam.copy( 0, nPathIndex ); + + INetURLObject aOutFilename( aObj ); + aOutFilename.SetExtension( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ps")) ); + FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut ); + rtl::OUString aOutFile = aFilterOut+ + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "/" ))+ + aOutFilename.getName(); + + rtl::OUString aTempName; + FileBase::getSystemPathFromFileURL( aName, aTempName ); + rtl::OString aSource8 = ::rtl::OUStringToOString ( aTempName, RTL_TEXTENCODING_UTF8 ); + FileBase::getSystemPathFromFileURL( aOutFile, aTempName ); + rtl::OString aTargetURL8 = ::rtl::OUStringToOString(aTempName, RTL_TEXTENCODING_UTF8 ); + printf("print %s -> %s using %s\n", aSource8.getStr(), aTargetURL8.getStr(), + aPrinterName.getLength() ? + ::rtl::OUStringToOString( aPrinterName, RTL_TEXTENCODING_UTF8 ).getStr() : "<default_printer>"); + + // create the custom printer, if given + Sequence < PropertyValue > aPrinterArgs( 1 ); + if( aPrinterName.getLength() ) + { + aPrinterArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")); + aPrinterArgs[0].Value <<= aPrinterName; + xDoc->setPrinter( aPrinterArgs ); + } + + // print ( also without user interaction ) + aPrinterArgs.realloc(2); + aPrinterArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FileName")); + aPrinterArgs[0].Value <<= aOutFile; + aPrinterArgs[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Wait")); + aPrinterArgs[1].Value <<= ( sal_Bool ) sal_True; + xDoc->print( aPrinterArgs ); + } else { + if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO ) + { + // create the printer + Sequence < PropertyValue > aPrinterArgs( 1 ); + aPrinterArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")); + aPrinterArgs[0].Value <<= ::rtl::OUString( aDispatchRequest.aPrinterName ); + xDoc->setPrinter( aPrinterArgs ); + } + + // print ( also without user interaction ) + Sequence < PropertyValue > aPrinterArgs( 1 ); + aPrinterArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Wait")); + aPrinterArgs[0].Value <<= ( sal_Bool ) sal_True; + xDoc->print( aPrinterArgs ); + } + } + else + { + // place error message here ... + } + + // remove the document + try + { + Reference < XCloseable > xClose( xDoc, UNO_QUERY ); + if ( xClose.is() ) + xClose->close( sal_True ); + else + { + Reference < XComponent > xComp( xDoc, UNO_QUERY ); + if ( xComp.is() ) + xComp->dispose(); + } + } + catch (const com::sun::star::util::CloseVetoException&) + { + } + + // request is completed + OfficeIPCThread::RequestsCompleted( 1 ); + } + } + } + + if ( !aDispatches.empty() ) + { + // Execute all asynchronous dispatches now after we placed them into our request container! + Sequence < PropertyValue > aArgs( 2 ); + aArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Referer")); + aArgs[0].Value <<= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:OpenEvent")); + aArgs[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SynchronMode")); + aArgs[1].Value <<= sal_True; + + for ( sal_uInt32 n = 0; n < aDispatches.size(); n++ ) + { + Reference< XDispatch > xDispatch = aDispatches[n].xDispatch; + Reference < XNotifyingDispatch > xDisp( xDispatch, UNO_QUERY ); + if ( xDisp.is() ) + xDisp->dispatchWithNotification( aDispatches[n].aURL, aArgs, this ); + else + { + ::osl::ClearableMutexGuard aGuard( GetMutex() ); + m_nRequestCount--; + aGuard.clear(); + xDispatch->dispatch( aDispatches[n].aURL, aArgs ); + } + } + } + + ::osl::ClearableMutexGuard aGuard( GetMutex() ); + bool bEmpty = (m_nRequestCount == 0); + aGuard.clear(); + + // No more asynchronous requests? + // The requests are removed from the request container after they called back to this + // implementation via statusChanged!! + if ( bEmpty && !bNoTerminate /*m_aRequestContainer.empty()*/ ) + { + // We have to check if we have an open task otherwise we have to shutdown the office. + Reference< XFramesSupplier > xTasksSupplier( xDesktop, UNO_QUERY ); + aGuard.clear(); + Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY ); + + if ( !xList->hasElements() ) + { + // We don't have any task open so we have to shutdown ourself!! + Reference< XDesktop > xDesktop2( xTasksSupplier, UNO_QUERY ); + if ( xDesktop2.is() ) + return xDesktop2->terminate(); + } + } + + return sal_False; +} + + +void SAL_CALL DispatchWatcher::disposing( const ::com::sun::star::lang::EventObject& ) +throw(::com::sun::star::uno::RuntimeException) +{ +} + + +void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException ) +{ + osl::ClearableMutexGuard aGuard( GetMutex() ); + sal_Int16 nCount = --m_nRequestCount; + aGuard.clear(); + OfficeIPCThread::RequestsCompleted( 1 ); + if ( !nCount && !OfficeIPCThread::AreRequestsPending() ) + { + // We have to check if we have an open task otherwise we have to shutdown the office. + Reference< XFramesSupplier > xTasksSupplier( ::comphelper::getProcessServiceFactory()->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + UNO_QUERY ); + Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY ); + + if ( !xList->hasElements() ) + { + // We don't have any task open so we have to shutdown ourself!! + Reference< XDesktop > xDesktop( xTasksSupplier, UNO_QUERY ); + if ( xDesktop.is() ) + xDesktop->terminate(); + } + } +} + +} + + + + + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/dispatchwatcher.hxx b/desktop/source/app/dispatchwatcher.hxx new file mode 100644 index 000000000000..7146a29b3fd2 --- /dev/null +++ b/desktop/source/app/dispatchwatcher.hxx @@ -0,0 +1,128 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_DISPATCHWATCHER_HXX +#define _DESKTOP_DISPATCHWATCHER_HXX + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/frame/XNotifyingDispatch.hpp> +#include <com/sun/star/frame/XDispatchResultListener.hpp> + +#include "officeipcthread.hxx" +#include <boost/unordered_map.hpp> +#include <vector> + +namespace desktop +{ + +/* + Class for controlls dispatching of command URL through office command line. There + are "dangerous" command URLs, that can result in a running office without UI. To prevent + this situation the implementation surveile all dispatches and looks for an open task if + there is arose a problem. If there is none the office will be shutdown to prevent a + running office without UI. +*/ + +struct OUStringHashCode +{ + size_t operator()( const ::rtl::OUString& sString ) const + { + return sString.hashCode(); + } +}; + +class DispatchWatcherHashMap : public ::boost::unordered_map< ::rtl::OUString, sal_Int32, OUStringHashCode, ::std::equal_to< ::rtl::OUString > > +{ + public: + inline void free() + { + DispatchWatcherHashMap().swap( *this ); + } +}; + +class DispatchWatcher : public ::cppu::WeakImplHelper1< ::com::sun::star::frame::XDispatchResultListener > +{ + public: + enum RequestType + { + REQUEST_OPEN, + REQUEST_VIEW, + REQUEST_START, + REQUEST_PRINT, + REQUEST_PRINTTO, + REQUEST_FORCEOPEN, + REQUEST_FORCENEW, + REQUEST_CONVERSION, + REQUEST_INFILTER, + REQUEST_BATCHPRINT + }; + + struct DispatchRequest + { + DispatchRequest( RequestType aType, const ::rtl::OUString& aFile, boost::optional< rtl::OUString > const & cwdUrl, const ::rtl::OUString& aPrinter, const ::rtl::OUString& aFact ) : + aRequestType( aType ), aURL( aFile ), aCwdUrl( cwdUrl ), aPrinterName( aPrinter ), aPreselectedFactory( aFact ) {} + + RequestType aRequestType; + rtl::OUString aURL; + boost::optional< rtl::OUString > aCwdUrl; + rtl::OUString aPrinterName; // also conversion params + rtl::OUString aPreselectedFactory; + }; + + typedef std::vector< DispatchRequest > DispatchList; + + virtual ~DispatchWatcher(); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw(::com::sun::star::uno::RuntimeException); + + // XDispachResultListener + virtual void SAL_CALL dispatchFinished( const com::sun::star::frame::DispatchResultEvent& aEvent ) throw( com::sun::star::uno::RuntimeException ); + + // Access function to get a dispatcher watcher reference. There must be a global reference holder + static DispatchWatcher* GetDispatchWatcher(); + + // execute new dispatch request + sal_Bool executeDispatchRequests( const DispatchList& aDispatches, bool bNoTerminate = false ); + + private: + DispatchWatcher(); + + static ::osl::Mutex& GetMutex(); + + DispatchWatcherHashMap m_aRequestContainer; + + sal_Int16 m_nRequestCount; +}; + +} + +#endif // _DESKTOP_DISPATCHWATCHER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/exports.dxp b/desktop/source/app/exports.dxp new file mode 100755 index 000000000000..70033078921a --- /dev/null +++ b/desktop/source/app/exports.dxp @@ -0,0 +1 @@ +component_getFactory diff --git a/desktop/source/app/langselect.cxx b/desktop/source/app/langselect.cxx new file mode 100644 index 000000000000..063fc69b2d35 --- /dev/null +++ b/desktop/source/app/langselect.cxx @@ -0,0 +1,561 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "app.hxx" +#include "langselect.hxx" +#include "cmdlineargs.hxx" +#include <stdio.h> + +#include <rtl/string.hxx> +#include <rtl/bootstrap.hxx> +#include <unotools/pathoptions.hxx> +#include <tools/resid.hxx> +#include <tools/config.hxx> +#include <i18npool/mslangid.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/lang/XLocalizable.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include "com/sun/star/util/XFlushable.hpp" +#include <rtl/locale.hxx> +#include <rtl/instance.hxx> +#include <osl/process.h> +#include <osl/file.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OString; + +namespace desktop { + +static char const SOFFICE_BOOTSTRAP[] = "Bootstrap"; +static char const SOFFICE_STARTLANG[] = "STARTLANG"; + +sal_Bool LanguageSelection::bFoundLanguage = sal_False; +OUString LanguageSelection::aFoundLanguage; +LanguageSelection::LanguageSelectionStatus LanguageSelection::m_eStatus = LS_STATUS_OK; + +const OUString LanguageSelection::usFallbackLanguage(RTL_CONSTASCII_USTRINGPARAM("en-US")); + +static sal_Bool existsURL( OUString const& sURL ) +{ + using namespace osl; + DirectoryItem aDirItem; + + if (sURL.getLength() != 0) + return ( DirectoryItem::get( sURL, aDirItem ) == DirectoryItem::E_None ); + + return sal_False; +} + +// locate soffice.ini/.rc file +static OUString locateSofficeIniFile() +{ + OUString aUserDataPath; + OUString aSofficeIniFileURL; + + // Retrieve the default file URL for the soffice.ini/rc + rtl::Bootstrap().getIniName( aSofficeIniFileURL ); + + if ( utl::Bootstrap::locateUserData( aUserDataPath ) == utl::Bootstrap::PATH_EXISTS ) + { + const char CONFIG_DIR[] = "/config"; + + sal_Int32 nIndex = aSofficeIniFileURL.lastIndexOf( '/'); + if ( nIndex > 0 ) + { + OUString aUserSofficeIniFileURL; + OUStringBuffer aBuffer( aUserDataPath ); + aBuffer.appendAscii( CONFIG_DIR ); + aBuffer.append( aSofficeIniFileURL.copy( nIndex )); + aUserSofficeIniFileURL = aBuffer.makeStringAndClear(); + + if ( existsURL( aUserSofficeIniFileURL )) + return aUserSofficeIniFileURL; + } + } + // Fallback try to use the soffice.ini/rc from program folder + return aSofficeIniFileURL; +} + +Locale LanguageSelection::IsoStringToLocale(const OUString& str) +{ + Locale l; + sal_Int32 index=0; + l.Language = str.getToken(0, '-', index); + if (index >= 0) l.Country = str.getToken(0, '-', index); + if (index >= 0) l.Variant = str.getToken(0, '-', index); + return l; +} + +bool LanguageSelection::prepareLanguage() +{ + m_eStatus = LS_STATUS_OK; + OUString sConfigSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")); + Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory(); + Reference< XLocalizable > theConfigProvider; + try + { + theConfigProvider = Reference< XLocalizable >(theMSF->createInstance( sConfigSrvc ),UNO_QUERY_THROW ); + } + catch(const Exception&) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + } + + if(!theConfigProvider.is()) + return false; + + sal_Bool bSuccess = sal_False; + + // #i42730#get the windows 16Bit locale - it should be preferred over the UI language + try + { + Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.System/L10N/", sal_False), UNO_QUERY_THROW); + Any aWin16SysLocale = xProp->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("SystemLocale"))); + ::rtl::OUString sWin16SysLocale; + aWin16SysLocale >>= sWin16SysLocale; + if( sWin16SysLocale.getLength()) + setDefaultLanguage(sWin16SysLocale); + } + catch(const Exception&) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + } + + // #i32939# use system locale to set document default locale + try + { + OUString usLocale; + Reference< XPropertySet > xLocaleProp(getConfigAccess( + "org.openoffice.System/L10N", sal_True), UNO_QUERY_THROW); + xLocaleProp->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Locale"))) >>= usLocale; + setDefaultLanguage(usLocale); + } + catch (Exception&) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + } + + // get the selected UI language as string + bool bCmdLanguage( false ); + bool bIniLanguage( false ); + OUString aLocaleString = getUserUILanguage(); + + if ( aLocaleString.getLength() == 0 ) + { + OUString aEmpty; + + const CommandLineArgs& rCmdLineArgs = Desktop::GetCommandLineArgs(); + rCmdLineArgs.GetLanguage(aLocaleString); + if (isInstalledLanguage(aLocaleString, sal_False)) + { + bCmdLanguage = true; + bFoundLanguage = true; + aFoundLanguage = aLocaleString; + } + else + aLocaleString = aEmpty; + + if ( !bCmdLanguage ) + { + OUString aSOfficeIniURL = locateSofficeIniFile(); + Config aConfig(aSOfficeIniURL); + aConfig.SetGroup( SOFFICE_BOOTSTRAP ); + OString sLang = aConfig.ReadKey( SOFFICE_STARTLANG ); + aLocaleString = OUString( sLang.getStr(), sLang.getLength(), RTL_TEXTENCODING_ASCII_US ); + if (isInstalledLanguage(aLocaleString, sal_False)) + { + bIniLanguage = true; + bFoundLanguage = true; + aFoundLanguage = aLocaleString; + } + else + aLocaleString = aEmpty; + } + } + + // user further fallbacks for the UI language + if ( aLocaleString.getLength() == 0 ) + aLocaleString = getLanguageString(); + + if ( aLocaleString.getLength() > 0 ) + { + try + { + // prepare default config provider by localizing it to the selected locale + // this will ensure localized configuration settings to be selected accoring to the + // UI language. + Locale loc = LanguageSelection::IsoStringToLocale(aLocaleString); + // flush any data already written to the configuration (which + // currently uses independent caches for different locales and thus + // would ignore data written to another cache): + Reference< XFlushable >(theConfigProvider, UNO_QUERY_THROW)-> + flush(); + theConfigProvider->setLocale(loc); + + Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.Setup/L10N/", sal_True), UNO_QUERY_THROW); + if ( !bCmdLanguage ) + { + // Store language only + xProp->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("ooLocale")), makeAny(aLocaleString)); + Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges(); + } + + if ( bIniLanguage ) + { + // Store language only + Reference< XPropertySet > xProp2(getConfigAccess("org.openoffice.Office.Linguistic/General/", sal_True), UNO_QUERY_THROW); + xProp2->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("UILocale")), makeAny(aLocaleString)); + Reference< XChangesBatch >(xProp2, UNO_QUERY_THROW)->commitChanges(); + } + + MsLangId::setConfiguredSystemUILanguage( MsLangId::convertLocaleToLanguage(loc) ); + + OUString sLocale; + xProp->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("ooSetupSystemLocale"))) >>= sLocale; + if ( sLocale.getLength() ) + { + loc = LanguageSelection::IsoStringToLocale(sLocale); + MsLangId::setConfiguredSystemLanguage( MsLangId::convertLocaleToLanguage(loc) ); + } + else + MsLangId::setConfiguredSystemLanguage( MsLangId::getSystemLanguage() ); + + bSuccess = sal_True; + } + catch ( PropertyVetoException& ) + { + // we are not allowed to change this + } + catch (Exception& e) + { + OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(aMsg.getStr()); + + } + } + + // #i32939# setting of default document locale + // #i32939# this should not be based on the UI language + setDefaultLanguage(aLocaleString); + + return bSuccess; +} + +void LanguageSelection::setDefaultLanguage(const OUString& sLocale) +{ + // #i32939# setting of default document language + // See #i42730# for rules for determining source of settings + + // determine script type of locale + LanguageType nLang = MsLangId::convertIsoStringToLanguage(sLocale); + sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage(nLang); + + switch (nScriptType) + { + case SCRIPTTYPE_ASIAN: + MsLangId::setConfiguredAsianFallback( nLang ); + break; + case SCRIPTTYPE_COMPLEX: + MsLangId::setConfiguredComplexFallback( nLang ); + break; + default: + MsLangId::setConfiguredWesternFallback( nLang ); + break; + } +} + +OUString LanguageSelection::getUserUILanguage() +{ + // check whether the user has selected a specific language + OUString aUserLanguage = getUserLanguage(); + if (aUserLanguage.getLength() > 0 ) + { + if (isInstalledLanguage(aUserLanguage)) + { + // all is well + bFoundLanguage = sal_True; + aFoundLanguage = aUserLanguage; + return aFoundLanguage; + } + else + { + // selected language is not/no longer installed + resetUserLanguage(); + } + } + + return aUserLanguage; +} + +OUString LanguageSelection::getLanguageString() +{ + // did we already find a language? + if (bFoundLanguage) + return aFoundLanguage; + + // check whether the user has selected a specific language + OUString aUserLanguage = getUserUILanguage(); + if (aUserLanguage.getLength() > 0 ) + return aUserLanguage ; + + // try to use system default + aUserLanguage = getSystemLanguage(); + if (aUserLanguage.getLength() > 0 ) + { + if (isInstalledLanguage(aUserLanguage, sal_False)) + { + // great, system default language is available + bFoundLanguage = sal_True; + aFoundLanguage = aUserLanguage; + return aFoundLanguage; + } + } + // fallback 1: en-US + OUString usFB = usFallbackLanguage; + if (isInstalledLanguage(usFB)) + { + bFoundLanguage = sal_True; + aFoundLanguage = usFallbackLanguage; + return aFoundLanguage; + } + + // fallback didn't work use first installed language + aUserLanguage = getFirstInstalledLanguage(); + + bFoundLanguage = sal_True; + aFoundLanguage = aUserLanguage; + return aFoundLanguage; +} + +Reference< XNameAccess > LanguageSelection::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate) +{ + Reference< XNameAccess > xNameAccess; + try{ + OUString sConfigSrvc(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")); + OUString sAccessSrvc; + if (bUpdate) + sAccessSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationUpdateAccess")); + else + sAccessSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")); + + OUString sConfigURL = OUString::createFromAscii(pPath); + + // get configuration provider + Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory(); + if (theMSF.is()) { + Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory > ( + theMSF->createInstance( sConfigSrvc ),UNO_QUERY_THROW ); + + // access the provider + Sequence< Any > theArgs(1); + theArgs[ 0 ] <<= sConfigURL; + xNameAccess = Reference< XNameAccess > ( + theConfigProvider->createInstanceWithArguments( + sAccessSrvc, theArgs ), UNO_QUERY_THROW ); + } + } catch (com::sun::star::uno::Exception& e) + { + OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(aMsg.getStr()); + } + return xNameAccess; +} + +Sequence< OUString > LanguageSelection::getInstalledLanguages() +{ + Sequence< OUString > seqLanguages; + Reference< XNameAccess > xAccess = getConfigAccess("org.openoffice.Setup/Office/InstalledLocales", sal_False); + if (!xAccess.is()) return seqLanguages; + seqLanguages = xAccess->getElementNames(); + return seqLanguages; +} + +// FIXME +// it's not very clever to handle language fallbacks here, but +// right now, there is no place that handles those fallbacks globally +static Sequence< OUString > _getFallbackLocales(const OUString& aIsoLang) +{ + Sequence< OUString > seqFallbacks; + if (aIsoLang.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("zh-HK"))) { + seqFallbacks = Sequence< OUString >(1); + seqFallbacks[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("zh-TW")); + } + return seqFallbacks; +} + +sal_Bool LanguageSelection::isInstalledLanguage(OUString& usLocale, sal_Bool bExact) +{ + sal_Bool bInstalled = sal_False; + Sequence< OUString > seqLanguages = getInstalledLanguages(); + for (sal_Int32 i=0; i<seqLanguages.getLength(); i++) + { + if (usLocale.equals(seqLanguages[i])) + { + bInstalled = sal_True; + break; + } + } + + if (!bInstalled && !bExact) + { + // try fallback locales + Sequence< OUString > seqFallbacks = _getFallbackLocales(usLocale); + for (sal_Int32 j=0; j<seqFallbacks.getLength(); j++) + { + for (sal_Int32 i=0; i<seqLanguages.getLength(); i++) + { + if (seqFallbacks[j].equals(seqLanguages[i])) + { + bInstalled = sal_True; + usLocale = seqFallbacks[j]; + break; + } + } + } + } + + if (!bInstalled && !bExact) + { + // no exact match was found, well try to find a substitute + OUString aInstalledLocale; + for (sal_Int32 i=0; i<seqLanguages.getLength(); i++) + { + if (usLocale.indexOf(seqLanguages[i]) == 0) + { + // requested locale starts with the installed locale + // (i.e. installed locale has index 0 in requested locale) + bInstalled = sal_True; + usLocale = seqLanguages[i]; + break; + } + } + } + return bInstalled; +} + +OUString LanguageSelection::getFirstInstalledLanguage() +{ + OUString aLanguage; + Sequence< OUString > seqLanguages = getInstalledLanguages(); + if (seqLanguages.getLength() > 0) + aLanguage = seqLanguages[0]; + return aLanguage; +} + +OUString LanguageSelection::getUserLanguage() +{ + OUString aUserLanguage; + Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_False)); + if (xAccess.is()) + { + try + { + xAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("UILocale"))) >>= aUserLanguage; + } + catch ( NoSuchElementException const & ) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + return OUString(); + } + catch ( WrappedTargetException const & ) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + return OUString(); + } + } + return aUserLanguage; +} + +OUString LanguageSelection::getSystemLanguage() +{ + OUString aUserLanguage; + Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.System/L10N", sal_False)); + if (xAccess.is()) + { + try + { + xAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("UILocale"))) >>= aUserLanguage; + } + catch ( NoSuchElementException const & ) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + return OUString(); + } + catch ( WrappedTargetException const & ) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + return OUString(); + } + } + return aUserLanguage; +} + + +void LanguageSelection::resetUserLanguage() +{ + try + { + Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_True), UNO_QUERY_THROW); + xProp->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("UILocale")), makeAny(OUString())); + Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges(); + } + catch ( PropertyVetoException& ) + { + // we are not allowed to change this + } + catch ( Exception& e) + { + OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(aMsg.getStr()); + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + } +} + +LanguageSelection::LanguageSelectionStatus LanguageSelection::getStatus() +{ + return m_eStatus; +} + +} // namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/langselect.hxx b/desktop/source/app/langselect.hxx new file mode 100644 index 000000000000..fdb229a47956 --- /dev/null +++ b/desktop/source/app/langselect.hxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <list> +#include <sal/types.h> +#include <tools/string.hxx> +#include <rtl/ustring.hxx> +#include <tools/resid.hxx> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <svl/languageoptions.hxx> + +namespace desktop +{ + +class LanguageSelection +{ +public: + enum LanguageSelectionStatus + { + LS_STATUS_OK, + LS_STATUS_CANNOT_DETERMINE_LANGUAGE, + LS_STATUS_CONFIGURATIONACCESS_BROKEN + }; + + static com::sun::star::lang::Locale IsoStringToLocale(const rtl::OUString& str); + static rtl::OUString getLanguageString(); + static bool prepareLanguage(); + static LanguageSelectionStatus getStatus(); + +private: + static const rtl::OUString usFallbackLanguage; + static rtl::OUString aFoundLanguage; + static sal_Bool bFoundLanguage; + static LanguageSelectionStatus m_eStatus; + + static com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > + getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate=sal_False); + static com::sun::star::uno::Sequence< rtl::OUString > getInstalledLanguages(); + static sal_Bool isInstalledLanguage(rtl::OUString& usLocale, sal_Bool bExact=sal_False); + static rtl::OUString getFirstInstalledLanguage(); + static rtl::OUString getUserUILanguage(); + static rtl::OUString getUserLanguage(); + static rtl::OUString getSystemLanguage(); + static void resetUserLanguage(); + static void setDefaultLanguage(const rtl::OUString&); +}; + +} //namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/lockfile.cxx b/desktop/source/app/lockfile.cxx new file mode 100644 index 000000000000..72632bdb5e27 --- /dev/null +++ b/desktop/source/app/lockfile.cxx @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <stdlib.h> +#include <time.h> +#ifndef WNT +#include <unistd.h> +#else +#include <windows.h> +#endif +#include <sal/types.h> +#include <osl/file.hxx> +#include <osl/socket.hxx> +#include <osl/security.hxx> +#include <unotools/bootstrap.hxx> +#include <tools/string.hxx> +#include <tools/config.hxx> + +#include "lockfile.hxx" + + +using namespace ::osl; +using namespace ::rtl; +using namespace ::utl; + + +static rtl::OString impl_getHostname() +{ + rtl::OString aHost; +#ifdef WNT + /* + prevent windows from connecting to the net to get it's own + hostname by using the netbios name + */ + sal_Int32 sz = MAX_COMPUTERNAME_LENGTH + 1; + char* szHost = new char[sz]; + if (GetComputerName(szHost, (LPDWORD)&sz)) + aHost = OString(szHost); + else + aHost = OString("UNKNOWN"); + delete[] szHost; +#else + /* Don't do dns lookup on Linux either */ + sal_Char pHostName[1024]; + + if ( gethostname( pHostName, sizeof( pHostName ) - 1 ) == 0 ) + { + pHostName[sizeof( pHostName ) - 1] = '\0'; + aHost = OString( pHostName ); + } + else + aHost = OString("UNKNOWN"); +#endif + + return aHost; +} + +namespace desktop { + + Lockfile::Lockfile( bool bIPCserver ) + :m_bIPCserver(bIPCserver) + ,m_bRemove(sal_False) + ,m_bIsLocked(sal_False) + { + // build the file-url to use for the lock + OUString aUserPath; + utl::Bootstrap::locateUserInstallation( aUserPath ); + m_aLockname = aUserPath + LOCKFILE_SUFFIX; + + // generate ID + const int nIdBytes = 16; + char tmpId[nIdBytes*2+1]; + time_t t; + srand( (unsigned)(t = time( NULL )) ); + int tmpByte = 0; + for (int i = 0; i<nIdBytes; i++) { + tmpByte = rand( ) % 0xFF; + sprintf( tmpId+i*2, "%02X", tmpByte ); + } + tmpId[nIdBytes*2]=0x00; + m_aId = OUString::createFromAscii( tmpId ); + + // generate date string + char *tmpTime = ctime( &t ); + if (tmpTime != NULL) { + m_aDate = OUString::createFromAscii( tmpTime ); + sal_Int32 i = m_aDate.indexOf('\n'); + if (i > 0) + m_aDate = m_aDate.copy(0, i); + } + + + // try to create file + File aFile(m_aLockname); + if (aFile.open( osl_File_OpenFlag_Create ) == File::E_EXIST) { + m_bIsLocked = sal_True; + } else { + // new lock created + aFile.close( ); + syncToFile( ); + m_bRemove = sal_True; + } + } + + sal_Bool Lockfile::check( fpExecWarning execWarning ) + { + + if (m_bIsLocked) { + // lock existed, ask user what to do + if (isStale() || + (execWarning != 0 && (*execWarning)( this ))) { + // remove file and create new + File::remove( m_aLockname ); + File aFile(m_aLockname); + aFile.open( osl_File_OpenFlag_Create ); + aFile.close( ); + syncToFile( ); + m_bRemove = sal_True; + return sal_True; + } else { + //leave alone and return false + m_bRemove = sal_False; + return sal_False; + } + } else { + // lock was created by us + return sal_True; + } + } + + sal_Bool Lockfile::isStale( void ) const + { + // this checks whether the lockfile was created on the same + // host by the same user. Should this be the case it is safe + // to assume that it is a stale lockfile which can be overwritten + String aLockname = m_aLockname; + Config aConfig(aLockname); + aConfig.SetGroup(LOCKFILE_GROUP); + rtl::OString aIPCserver = aConfig.ReadKey( LOCKFILE_IPCKEY ); + if (!aIPCserver.equalsIgnoreAsciiCase(rtl::OString("true"))) + return false; + + rtl::OString aHost = aConfig.ReadKey( LOCKFILE_HOSTKEY ); + rtl::OString aUser = aConfig.ReadKey( LOCKFILE_USERKEY ); + + // lockfile from same host? + rtl::OString myHost( impl_getHostname() ); + if (aHost == myHost) { + // lockfile by same UID + OUString myUserName; + Security aSecurity; + aSecurity.getUserName( myUserName ); + rtl::OString myUser(rtl::OUStringToOString(myUserName, RTL_TEXTENCODING_ASCII_US)); + if (aUser == myUser) + return sal_True; + } + return sal_False; + } + + void Lockfile::syncToFile( void ) const + { + String aLockname = m_aLockname; + Config aConfig(aLockname); + aConfig.SetGroup(LOCKFILE_GROUP); + + // get information + rtl::OString aHost( impl_getHostname() ); + OUString aUserName; + Security aSecurity; + aSecurity.getUserName( aUserName ); + rtl::OString aUser = OUStringToOString( aUserName, RTL_TEXTENCODING_ASCII_US ); + rtl::OString aTime = OUStringToOString( m_aDate, RTL_TEXTENCODING_ASCII_US ); + rtl::OString aStamp = OUStringToOString( m_aId, RTL_TEXTENCODING_ASCII_US ); + + // write information + aConfig.WriteKey( LOCKFILE_USERKEY, aUser ); + aConfig.WriteKey( LOCKFILE_HOSTKEY, aHost ); + aConfig.WriteKey( LOCKFILE_STAMPKEY, aStamp ); + aConfig.WriteKey( LOCKFILE_TIMEKEY, aTime ); + aConfig.WriteKey( + LOCKFILE_IPCKEY, + m_bIPCserver ? rtl::OString("true") : rtl::OString("false") ); + aConfig.Flush( ); + } + + void Lockfile::clean( void ) + { + if ( m_bRemove ) + { + File::remove( m_aLockname ); + m_bRemove = sal_False; + } + } + + Lockfile::~Lockfile( void ) + { + // unlock userdata by removing file + if ( m_bRemove ) + File::remove( m_aLockname ); + } +} + + + + + + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/lockfile.hxx b/desktop/source/app/lockfile.hxx new file mode 100644 index 000000000000..5444714ec88c --- /dev/null +++ b/desktop/source/app/lockfile.hxx @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +/* Information: + * This class implements a mechanism to lock a users installation directory, + * which is necessesary because instances of staroffice could be running on + * different hosts while using the same directory thus causing data + * inconsistency. + * When an existing lock is detected, the user will be asked whether he wants + * to continue anyway, thus removing the lock and replacing it with a new one + * + * ideas: + * - store information about user and host and time in the lockfile and display + * these when asking whether to remove the lockfile. + * - periodically check the lockfile and warn the user when it gets replaced + * + */ + +#include "sal/types.h" +#include "rtl/ustring.hxx" + +class ByteString; + +#define LOCKFILE_SUFFIX rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/.lock" ) ) +#define LOCKFILE_GROUP ByteString( "Lockdata" ) +#define LOCKFILE_USERKEY ByteString( "User" ) +#define LOCKFILE_HOSTKEY ByteString( "Host" ) +#define LOCKFILE_STAMPKEY ByteString( "Stamp" ) +#define LOCKFILE_TIMEKEY ByteString( "Time" ) +#define LOCKFILE_IPCKEY ByteString( "IPCServer" ) + +namespace desktop { + + class Lockfile; + bool Lockfile_execWarning( Lockfile * that ); + + class Lockfile + { + public: + + // contructs a new lockfile onject + Lockfile( bool bIPCserver = true ); + + // separating GUI code: + typedef bool (* fpExecWarning)( Lockfile * that ); + + // checks the lockfile, asks user when lockfile is + // found (iff gui) and returns false when we may not continue + sal_Bool check( fpExecWarning execWarning ); + + // removes the lockfile. should only be called in exceptional situations + void clean(void); + + // removes the lockfile + ~Lockfile(void); + + private: + bool m_bIPCserver; + // full qualified name (file://-url) of the lockfile + rtl::OUString m_aLockname; + // flag whether the d'tor should delete the lock + sal_Bool m_bRemove; + sal_Bool m_bIsLocked; + // ID + rtl::OUString m_aId; + rtl::OUString m_aDate; + // access to data in file + void syncToFile(void) const; + sal_Bool isStale(void) const; + friend bool Lockfile_execWarning( Lockfile * that ); + + }; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/lockfile2.cxx b/desktop/source/app/lockfile2.cxx new file mode 100644 index 000000000000..619102b70c2b --- /dev/null +++ b/desktop/source/app/lockfile2.cxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "vcl/msgbox.hxx" +#include "desktopresid.hxx" +#include "desktop.hrc" +#include "tools/config.hxx" +#include "lockfile.hxx" + + +namespace desktop { + +bool Lockfile_execWarning( Lockfile * that ) +{ + // read information from lock + String aLockname = that->m_aLockname; + Config aConfig(aLockname); + aConfig.SetGroup( LOCKFILE_GROUP ); + ByteString aHost = aConfig.ReadKey( LOCKFILE_HOSTKEY ); + ByteString aUser = aConfig.ReadKey( LOCKFILE_USERKEY ); + ByteString aStamp = aConfig.ReadKey( LOCKFILE_STAMPKEY ); + ByteString aTime = aConfig.ReadKey( LOCKFILE_TIMEKEY ); + + // display warning and return response + QueryBox aBox( NULL, DesktopResId( QBX_USERDATALOCKED ) ); + // set box title + String aTitle = String( DesktopResId( STR_TITLE_USERDATALOCKED )); + aBox.SetText( aTitle ); + // insert values... + String aMsgText = aBox.GetMessText( ); + aMsgText.SearchAndReplaceAscii( + "$u", String( aUser, RTL_TEXTENCODING_ASCII_US) ); + aMsgText.SearchAndReplaceAscii( + "$h", String( aHost, RTL_TEXTENCODING_ASCII_US) ); + aMsgText.SearchAndReplaceAscii( + "$t", String( aTime, RTL_TEXTENCODING_ASCII_US) ); + aBox.SetMessText(aMsgText); + // do it + return aBox.Execute( ) == RET_YES; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/main.c b/desktop/source/app/main.c new file mode 100755 index 000000000000..88610ba18ef9 --- /dev/null +++ b/desktop/source/app/main.c @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "sofficemain.h" + +SAL_IMPLEMENT_MAIN() { + return soffice_main(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/makefile.mk b/desktop/source/app/makefile.mk new file mode 100755 index 000000000000..f905bd6ea296 --- /dev/null +++ b/desktop/source/app/makefile.mk @@ -0,0 +1,113 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=dkt +AUTOSEG=true +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : ../deployment/inc/dp_misc.mk + +.IF "$(ENABLE_GNOMEVFS)"=="TRUE" +CFLAGS+=-DGNOME_VFS_ENABLED +.ENDIF + +# .IF "$(OS)" == "WNT" +# .IF "$(COM)" == "GCC" +# DEPLOYMENTMISCLIB = -ldeploymentmisc$(DLLPOSTFIX) +# .ELSE +# DEPLOYMENTMISCLIB = ideploymentmisc$(DLLPOSTFIX).lib +# .ENDIF +# .ELSE +# DEPLOYMENTMISCLIB = -ldeploymentmisc$(DLLPOSTFIX) +# .ENDIF + +.IF "$(GUI)"=="WNT" || "$(GUIBASE)"=="aqua" || "$(ENABLE_SYSTRAY_GTK)"=="TRUE" +CFLAGS+=-DENABLE_QUICKSTART_APPLET +.ENDIF + +SHL1TARGET = sofficeapp +SHL1OBJS = \ + $(SLO)$/app.obj \ + $(SLO)$/appfirststart.obj \ + $(SLO)$/appinit.obj \ + $(SLO)$/appsys.obj \ + $(SLO)$/check_ext_deps.obj \ + $(SLO)$/cmdlineargs.obj \ + $(SLO)$/cmdlinehelp.obj \ + $(SLO)$/configinit.obj \ + $(SLO)$/desktopcontext.obj \ + $(SLO)$/desktopresid.obj \ + $(SLO)$/dispatchwatcher.obj \ + $(SLO)$/langselect.obj \ + $(SLO)$/lockfile.obj \ + $(SLO)$/lockfile2.obj \ + $(SLO)$/officeipcthread.obj \ + $(SLO)$/sofficemain.obj \ + $(SLO)$/userinstall.obj + +SHL1LIBS = $(SLB)$/mig.lib + +SHL1STDLIBS = \ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(DEPLOYMENTMISCLIB) \ + $(I18NISOLANGLIB) \ + $(SALLIB) \ + $(SFXLIB) \ + $(SVLLIB) \ + $(SVTOOLLIB) \ + $(TKLIB) \ + $(TOOLSLIB) \ + $(UCBHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(VCLLIB) \ + +SHL1VERSIONMAP = version.map +SHL1IMPLIB = i$(SHL1TARGET) +DEF1NAME = $(SHL1TARGET) + +OBJFILES = \ + $(OBJ)$/copyright_ascii_ooo.obj \ + $(OBJ)$/main.obj \ + $(OBJ)$/copyright_ascii_sun.obj + +SLOFILES = $(SHL1OBJS) + +SRS1NAME= desktop +SRC1FILES= desktop.src + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/desktop/source/app/officeipcthread.cxx b/desktop/source/app/officeipcthread.cxx new file mode 100644 index 000000000000..022ccf1eada2 --- /dev/null +++ b/desktop/source/app/officeipcthread.cxx @@ -0,0 +1,1037 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "app.hxx" +#include "officeipcthread.hxx" +#include "cmdlineargs.hxx" +#include "dispatchwatcher.hxx" +#include <memory> +#include <stdio.h> +#include <osl/process.h> +#include <unotools/bootstrap.hxx> +#include <vcl/svapp.hxx> +#include <vcl/help.hxx> +#include <unotools/configmgr.hxx> +#include <osl/thread.hxx> +#include <rtl/digest.h> +#include <rtl/ustrbuf.hxx> +#include <rtl/instance.hxx> +#include <osl/conditn.hxx> +#include <unotools/moduleoptions.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/strbuf.hxx> +#include <comphelper/processfactory.hxx> +#include <osl/file.hxx> +#include <rtl/process.h> +#include <rtl/instance.hxx> +#include "tools/getprocessworkingdir.hxx" + +using namespace desktop; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; + +using ::rtl::OString; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +const char *OfficeIPCThread::sc_aTerminationSequence = "InternalIPC::TerminateThread"; +const int OfficeIPCThread::sc_nTSeqLength = 28; +const char *OfficeIPCThread::sc_aShowSequence = "-tofront"; +const int OfficeIPCThread::sc_nShSeqLength = 5; +const char *OfficeIPCThread::sc_aConfirmationSequence = "InternalIPC::ProcessingDone"; +const int OfficeIPCThread::sc_nCSeqLength = 27; + +namespace { static char const ARGUMENT_PREFIX[] = "InternalIPC::Arguments"; } + +// Type of pipe we use +enum PipeMode +{ + PIPEMODE_DONTKNOW, + PIPEMODE_CREATED, + PIPEMODE_CONNECTED +}; + +namespace desktop +{ + +namespace { + +class Parser: public CommandLineArgs::Supplier { +public: + explicit Parser(rtl::OString const & input): m_input(input) { + if (!m_input.match(ARGUMENT_PREFIX) || + m_input.getLength() == RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX)) + { + throw CommandLineArgs::Supplier::Exception(); + } + m_index = RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX); + switch (m_input[m_index++]) { + case '0': + break; + case '1': + { + rtl::OUString url; + if (!next(&url, false)) { + throw CommandLineArgs::Supplier::Exception(); + } + m_cwdUrl.reset(url); + break; + } + case '2': + { + rtl::OUString path; + if (!next(&path, false)) { + throw CommandLineArgs::Supplier::Exception(); + } + rtl::OUString url; + if (osl::FileBase::getFileURLFromSystemPath(path, url) == + osl::FileBase::E_None) + { + m_cwdUrl.reset(url); + } + break; + } + default: + throw CommandLineArgs::Supplier::Exception(); + } + } + + virtual ~Parser() {} + + virtual boost::optional< rtl::OUString > getCwdUrl() { return m_cwdUrl; } + + virtual bool next(rtl::OUString * argument) { return next(argument, true); } + +private: + virtual bool next(rtl::OUString * argument, bool prefix) { + OSL_ASSERT(argument != NULL); + if (m_index < m_input.getLength()) { + if (prefix) { + if (m_input[m_index] != ',') { + throw CommandLineArgs::Supplier::Exception(); + } + ++m_index; + } + rtl::OStringBuffer b; + while (m_index < m_input.getLength()) { + char c = m_input[m_index]; + if (c == ',') { + break; + } + ++m_index; + if (c == '\\') { + if (m_index < m_input.getLength()) { + c = m_input[m_index++]; + switch (c) { + case '0': + c = '\0'; + break; + case ',': + case '\\': + break; + default: + throw CommandLineArgs::Supplier::Exception(); + } + } else { + throw CommandLineArgs::Supplier::Exception(); + } + } + b.append(c); + } + rtl::OString b2(b.makeStringAndClear()); + if (!rtl_convertStringToUString( + &argument->pData, b2.getStr(), b2.getLength(), + RTL_TEXTENCODING_UTF8, + (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR | + RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR | + RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) + { + throw CommandLineArgs::Supplier::Exception(); + } + return true; + } else { + return false; + } + } + + boost::optional< rtl::OUString > m_cwdUrl; + rtl::OString m_input; + sal_Int32 m_index; +}; + +bool addArgument( + ByteString * arguments, char prefix, rtl::OUString const & argument) +{ + rtl::OString utf8; + if (!argument.convertToString( + &utf8, RTL_TEXTENCODING_UTF8, + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + return false; + } + *arguments += prefix; + for (sal_Int32 i = 0; i < utf8.getLength(); ++i) { + char c = utf8[i]; + switch (c) { + case '\0': + *arguments += "\\0"; + break; + case ',': + *arguments += "\\,"; + break; + case '\\': + *arguments += "\\\\"; + break; + default: + *arguments += c; + break; + } + } + return true; +} + +} + +OfficeIPCThread* OfficeIPCThread::pGlobalOfficeIPCThread = 0; + namespace { struct Security : public rtl::Static<osl::Security, Security> {}; } + +// Turns a string in aMsg such as file:///home/foo/.libreoffice/3 +// Into a hex string of well known length ff132a86... +String CreateMD5FromString( const OUString& aMsg ) +{ +#if (OSL_DEBUG_LEVEL > 2) + fprintf (stderr, "create md5 from '%s'\n", + (const sal_Char *)rtl::OUStringToOString (aMsg, RTL_TEXTENCODING_UTF8)); +#endif + + rtlDigest handle = rtl_digest_create( rtl_Digest_AlgorithmMD5 ); + if ( handle > 0 ) + { + const sal_uInt8* pData = (const sal_uInt8*)aMsg.getStr(); + sal_uInt32 nSize = ( aMsg.getLength() * sizeof( sal_Unicode )); + sal_uInt32 nMD5KeyLen = rtl_digest_queryLength( handle ); + sal_uInt8* pMD5KeyBuffer = new sal_uInt8[ nMD5KeyLen ]; + + rtl_digest_init( handle, pData, nSize ); + rtl_digest_update( handle, pData, nSize ); + rtl_digest_get( handle, pMD5KeyBuffer, nMD5KeyLen ); + rtl_digest_destroy( handle ); + + // Create hex-value string from the MD5 value to keep the string size minimal + OUStringBuffer aBuffer( nMD5KeyLen * 2 + 1 ); + for ( sal_uInt32 i = 0; i < nMD5KeyLen; i++ ) + aBuffer.append( (sal_Int32)pMD5KeyBuffer[i], 16 ); + + delete [] pMD5KeyBuffer; + return aBuffer.makeStringAndClear(); + } + + return String(); +} + +class ProcessEventsClass_Impl +{ +public: + DECL_STATIC_LINK( ProcessEventsClass_Impl, CallEvent, void* pEvent ); + DECL_STATIC_LINK( ProcessEventsClass_Impl, ProcessDocumentsEvent, void* pEvent ); +}; + +IMPL_STATIC_LINK_NOINSTANCE( ProcessEventsClass_Impl, CallEvent, void*, pEvent ) +{ + // Application events are processed by the Desktop::HandleAppEvent implementation. + Desktop::HandleAppEvent( *((ApplicationEvent*)pEvent) ); + delete (ApplicationEvent*)pEvent; + return 0; +} + +IMPL_STATIC_LINK_NOINSTANCE( ProcessEventsClass_Impl, ProcessDocumentsEvent, void*, pEvent ) +{ + // Documents requests are processed by the OfficeIPCThread implementation + ProcessDocumentsRequest* pDocsRequest = (ProcessDocumentsRequest*)pEvent; + + if ( pDocsRequest ) + { + OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest ); + delete pDocsRequest; + } + return 0; +} + +void ImplPostForeignAppEvent( ApplicationEvent* pEvent ) +{ + Application::PostUserEvent( STATIC_LINK( NULL, ProcessEventsClass_Impl, CallEvent ), pEvent ); +} + +void ImplPostProcessDocumentsEvent( ProcessDocumentsRequest* pEvent ) +{ + Application::PostUserEvent( STATIC_LINK( NULL, ProcessEventsClass_Impl, ProcessDocumentsEvent ), pEvent ); +} + +oslSignalAction SAL_CALL SalMainPipeExchangeSignal_impl(void* /*pData*/, oslSignalInfo* pInfo) +{ + if( pInfo->Signal == osl_Signal_Terminate ) + OfficeIPCThread::DisableOfficeIPCThread(); + return osl_Signal_ActCallNextHdl; +} + +// ---------------------------------------------------------------------------- + +// The OfficeIPCThreadController implementation is a bookkeeper for all pending requests +// that were created by the OfficeIPCThread. The requests are waiting to be processed by +// our framework loadComponentFromURL function (e.g. open/print request). +// During shutdown the framework is asking OfficeIPCThreadController about pending requests. +// If there are pending requests framework has to stop the shutdown process. It is waiting +// for these requests because framework is not able to handle shutdown and open a document +// concurrently. + + +// XServiceInfo +OUString SAL_CALL OfficeIPCThreadController::getImplementationName() +throw ( RuntimeException ) +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.OfficeIPCThreadController" )); +} + +sal_Bool SAL_CALL OfficeIPCThreadController::supportsService( const OUString& ) +throw ( RuntimeException ) +{ + return sal_False; +} + +Sequence< OUString > SAL_CALL OfficeIPCThreadController::getSupportedServiceNames() +throw ( RuntimeException ) +{ + Sequence< OUString > aSeq( 0 ); + return aSeq; +} + +// XEventListener +void SAL_CALL OfficeIPCThreadController::disposing( const EventObject& ) +throw( RuntimeException ) +{ +} + +// XTerminateListener +void SAL_CALL OfficeIPCThreadController::queryTermination( const EventObject& ) +throw( TerminationVetoException, RuntimeException ) +{ + // Desktop ask about pending request through our office ipc pipe. We have to + // be sure that no pending request is waiting because framework is not able to + // handle shutdown and open a document concurrently. + + if ( OfficeIPCThread::AreRequestsPending() ) + throw TerminationVetoException(); + else + OfficeIPCThread::SetDowning(); +} + +void SAL_CALL OfficeIPCThreadController::notifyTermination( const EventObject& ) +throw( RuntimeException ) +{ +} + +namespace +{ + class theOfficeIPCThreadMutex + : public rtl::Static<osl::Mutex, theOfficeIPCThreadMutex> {}; +} + +::osl::Mutex& OfficeIPCThread::GetMutex() +{ + return theOfficeIPCThreadMutex::get(); +} + +void OfficeIPCThread::SetDowning() +{ + // We have the order to block all incoming requests. Framework + // wants to shutdown and we have to make sure that no loading/printing + // requests are executed anymore. + ::osl::MutexGuard aGuard( GetMutex() ); + + if ( pGlobalOfficeIPCThread ) + pGlobalOfficeIPCThread->mbDowning = true; +} + +static bool s_bInEnableRequests = false; + +void OfficeIPCThread::EnableRequests( bool i_bEnable ) +{ + // switch between just queueing the requests and executing them + ::osl::MutexGuard aGuard( GetMutex() ); + + if ( pGlobalOfficeIPCThread ) + { + s_bInEnableRequests = true; + pGlobalOfficeIPCThread->mbRequestsEnabled = i_bEnable; + if( i_bEnable ) + { + // hit the compiler over the head + ProcessDocumentsRequest aEmptyReq = ProcessDocumentsRequest( boost::optional< rtl::OUString >() ); + // trigger already queued requests + OfficeIPCThread::ExecuteCmdLineRequests( aEmptyReq ); + } + s_bInEnableRequests = false; + } +} + +sal_Bool OfficeIPCThread::AreRequestsPending() +{ + // Give info about pending requests + ::osl::MutexGuard aGuard( GetMutex() ); + if ( pGlobalOfficeIPCThread ) + return ( pGlobalOfficeIPCThread->mnPendingRequests > 0 ); + else + return sal_False; +} + +void OfficeIPCThread::RequestsCompleted( int nCount ) +{ + // Remove nCount pending requests from our internal counter + ::osl::MutexGuard aGuard( GetMutex() ); + if ( pGlobalOfficeIPCThread ) + { + if ( pGlobalOfficeIPCThread->mnPendingRequests > 0 ) + pGlobalOfficeIPCThread->mnPendingRequests -= nCount; + } +} + +OfficeIPCThread::Status OfficeIPCThread::EnableOfficeIPCThread() +{ + ::osl::MutexGuard aGuard( GetMutex() ); + + if( pGlobalOfficeIPCThread ) + return IPC_STATUS_OK; + + ::rtl::OUString aUserInstallPath; + ::rtl::OUString aDummy; + + OfficeIPCThread* pThread = new OfficeIPCThread; + + pThread->maPipeIdent = OUString( RTL_CONSTASCII_USTRINGPARAM( "SingleOfficeIPC_" ) ); + + // The name of the named pipe is created with the hashcode of the user installation directory (without /user). We have to retrieve + // this information from a unotools implementation. + ::utl::Bootstrap::PathStatus aLocateResult = ::utl::Bootstrap::locateUserInstallation( aUserInstallPath ); + if ( aLocateResult == ::utl::Bootstrap::PATH_EXISTS || aLocateResult == ::utl::Bootstrap::PATH_VALID) + aDummy = aUserInstallPath; + else + { + delete pThread; + return IPC_STATUS_BOOTSTRAP_ERROR; + } + + // Try to determine if we are the first office or not! This should prevent multiple + // access to the user directory ! + // First we try to create our pipe if this fails we try to connect. We have to do this + // in a loop because the the other office can crash or shutdown between createPipe + // and connectPipe!! + + OUString aIniName; + + osl_getExecutableFile( &aIniName.pData ); + + sal_uInt32 lastIndex = aIniName.lastIndexOf('/'); + if ( lastIndex > 0 ) + { + aIniName = aIniName.copy( 0, lastIndex+1 ); + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "perftune" )); +#if defined(WNT) + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( ".ini" )); +#else + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "rc" )); +#endif + } + + ::rtl::Bootstrap aPerfTuneIniFile( aIniName ); + + OUString aDefault( RTL_CONSTASCII_USTRINGPARAM( "0" )); + OUString aPreloadData; + + aPerfTuneIniFile.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "FastPipeCommunication" )), aPreloadData, aDefault ); + + + OUString aUserInstallPathHashCode; + + if ( aPreloadData.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "1" ) )) + { + sal_Char szBuffer[32]; + sprintf( szBuffer, "%d", SUPD ); + aUserInstallPathHashCode = OUString( szBuffer, strlen(szBuffer), osl_getThreadTextEncoding() ); + } + else + aUserInstallPathHashCode = CreateMD5FromString( aDummy ); + + + // Check result to create a hash code from the user install path + if ( aUserInstallPathHashCode.getLength() == 0 ) + return IPC_STATUS_BOOTSTRAP_ERROR; // Something completely broken, we cannot create a valid hash code! + + pThread->maPipeIdent = pThread->maPipeIdent + aUserInstallPathHashCode; + + PipeMode nPipeMode = PIPEMODE_DONTKNOW; + do + { + osl::Security &rSecurity = Security::get(); + // Try to create pipe + if ( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_CREATE, rSecurity )) + { + // Pipe created + nPipeMode = PIPEMODE_CREATED; + } + else if( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_OPEN, rSecurity )) // Creation not successfull, now we try to connect + { + // Pipe connected to first office + nPipeMode = PIPEMODE_CONNECTED; + } + else + { + oslPipeError eReason = pThread->maPipe.getError(); + if ((eReason == osl_Pipe_E_ConnectionRefused) || (eReason == osl_Pipe_E_invalidError)) + return IPC_STATUS_BOOTSTRAP_ERROR; + + // Wait for second office to be ready + TimeValue aTimeValue; + aTimeValue.Seconds = 0; + aTimeValue.Nanosec = 10000000; // 10ms + osl::Thread::wait( aTimeValue ); + } + + } while ( nPipeMode == PIPEMODE_DONTKNOW ); + + if ( nPipeMode == PIPEMODE_CREATED ) + { + // Seems we are the one and only, so start listening thread + pGlobalOfficeIPCThread = pThread; + pThread->create(); // starts thread + } + else + { + // Seems another office is running. Pipe arguments to it and self terminate + osl::StreamPipe aStreamPipe(pThread->maPipe.getHandle()); + + ByteString aArguments(RTL_CONSTASCII_STRINGPARAM(ARGUMENT_PREFIX)); + rtl::OUString cwdUrl; + if (!(tools::getProcessWorkingDir(cwdUrl) && + addArgument(&aArguments, '1', cwdUrl))) + { + aArguments += '0'; + } + sal_uInt32 nCount = rtl_getAppCommandArgCount(); + for( sal_uInt32 i=0; i < nCount; i++ ) + { + rtl_getAppCommandArg( i, &aDummy.pData ); + if (!addArgument(&aArguments, ',', aDummy)) { + return IPC_STATUS_BOOTSTRAP_ERROR; + } + } + // finally, write the string onto the pipe + aStreamPipe.write( aArguments.GetBuffer(), aArguments.Len() ); + aStreamPipe.write( "\0", 1 ); + + ByteString aToken(sc_aConfirmationSequence); + char *aReceiveBuffer = new char[aToken.Len()+1]; + int n = aStreamPipe.read( aReceiveBuffer, aToken.Len() ); + aReceiveBuffer[n]='\0'; + + delete pThread; + if (aToken.CompareTo(aReceiveBuffer)!= COMPARE_EQUAL) { + // something went wrong + delete[] aReceiveBuffer; + return IPC_STATUS_BOOTSTRAP_ERROR; + } else { + delete[] aReceiveBuffer; + return IPC_STATUS_2ND_OFFICE; + } + } + + return IPC_STATUS_OK; +} + +void OfficeIPCThread::DisableOfficeIPCThread() +{ + osl::ClearableMutexGuard aMutex( GetMutex() ); + + if( pGlobalOfficeIPCThread ) + { + OfficeIPCThread *pOfficeIPCThread = pGlobalOfficeIPCThread; + pGlobalOfficeIPCThread = 0; + + // send thread a termination message + // this is done so the subsequent join will not hang + // because the thread hangs in accept of pipe + osl::StreamPipe aPipe ( pOfficeIPCThread->maPipeIdent, osl_Pipe_OPEN, Security::get() ); + if (aPipe.is()) + { + aPipe.send( sc_aTerminationSequence, sc_nTSeqLength+1 ); // also send 0-byte + + // close the pipe so that the streampipe on the other + // side produces EOF + aPipe.close(); + } + + // release mutex to avoid deadlocks + aMutex.clear(); + + OfficeIPCThread::SetReady(pOfficeIPCThread); + + // exit gracefully and join + pOfficeIPCThread->join(); + delete pOfficeIPCThread; + + + } +} + +OfficeIPCThread::OfficeIPCThread() : + mbDowning( false ), + mbRequestsEnabled( false ), + mnPendingRequests( 0 ), + mpDispatchWatcher( 0 ) +{ +} + +OfficeIPCThread::~OfficeIPCThread() +{ + ::osl::ClearableMutexGuard aGuard( GetMutex() ); + + if ( mpDispatchWatcher ) + mpDispatchWatcher->release(); + maPipe.close(); + maStreamPipe.close(); + pGlobalOfficeIPCThread = 0; +} + +static void AddURLToStringList( const rtl::OUString& aURL, rtl::OUString& aStringList ) +{ + if ( aStringList.getLength() ) + aStringList += ::rtl::OUString::valueOf( (sal_Unicode)APPEVENT_PARAM_DELIMITER ); + aStringList += aURL; +} + +void OfficeIPCThread::SetReady(OfficeIPCThread* pThread) +{ + if (pThread == NULL) pThread = pGlobalOfficeIPCThread; + if (pThread != NULL) + { + pThread->cReady.set(); + } +} + +void SAL_CALL OfficeIPCThread::run() +{ + do + { + oslPipeError nError = maPipe.accept( maStreamPipe ); + + + if( nError == osl_Pipe_E_None ) + { + // if we receive a request while the office is displaying some dialog or error during + // bootstrap, that dialogs event loop might get events that are dispatched by this thread + // we have to wait for cReady to be set by the real main loop. + // only reqests that dont dispatch events may be processed before cReady is set. + cReady.wait(); + + // we might have decided to shutdown while we were sleeping + if (!pGlobalOfficeIPCThread) return; + + // only lock the mutex when processing starts, othewise we deadlock when the office goes + // down during wait + osl::ClearableMutexGuard aGuard( GetMutex() ); + + ByteString aArguments; + // test byte by byte + const int nBufSz = 2048; + char pBuf[nBufSz]; + int nBytes = 0; + int nResult = 0; + // read into pBuf until '\0' is read or read-error + while ((nResult=maStreamPipe.recv( pBuf+nBytes, nBufSz-nBytes))>0) { + nBytes += nResult; + if (pBuf[nBytes-1]=='\0') { + aArguments += pBuf; + break; + } + } + // don't close pipe ... + + // Is this a lookup message from another application? if so, ignore + if ( aArguments.Len() == 0 ) + continue; + + // is this a termination message ? if so, terminate + if(( aArguments.CompareTo( sc_aTerminationSequence, sc_nTSeqLength ) == COMPARE_EQUAL ) || + mbDowning ) return; + String aEmpty; + std::auto_ptr< CommandLineArgs > aCmdLineArgs; + try + { + Parser p( aArguments ); + aCmdLineArgs.reset( new CommandLineArgs( p ) ); + } + catch ( CommandLineArgs::Supplier::Exception & ) + { +#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL + fprintf( stderr, "Error in received command line arguments\n" ); +#endif + continue; + } + const CommandLineArgs &rCurrentCmdLineArgs = Desktop::GetCommandLineArgs(); + + if ( aCmdLineArgs->IsQuickstart() ) + { + // we have to use application event, because we have to start quickstart service in main thread!! + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, + "QUICKSTART", aEmpty ); + ImplPostForeignAppEvent( pAppEvent ); + } + + // handle request for acceptor + OUString aAcceptString; + if ( aCmdLineArgs->GetAcceptString(aAcceptString) ) { + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, + "ACCEPT", aAcceptString ); + ImplPostForeignAppEvent( pAppEvent ); + } + // handle acceptor removal + OUString aUnAcceptString; + if ( aCmdLineArgs->GetUnAcceptString(aUnAcceptString) ) { + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, + "UNACCEPT", aUnAcceptString ); + ImplPostForeignAppEvent( pAppEvent ); + } + +#ifndef UNX + // only in non-unix version, we need to handle a -help request + // in a running instance in order to display the command line help + if ( aCmdLineArgs->IsHelp() ) { + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, "HELP", aEmpty ); + ImplPostForeignAppEvent( pAppEvent ); + } +#endif + + sal_Bool bDocRequestSent = sal_False; + ProcessDocumentsRequest* pRequest = new ProcessDocumentsRequest( + aCmdLineArgs->getCwdUrl()); + cProcessed.reset(); + pRequest->pcProcessed = &cProcessed; + + // Print requests are not dependent on the -invisible cmdline argument as they are + // loaded with the "hidden" flag! So they are always checked. + bDocRequestSent |= aCmdLineArgs->GetPrintList( pRequest->aPrintList ); + bDocRequestSent |= ( aCmdLineArgs->GetPrintToList( pRequest->aPrintToList ) && + aCmdLineArgs->GetPrinterName( pRequest->aPrinterName ) ); + + if ( !rCurrentCmdLineArgs.IsInvisible() ) + { + // Read cmdline args that can open/create documents. As they would open a window + // they are only allowed if the "-invisible" is currently not used! + bDocRequestSent |= aCmdLineArgs->GetOpenList( pRequest->aOpenList ); + bDocRequestSent |= aCmdLineArgs->GetViewList( pRequest->aViewList ); + bDocRequestSent |= aCmdLineArgs->GetStartList( pRequest->aStartList ); + bDocRequestSent |= aCmdLineArgs->GetForceOpenList( pRequest->aForceOpenList ); + bDocRequestSent |= aCmdLineArgs->GetForceNewList( pRequest->aForceNewList ); + + // Special command line args to create an empty document for a given module + + // #i18338# (lo) + // we only do this if no document was specified on the command line, + // since this would be inconsistent with the the behaviour of + // the first process, see OpenClients() (call to OpenDefault()) in app.cxx + if ( aCmdLineArgs->HasModuleParam() && (!bDocRequestSent) ) + { + SvtModuleOptions aOpt; + SvtModuleOptions::EFactory eFactory = SvtModuleOptions::E_WRITER; + if ( aCmdLineArgs->IsWriter() ) + eFactory = SvtModuleOptions::E_WRITER; + else if ( aCmdLineArgs->IsCalc() ) + eFactory = SvtModuleOptions::E_CALC; + else if ( aCmdLineArgs->IsDraw() ) + eFactory = SvtModuleOptions::E_DRAW; + else if ( aCmdLineArgs->IsImpress() ) + eFactory = SvtModuleOptions::E_IMPRESS; + else if ( aCmdLineArgs->IsBase() ) + eFactory = SvtModuleOptions::E_DATABASE; + else if ( aCmdLineArgs->IsMath() ) + eFactory = SvtModuleOptions::E_MATH; + else if ( aCmdLineArgs->IsGlobal() ) + eFactory = SvtModuleOptions::E_WRITERGLOBAL; + else if ( aCmdLineArgs->IsWeb() ) + eFactory = SvtModuleOptions::E_WRITERWEB; + + if ( pRequest->aOpenList.getLength() ) + pRequest->aModule = aOpt.GetFactoryName( eFactory ); + else + AddURLToStringList( aOpt.GetFactoryEmptyDocumentURL( eFactory ), pRequest->aOpenList ); + bDocRequestSent = sal_True; + } + } + + if ( !aCmdLineArgs->IsQuickstart() ) { + sal_Bool bShowHelp = sal_False; + rtl::OUStringBuffer aHelpURLBuffer; + if (aCmdLineArgs->IsHelpWriter()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start"); + } else if (aCmdLineArgs->IsHelpCalc()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start"); + } else if (aCmdLineArgs->IsHelpDraw()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start"); + } else if (aCmdLineArgs->IsHelpImpress()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start"); + } else if (aCmdLineArgs->IsHelpBase()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start"); + } else if (aCmdLineArgs->IsHelpBasic()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start"); + } else if (aCmdLineArgs->IsHelpMath()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start"); + } + if (bShowHelp) { + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::LOCALE ); + rtl::OUString aTmp; + aRet >>= aTmp; + aHelpURLBuffer.appendAscii("?Language="); + aHelpURLBuffer.append(aTmp); +#if defined UNX + aHelpURLBuffer.appendAscii("&System=UNX"); +#elif defined WNT + aHelpURLBuffer.appendAscii("&System=WIN"); +#endif + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, + "OPENHELPURL", aHelpURLBuffer.makeStringAndClear()); + ImplPostForeignAppEvent( pAppEvent ); + } + } + + if ( bDocRequestSent ) + { + // Send requests to dispatch watcher if we have at least one. The receiver + // is responsible to delete the request after processing it. + if ( aCmdLineArgs->HasModuleParam() ) + { + SvtModuleOptions aOpt; + + // Support command line parameters to start a module (as preselection) + if ( aCmdLineArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER ); + else if ( aCmdLineArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC ); + else if ( aCmdLineArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS ); + else if ( aCmdLineArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW ); + } + + + ImplPostProcessDocumentsEvent( pRequest ); + } + else + { + // delete not used request again + delete pRequest; + pRequest = NULL; + } + if (( aArguments.CompareTo( sc_aShowSequence, sc_nShSeqLength ) == COMPARE_EQUAL ) || + aCmdLineArgs->IsEmpty() ) + { + // no document was sent, just bring Office to front + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, "APPEAR", aEmpty ); + ImplPostForeignAppEvent( pAppEvent ); + } + + // we don't need the mutex any longer... + aGuard.clear(); + // wait for processing to finish + if (bDocRequestSent) + cProcessed.wait(); + // processing finished, inform the requesting end + nBytes = 0; + while ( + (nResult = maStreamPipe.send(sc_aConfirmationSequence+nBytes, sc_nCSeqLength-nBytes))>0 && + ((nBytes += nResult) < sc_nCSeqLength) ) ; + } + else + { +#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL + fprintf( stderr, "Error on accept: %d\n", (int)nError ); +#endif + TimeValue tval; + tval.Seconds = 1; + tval.Nanosec = 0; + wait( tval ); + } + } while( schedule() ); +} + +static void AddToDispatchList( + DispatchWatcher::DispatchList& rDispatchList, + boost::optional< rtl::OUString > const & cwdUrl, + const OUString& aRequestList, + DispatchWatcher::RequestType nType, + const OUString& aParam, + const OUString& aFactory ) +{ + if ( aRequestList.getLength() > 0 ) + { + sal_Int32 nIndex = 0; + do + { + OUString aToken = aRequestList.getToken( 0, APPEVENT_PARAM_DELIMITER, nIndex ); + if ( aToken.getLength() > 0 ) + rDispatchList.push_back( + DispatchWatcher::DispatchRequest( nType, aToken, cwdUrl, aParam, aFactory )); + } + while ( nIndex >= 0 ); + } +} + +static void AddConversionsToDispatchList( + DispatchWatcher::DispatchList& rDispatchList, + boost::optional< rtl::OUString > const & cwdUrl, + const OUString& rRequestList, + const OUString& rParam, + const OUString& rPrinterName, + const OUString& rFactory, + const OUString& rParamOut ) +{ + DispatchWatcher::RequestType nType; + OUString aParam( rParam ); + + if( rParam.getLength() ) + { + nType = DispatchWatcher::REQUEST_CONVERSION; + aParam = rParam; + } + else + { + nType = DispatchWatcher::REQUEST_BATCHPRINT; + aParam = rPrinterName; + } + + OUString aOutDir( rParamOut.trim() ); + ::rtl::OUString aPWD; + ::tools::getProcessWorkingDir( aPWD ); + + if( !::osl::FileBase::getAbsoluteFileURL( aPWD, rParamOut, aOutDir ) ) + ::osl::FileBase::getSystemPathFromFileURL( aOutDir, aOutDir ); + + if( rParamOut.trim().getLength() ) + { + aParam += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(";")); + aParam += aOutDir; + } + else + { + ::osl::FileBase::getSystemPathFromFileURL( aPWD, aPWD ); + aParam += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ";" )) + aPWD; + } + + if ( rRequestList.getLength() > 0 ) + { + sal_Int32 nIndex = 0; + do + { + OUString aToken = rRequestList.getToken( 0, APPEVENT_PARAM_DELIMITER, nIndex ); + if ( aToken.getLength() > 0 ) + rDispatchList.push_back( + DispatchWatcher::DispatchRequest( nType, aToken, cwdUrl, aParam, rFactory )); + } + while ( nIndex >= 0 ); + } +} + + +sal_Bool OfficeIPCThread::ExecuteCmdLineRequests( ProcessDocumentsRequest& aRequest ) +{ + // protect the dispatch list + osl::ClearableMutexGuard aGuard( GetMutex() ); + + static DispatchWatcher::DispatchList aDispatchList; + + rtl::OUString aEmpty; + // Create dispatch list for dispatch watcher + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aInFilter, DispatchWatcher::REQUEST_INFILTER, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aOpenList, DispatchWatcher::REQUEST_OPEN, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aViewList, DispatchWatcher::REQUEST_VIEW, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aStartList, DispatchWatcher::REQUEST_START, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintList, DispatchWatcher::REQUEST_PRINT, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintToList, DispatchWatcher::REQUEST_PRINTTO, aRequest.aPrinterName, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceOpenList, DispatchWatcher::REQUEST_FORCEOPEN, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceNewList, DispatchWatcher::REQUEST_FORCENEW, aEmpty, aRequest.aModule ); + AddConversionsToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aConversionList, aRequest.aConversionParams, aRequest.aPrinterName, aRequest.aModule, aRequest.aConversionOut ); + sal_Bool bShutdown( sal_False ); + + if ( pGlobalOfficeIPCThread ) + { + if( ! pGlobalOfficeIPCThread->AreRequestsEnabled() ) + return bShutdown; + + pGlobalOfficeIPCThread->mnPendingRequests += aDispatchList.size(); + if ( !pGlobalOfficeIPCThread->mpDispatchWatcher ) + { + pGlobalOfficeIPCThread->mpDispatchWatcher = DispatchWatcher::GetDispatchWatcher(); + pGlobalOfficeIPCThread->mpDispatchWatcher->acquire(); + } + + // copy for execute + DispatchWatcher::DispatchList aTempList( aDispatchList ); + aDispatchList.clear(); + + aGuard.clear(); + + // Execute dispatch requests + bShutdown = pGlobalOfficeIPCThread->mpDispatchWatcher->executeDispatchRequests( aTempList, s_bInEnableRequests ); + + // set processed flag + if (aRequest.pcProcessed != NULL) + aRequest.pcProcessed->set(); + } + + return bShutdown; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/officeipcthread.hxx b/desktop/source/app/officeipcthread.hxx new file mode 100644 index 000000000000..a1fe4c5f772a --- /dev/null +++ b/desktop/source/app/officeipcthread.hxx @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_OFFICEIPCTHREAD_HXX_ +#define _DESKTOP_OFFICEIPCTHREAD_HXX_ + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/frame/XTerminateListener.hpp> +#include <osl/pipe.hxx> +#include <osl/security.hxx> +#include <osl/signal.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/implbase2.hxx> +#include <osl/conditn.hxx> +#include <osl/thread.hxx> +#include "boost/optional.hpp" + +namespace desktop +{ + +oslSignalAction SAL_CALL SalMainPipeExchangeSignal_impl(void* /*pData*/, oslSignalInfo* pInfo); + +// A request for the current office +// that was given by command line or by IPC pipe communication. +struct ProcessDocumentsRequest +{ + ProcessDocumentsRequest(boost::optional< rtl::OUString > const & cwdUrl): + aCwdUrl(cwdUrl), pcProcessed( NULL ) {} + + boost::optional< ::rtl::OUString > aCwdUrl; + ::rtl::OUString aModule; + ::rtl::OUString aOpenList; // Documents that should be opened in the default way + ::rtl::OUString aViewList; // Documents that should be opened in viewmode + ::rtl::OUString aStartList; // Documents/Presentations that should be started + ::rtl::OUString aPrintList; // Documents that should be printed on default printer + ::rtl::OUString aForceOpenList; // Documents that should be forced to open for editing (even templates) + ::rtl::OUString aForceNewList; // Documents that should be forced to create a new document + ::rtl::OUString aPrinterName; // The printer name that should be used for printing + ::rtl::OUString aPrintToList; // Documents that should be printed on the given printer + ::rtl::OUString aConversionList; + ::rtl::OUString aConversionParams; + ::rtl::OUString aConversionOut; + ::rtl::OUString aInFilter; + ::osl::Condition *pcProcessed; // pointer condition to be set when the request has been processed +}; + +class DispatchWatcher; +class OfficeIPCThread : public osl::Thread +{ + private: + static OfficeIPCThread* pGlobalOfficeIPCThread; + + osl::Pipe maPipe; + osl::StreamPipe maStreamPipe; + rtl::OUString maPipeIdent; + bool mbDowning; + bool mbRequestsEnabled; + int mnPendingRequests; + DispatchWatcher* mpDispatchWatcher; + + /* condition to be set when the request has been processed */ + ::osl::Condition cProcessed; + + /* condition to be set when the main event loop is ready + otherwise an error dialogs event loop could eat away + requests from a 2nd office */ + ::osl::Condition cReady; + + static ::osl::Mutex& GetMutex(); + static const char *sc_aTerminationSequence; + static const int sc_nTSeqLength; + static const char *sc_aShowSequence; + static const int sc_nShSeqLength; + static const char *sc_aConfirmationSequence; + static const int sc_nCSeqLength; + + OfficeIPCThread(); + + protected: + /// Working method which should be overridden + virtual void SAL_CALL run(); + + public: + enum Status + { + IPC_STATUS_OK, + IPC_STATUS_2ND_OFFICE, + IPC_STATUS_BOOTSTRAP_ERROR + }; + + virtual ~OfficeIPCThread(); + + // controlling pipe communication during shutdown + static void SetDowning(); + static void EnableRequests( bool i_bEnable = true ); + static sal_Bool AreRequestsPending(); + static void RequestsCompleted( int n = 1 ); + static sal_Bool ExecuteCmdLineRequests( ProcessDocumentsRequest& ); + + // return sal_False if second office + static Status EnableOfficeIPCThread(); + static void DisableOfficeIPCThread(); + // start dispatching events... + static void SetReady(OfficeIPCThread* pThread = NULL); + + bool AreRequestsEnabled() const { return mbRequestsEnabled && ! mbDowning; } +}; + + +class OfficeIPCThreadController : public ::cppu::WeakImplHelper2< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::frame::XTerminateListener > +{ + public: + OfficeIPCThreadController() {} + virtual ~OfficeIPCThreadController() {} + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw ( ::com::sun::star::uno::RuntimeException ); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw( ::com::sun::star::uno::RuntimeException ); + + // XTerminateListener + virtual void SAL_CALL queryTermination( const ::com::sun::star::lang::EventObject& aEvent ) + throw( ::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL notifyTermination( const ::com::sun::star::lang::EventObject& aEvent ) + throw( ::com::sun::star::uno::RuntimeException ); +}; + +} + +#endif // _DESKTOP_OFFICEIPCTHREAD_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/omutexmember.hxx b/desktop/source/app/omutexmember.hxx new file mode 100644 index 000000000000..175eae09fe93 --- /dev/null +++ b/desktop/source/app/omutexmember.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 __FRAMEWORK_OMUTEXMEMBER_HXX_ +#define __FRAMEWORK_OMUTEXMEMBER_HXX_ + +//_________________________________________________________________________________________________________________ +// includes +//_________________________________________________________________________________________________________________ + +#include <osl/mutex.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ +// definitions +//_________________________________________________________________________________________________________________ + +/*-************************************************************************************************************//** + @short definition of a public mutex member + @descr You can use this struct as baseclass to get a public mutex member for right initialization. + Don't use it as member. You can't guarantee the right order of initialization of baseclasses then! + And some other helper classes share the mutex with an implementation and must have a valid one. + + @seealso See implementation of constructors in derived classes for further informations! + + @devstatus ready +*//*-*************************************************************************************************************/ + +struct OMutexMember +{ + ::osl::Mutex m_aMutex; +}; + +#endif // #ifndef __FRAMEWORK_OMUTEXMEMBER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/sofficemain.cxx b/desktop/source/app/sofficemain.cxx new file mode 100644 index 000000000000..1e72fa121423 --- /dev/null +++ b/desktop/source/app/sofficemain.cxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "app.hxx" +#include "cmdlineargs.hxx" +#include "cmdlinehelp.hxx" + +#include <rtl/logfile.hxx> +#include <tools/extendapplicationenvironment.hxx> + +int SVMain(); + +// -=-= main() -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +extern "C" int soffice_main() +{ + tools::extendApplicationEnvironment(); + + RTL_LOGFILE_PRODUCT_TRACE( "PERFORMANCE - enter Main()" ); + + desktop::Desktop aDesktop; + // This string is used during initialization of the Gtk+ VCL module + aDesktop.SetAppName( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("soffice")) ); + aDesktop.CreateProcessServiceFactory(); +#ifdef UNX + // handle --version and --help already here, otherwise they would be handled + // after VCL initialization that might fail if $DISPLAY is not set + const desktop::CommandLineArgs& rCmdLineArgs = aDesktop.GetCommandLineArgs(); + if ( rCmdLineArgs.IsHelp() ) + { + desktop::displayCmdlineHelp(); + return EXIT_SUCCESS; + } + else if ( rCmdLineArgs.IsVersion() ) + { + desktop::displayVersion(); + return EXIT_SUCCESS; + } +#endif + return SVMain(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/sofficemain.h b/desktop/source/app/sofficemain.h new file mode 100755 index 000000000000..539988834a02 --- /dev/null +++ b/desktop/source/app/sofficemain.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_APP_SOFFICEMAIN_H +#define INCLUDED_DESKTOP_SOURCE_APP_SOFFICEMAIN_H + +#include "sal/config.h" + +#if defined __cplusplus +extern "C" { +#endif + +int soffice_main(void); + +#if defined __cplusplus +} +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/userinstall.cxx b/desktop/source/app/userinstall.cxx new file mode 100644 index 000000000000..592821208a34 --- /dev/null +++ b/desktop/source/app/userinstall.cxx @@ -0,0 +1,297 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "userinstall.hxx" +#include "langselect.hxx" + +#include <stdio.h> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/file.hxx> +#include <osl/mutex.hxx> +#include <osl/process.h> +#include <osl/diagnose.h> +#include <osl/security.hxx> +#include <rtl/ref.hxx> + +#include <tools/resmgr.hxx> +#include <unotools/bootstrap.hxx> +#include <svl/languageoptions.hxx> +#include <unotools/syslocaleoptions.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <i18npool/mslangid.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/beans/XHierarchicalPropertySet.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XLocalizable.hpp> +#include <com/sun/star/lang/Locale.hpp> + +#include "app.hxx" + +using rtl::OString; +using rtl::OUString; +using namespace osl; +using namespace utl; +using namespace com::sun::star::container; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; + + +namespace desktop { + + static UserInstall::UserInstallError create_user_install(OUString&); + + static bool is_user_install() + { + try + { + OUString sConfigSrvc( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationProvider" ) ); + OUString sAccessSrvc( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationAccess" ) ); + + // get configuration provider + Reference< XMultiServiceFactory > theMSF + = comphelper::getProcessServiceFactory(); + Reference< XMultiServiceFactory > theConfigProvider + = Reference< XMultiServiceFactory >( + theMSF->createInstance(sConfigSrvc), UNO_QUERY_THROW); + + // localize the provider to user selection + Reference< XLocalizable > localizable(theConfigProvider, UNO_QUERY_THROW); + OUString aUserLanguage = LanguageSelection::getLanguageString(); + Locale aLocale = LanguageSelection::IsoStringToLocale(aUserLanguage); + localizable->setLocale(aLocale); + + Sequence< Any > theArgs(1); + NamedValue v; + v.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("NodePath")); + v.Value = makeAny(OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Setup"))); + theArgs[0] <<= v; + Reference< XHierarchicalNameAccess> hnacc( + theConfigProvider->createInstanceWithArguments( + sAccessSrvc, theArgs), UNO_QUERY_THROW); + + try + { + sal_Bool bValue = sal_False; + hnacc->getByHierarchicalName( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "Office/ooSetupInstCompleted" ) ) ) >>= bValue; + + return bValue ? true : false; + } + catch ( NoSuchElementException const & ) + { + // just return false in this case. + } + } + catch (Exception const & e) + { + OString msg(OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US)); + OSL_FAIL(msg.getStr()); + } + + return false; + } + + UserInstall::UserInstallError UserInstall::finalize() + { + OUString aUserInstallPath; + utl::Bootstrap::PathStatus aLocateResult = + utl::Bootstrap::locateUserInstallation(aUserInstallPath); + + switch (aLocateResult) { + + case utl::Bootstrap::DATA_INVALID: + case utl::Bootstrap::DATA_MISSING: + case utl::Bootstrap::DATA_UNKNOWN: + // cannot find a valid path or path is missing + return E_Unknown; + + case utl::Bootstrap::PATH_EXISTS: + { + // path exists, check if an installation lives there + if ( is_user_install() ) + { + return E_None; + } + // Note: fall-thru intended. + } + case utl::Bootstrap::PATH_VALID: + // found a path but need to create user install + return create_user_install(aUserInstallPath); + default: + return E_Unknown; + } + } + + static osl::FileBase::RC copy_recursive( const rtl::OUString& srcUnqPath, const rtl::OUString& dstUnqPath) + { + + FileBase::RC err; + DirectoryItem aDirItem; + DirectoryItem::get(srcUnqPath, aDirItem); + FileStatus aFileStatus(osl_FileStatus_Mask_All); + aDirItem.getFileStatus(aFileStatus); + + if( aFileStatus.getFileType() == FileStatus::Directory) + { + // create directory if not already there + err = Directory::create( dstUnqPath ); + if (err == osl::FileBase::E_EXIST) + err = osl::FileBase::E_None; + + FileBase::RC next = err; + if (err == osl::FileBase::E_None) + { + // iterate through directory contents + Directory aDir( srcUnqPath ); + aDir.open(); + while (err == osl::FileBase::E_None && + (next = aDir.getNextItem( aDirItem )) == osl::FileBase::E_None) + { + aDirItem.getFileStatus(aFileStatus); + // generate new src/dst pair and make recursive call + rtl::OUString newSrcUnqPath = aFileStatus.getFileURL(); + rtl::OUString newDstUnqPath = dstUnqPath; + rtl::OUString itemname = aFileStatus.getFileName(); + // append trailing '/' if needed + if (newDstUnqPath.lastIndexOf(sal_Unicode('/')) != newDstUnqPath.getLength()-1) + newDstUnqPath += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")); + newDstUnqPath += itemname; + // recursion + err = copy_recursive(newSrcUnqPath, newDstUnqPath); + } + aDir.close(); + + if ( err != osl::FileBase::E_None ) + return err; + if( next != FileBase::E_NOENT ) + err = FileBase::E_INVAL; + } + } + else + { + // copy single file - foldback + err = File::copy( srcUnqPath,dstUnqPath ); + } + return err; + } + + static const char *pszSrcList[] = { + "/presets", + NULL + }; + static const char *pszDstList[] = { + "/user", + NULL + }; + + + static UserInstall::UserInstallError create_user_install(OUString& aUserPath) + { + OUString aBasePath; + if (utl::Bootstrap::locateBaseInstallation(aBasePath) != utl::Bootstrap::PATH_EXISTS) + return UserInstall::E_InvalidBaseinstall; + + // create the user directory + FileBase::RC rc = Directory::createPath(aUserPath); + if ((rc != FileBase::E_None) && (rc != FileBase::E_EXIST)) return UserInstall::E_Creation; + +#ifdef UNIX + // set safer permissions for the user directory by default + File::setAttributes(aUserPath, osl_File_Attribute_OwnWrite| osl_File_Attribute_OwnRead| osl_File_Attribute_OwnExe); +#endif + + // copy data from shared data directory of base installation + for (sal_Int32 i=0; pszSrcList[i]!=NULL && pszDstList[i]!=NULL; i++) + { + rc = copy_recursive( + aBasePath + OUString::createFromAscii(pszSrcList[i]), + aUserPath + OUString::createFromAscii(pszDstList[i])); + if ((rc != FileBase::E_None) && (rc != FileBase::E_EXIST)) + { + if ( rc == FileBase::E_NOSPC ) + return UserInstall::E_NoDiskSpace; + else if ( rc == FileBase::E_ACCES ) + return UserInstall::E_NoWriteAccess; + else + return UserInstall::E_Creation; + } + } + try + { + OUString sConfigSrvc(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")); + OUString sAccessSrvc(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationUpdateAccess")); + + // get configuration provider + Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory(); + Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >( + theMSF->createInstance(sConfigSrvc), UNO_QUERY_THROW); + Sequence< Any > theArgs(1); + NamedValue v(OUString(RTL_CONSTASCII_USTRINGPARAM("NodePath")), makeAny(OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Setup")))); + theArgs[0] <<= v; + Reference< XHierarchicalPropertySet> hpset( + theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW); + hpset->setHierarchicalPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Office/ooSetupInstCompleted")), makeAny(sal_True)); + Reference< XChangesBatch >(hpset, UNO_QUERY_THROW)->commitChanges(); + } + catch ( PropertyVetoException& ) + { + // we are not allowed to change this + } + catch (Exception& e) + { + OString aMsg("create_user_install(): "); + aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(aMsg.getStr()); + return UserInstall::E_Creation; + } + + return UserInstall::E_None; + + } +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/userinstall.hxx b/desktop/source/app/userinstall.hxx new file mode 100644 index 000000000000..6dcb5e91db41 --- /dev/null +++ b/desktop/source/app/userinstall.hxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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/types.h> +#include <rtl/ustring.hxx> + +namespace desktop +{ + +class UserInstall +{ +public: + enum UserInstallError { + E_None, // no error + E_Creation, // error while creating user install + E_InvalidBaseinstall, // corrupt base installation + E_SetupFailed, // external setup did not run correctly + E_Configuration, // error while accessing configuration + E_License, // License not accepted + E_NoDiskSpace, // not enough disk space + E_NoWriteAccess, // no write access + E_Unknown // unknown error + }; + + static UserInstallError finalize(); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/version.map b/desktop/source/app/version.map new file mode 100755 index 000000000000..0ffffcd58635 --- /dev/null +++ b/desktop/source/app/version.map @@ -0,0 +1,34 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +UDK_3_0_0 { + global: + soffice_main; + + local: + *; +}; diff --git a/desktop/source/deployment/deployment.component b/desktop/source/deployment/deployment.component new file mode 100755 index 000000000000..11385c7aa8d9 --- /dev/null +++ b/desktop/source/deployment/deployment.component @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.deployment.ExtensionManager"> + <service name="com.sun.star.comp.deployment.ExtensionManager"/> + <singleton name="com.sun.star.deployment.ExtensionManager"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.PackageInformationProvider"> + <service name="com.sun.star.comp.deployment.PackageInformationProvider"/> + <singleton name="com.sun.star.deployment.PackageInformationProvider"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.PackageManagerFactory"> + <service name="com.sun.star.comp.deployment.PackageManagerFactory"/> + <singleton name="com.sun.star.deployment.thePackageManagerFactory"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.ProgressLog"> + <service name="com.sun.star.comp.deployment.ProgressLog"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.component.PackageRegistryBackend"> + <service name="com.sun.star.deployment.PackageRegistryBackend"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.configuration.PackageRegistryBackend"> + <service name="com.sun.star.deployment.PackageRegistryBackend"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.executable.PackageRegistryBackend"> + <service name="com.sun.star.deployment.PackageRegistryBackend"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.help.PackageRegistryBackend"> + <service name="com.sun.star.deployment.PackageRegistryBackend"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.script.PackageRegistryBackend"> + <service name="com.sun.star.deployment.PackageRegistryBackend"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.sfwk.PackageRegistryBackend"> + <service name="com.sun.star.deployment.PackageRegistryBackend"/> + </implementation> +</component> diff --git a/desktop/source/deployment/dp_log.cxx b/desktop/source/deployment/dp_log.cxx new file mode 100644 index 000000000000..24a8b7b40c0d --- /dev/null +++ b/desktop/source/deployment/dp_log.cxx @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_misc.h" +#include "rtl/strbuf.hxx" +#include "osl/time.h" +#include "osl/thread.h" +#include "cppuhelper/compbase1.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/unwrapargs.hxx" +#include "com/sun/star/deployment/DeploymentException.hpp" +#include "com/sun/star/ucb/XProgressHandler.hpp" +#include "com/sun/star/ucb/XSimpleFileAccess.hpp" +#include "com/sun/star/io/XSeekable.hpp" +#include <stdio.h> + + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace dp_log { + +typedef ::cppu::WeakComponentImplHelper1<ucb::XProgressHandler> t_log_helper; + +//============================================================================== +class ProgressLogImpl : public ::dp_misc::MutexHolder, public t_log_helper +{ + Reference<io::XOutputStream> m_xLogFile; + sal_Int32 m_log_level; + void log_write( OString const & text ); + +protected: + virtual void SAL_CALL disposing(); + virtual ~ProgressLogImpl(); + +public: + ProgressLogImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xContext ); + + // 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); +}; + +//______________________________________________________________________________ +ProgressLogImpl::~ProgressLogImpl() +{ +} + +//______________________________________________________________________________ +void ProgressLogImpl::disposing() +{ + try { + if (m_xLogFile.is()) { + m_xLogFile->closeOutput(); + m_xLogFile.clear(); + } + } + catch (Exception & exc) { + (void) exc; + OSL_FAIL( OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } +} + +//______________________________________________________________________________ +ProgressLogImpl::ProgressLogImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xContext ) + : t_log_helper( getMutex() ), + m_log_level( 0 ) +{ + OUString log_file; + boost::optional< Reference<task::XInteractionHandler> > interactionHandler; + comphelper::unwrapArgs( args, log_file, interactionHandler ); + + Reference<ucb::XSimpleFileAccess> xSimpleFileAccess( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.ucb.SimpleFileAccess"), + xContext ), UNO_QUERY_THROW ); + // optional ia handler: + if (interactionHandler) + xSimpleFileAccess->setInteractionHandler( *interactionHandler ); + + m_xLogFile.set( + xSimpleFileAccess->openFileWrite( log_file ), UNO_QUERY_THROW ); + Reference<io::XSeekable> xSeekable( m_xLogFile, UNO_QUERY_THROW ); + xSeekable->seek( xSeekable->getLength() ); + + // write log stamp + OStringBuffer buf; + buf.append( + RTL_CONSTASCII_STRINGPARAM("###### Progress log entry ") ); + TimeValue m_start_time, tLocal; + oslDateTime date_time; + if (osl_getSystemTime( &m_start_time ) && + osl_getLocalTimeFromSystemTime( &m_start_time, &tLocal ) && + osl_getDateTimeFromTimeValue( &tLocal, &date_time )) + { + char ar[ 128 ]; + snprintf( + ar, sizeof (ar), + "%04d-%02d-%02d %02d:%02d:%02d ", + date_time.Year, date_time.Month, date_time.Day, + date_time.Hours, date_time.Minutes, date_time.Seconds ); + buf.append( ar ); + } + buf.append( RTL_CONSTASCII_STRINGPARAM("######\n") ); + log_write( buf.makeStringAndClear() ); +} + +//______________________________________________________________________________ +void ProgressLogImpl::log_write( OString const & text ) +{ + try { + if (m_xLogFile.is()) { + m_xLogFile->writeBytes( + Sequence< sal_Int8 >( + reinterpret_cast< sal_Int8 const * >(text.getStr()), + text.getLength() ) ); + } + } + catch (io::IOException & exc) { + (void) exc; + OSL_FAIL( OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } +} + +// XProgressHandler +//______________________________________________________________________________ +void ProgressLogImpl::push( Any const & Status ) + throw (RuntimeException) +{ + update( Status ); + OSL_ASSERT( m_log_level >= 0 ); + ++m_log_level; +} + +//______________________________________________________________________________ +void ProgressLogImpl::update( Any const & Status ) + throw (RuntimeException) +{ + if (! Status.hasValue()) + return; + + OUStringBuffer buf; + OSL_ASSERT( m_log_level >= 0 ); + for ( sal_Int32 n = 0; n < m_log_level; ++n ) + buf.append( static_cast<sal_Unicode>(' ') ); + + OUString msg; + if (Status >>= msg) { + buf.append( msg ); + } + else { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("ERROR: ") ); + buf.append( ::comphelper::anyToString(Status) ); + } + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\n") ); + log_write( OUStringToOString( + buf.makeStringAndClear(), osl_getThreadTextEncoding() ) ); +} + +//______________________________________________________________________________ +void ProgressLogImpl::pop() throw (RuntimeException) +{ + OSL_ASSERT( m_log_level > 0 ); + --m_log_level; +} + +namespace sdecl = comphelper::service_decl; +sdecl::class_<ProgressLogImpl, sdecl::with_args<true> > servicePLI; +extern sdecl::ServiceDecl const serviceDecl( + servicePLI, + // a private one: + "com.sun.star.comp.deployment.ProgressLog", + "com.sun.star.comp.deployment.ProgressLog" ); + +} // namespace dp_log + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/dp_persmap.cxx b/desktop/source/deployment/dp_persmap.cxx new file mode 100644 index 000000000000..92e4080063f9 --- /dev/null +++ b/desktop/source/deployment/dp_persmap.cxx @@ -0,0 +1,254 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_misc.h" +#include "dp_ucb.h" +#include "dp_persmap.h" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" +#include "osl/file.hxx" +#include "osl/thread.h" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::rtl; +using ::osl::File; + +namespace dp_misc +{ + +//______________________________________________________________________________ +void PersistentMap::throw_rtexc( int err, char const * pmsg ) const +{ + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[") ); + buf.append( m_sysPath ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] Berkeley Db error (") ); + buf.append( static_cast<sal_Int32>(err) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("): ") ); + if (pmsg == 0) + pmsg = DbEnv::strerror(err); + const OString msg(pmsg); + buf.append( OUString( msg.getStr(), msg.getLength(), + osl_getThreadTextEncoding() ) ); + const OUString msg_(buf.makeStringAndClear()); + OSL_FAIL( rtl::OUStringToOString( + msg_, RTL_TEXTENCODING_UTF8 ).getStr() ); + throw RuntimeException( msg_, Reference<XInterface>() ); +} + +//______________________________________________________________________________ +PersistentMap::~PersistentMap() +{ + try { + m_db.close(0); + } + catch (DbException & exc) { + (void) exc; // avoid warnings + OSL_FAIL( DbEnv::strerror( exc.get_errno() ) ); + } +} + +//______________________________________________________________________________ +PersistentMap::PersistentMap( OUString const & url_, bool readOnly ) + : m_db( 0, 0 ) +{ + try { + OUString url( expandUnoRcUrl(url_) ); + if ( File::getSystemPathFromFileURL( url, m_sysPath ) != File::E_None ) + { + OSL_ASSERT( false ); + } + OString cstr_sysPath( + OUStringToOString( m_sysPath, RTL_TEXTENCODING_UTF8 ) ); + char const * pcstr_sysPath = cstr_sysPath.getStr(); + + u_int32_t flags = DB_CREATE; + if (readOnly) { + flags = DB_RDONLY; + if (! create_ucb_content( + 0, url, + Reference<com::sun::star::ucb::XCommandEnvironment>(), + false /* no throw */ )) { + // ignore non-existent file in read-only mode: simulate empty db + pcstr_sysPath = 0; + flags = DB_CREATE; + } + } + + int err = m_db.open( + // xxx todo: DB_THREAD, DB_DBT_MALLOC currently not used + 0, pcstr_sysPath, 0, DB_HASH, flags/* | DB_THREAD*/, 0664 /* fs mode */ ); + if (err != 0) + throw_rtexc(err); + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } +} + +//______________________________________________________________________________ +PersistentMap::PersistentMap() + : m_db( 0, 0 ) +{ + try { + // xxx todo: DB_THREAD, DB_DBT_MALLOC currently not used + int err = m_db.open( 0, 0, 0, DB_HASH, DB_CREATE/* | DB_THREAD*/, 0 ); + if (err != 0) + throw_rtexc(err); + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } +} + +//______________________________________________________________________________ +bool PersistentMap::has( OString const & key ) const +{ + return get( 0, key ); +} + +//______________________________________________________________________________ +bool PersistentMap::get( OString * value, OString const & key ) const +{ + try { + Dbt dbKey( const_cast< sal_Char * >(key.getStr()), key.getLength() ); + Dbt dbData; + int err = m_db.get( 0, &dbKey, &dbData, 0 ); + if (err == DB_NOTFOUND) + return false; + if (err == 0) { + if (value != 0) { + *value = OString( + static_cast< sal_Char const * >(dbData.get_data()), + dbData.get_size() ); + } + return true; + } + throw_rtexc(err); + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } + return false; // avoiding warning +} + +//______________________________________________________________________________ +void PersistentMap::put( OString const & key, OString const & value ) +{ + try { + Dbt dbKey( const_cast< sal_Char * >(key.getStr()), key.getLength() ); + Dbt dbData( const_cast< sal_Char * >( + value.getStr()), value.getLength() ); + int err = m_db.put( 0, &dbKey, &dbData, 0 ); + if (err == 0) { +#if OSL_DEBUG_LEVEL > 0 + OString v; + OSL_ASSERT( get( &v, key ) ); + OSL_ASSERT( v.equals( value ) ); +#endif + err = m_db.sync(0); + } + if (err != 0) + throw_rtexc(err); + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } +} + +//______________________________________________________________________________ +bool PersistentMap::erase( OString const & key, bool flush_immediately ) +{ + try { + Dbt dbKey( const_cast< sal_Char * >(key.getStr()), key.getLength() ); + int err = m_db.del( &dbKey, 0 ); + if (err == 0) { + if (flush_immediately) { + err = m_db.sync(0); + if (err != 0) + throw_rtexc(err); + } + return true; + } + if (err == DB_NOTFOUND) + return false; + throw_rtexc(err); + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } + return false; // avoiding warning +} + +//______________________________________________________________________________ +t_string2string_map PersistentMap::getEntries() const +{ + try { + Dbc * pcurs = 0; + int err = m_db.cursor( 0, &pcurs, 0 ); + if (err != 0) + throw_rtexc(err); + + t_string2string_map ret; + for (;;) { + Dbt dbKey, dbData; + err = pcurs->get( &dbKey, &dbData, DB_NEXT ); + if (err == DB_NOTFOUND) + break; + if (err != 0) + throw_rtexc(err); + +#if OSL_DEBUG_LEVEL > 0 + ::std::pair<t_string2string_map::iterator, bool> insertion = +#endif + ret.insert( + t_string2string_map::value_type( + OString( static_cast<sal_Char const*>(dbKey.get_data()), dbKey.get_size() ), + OString( static_cast<sal_Char const*>(dbData.get_data()), dbData.get_size() ) + ) ); + OSL_ASSERT( insertion.second ); + } + err = pcurs->close(); + if (err != 0) + throw_rtexc(err); + return ret; + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } + return t_string2string_map(); // avoiding warning +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/dp_services.cxx b/desktop/source/deployment/dp_services.cxx new file mode 100644 index 000000000000..7a93e5b42df3 --- /dev/null +++ b/desktop/source/deployment/dp_services.cxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" + +#define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 12 +#include "comphelper/servicedecl.hxx" + +using namespace com::sun::star; +namespace sdecl = comphelper::service_decl; + +namespace dp_registry { +namespace backend { + +namespace configuration { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace component { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace script { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace sfwk { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace help { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace executable { +extern sdecl::ServiceDecl const serviceDecl; +} + +} // namespace backend +} // namespace dp_registry + +namespace dp_manager { +namespace factory { +extern sdecl::ServiceDecl const serviceDecl; +bool singleton_entries( uno::Reference<registry::XRegistryKey> const& ); +} +extern sdecl::ServiceDecl const serviceDecl; +bool singleton_entries( uno::Reference<registry::XRegistryKey> const& ); +} + +namespace dp_log { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace dp_info { +extern sdecl::ServiceDecl const serviceDecl; +bool singleton_entries( uno::Reference<registry::XRegistryKey> const& ); +} + +extern "C" { + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + sal_Char const * pImplName, + lang::XMultiServiceFactory * pServiceManager, + registry::XRegistryKey * pRegistryKey ) +{ + return component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, + dp_registry::backend::configuration::serviceDecl, + dp_registry::backend::component::serviceDecl, + dp_registry::backend::help::serviceDecl, + dp_registry::backend::script::serviceDecl, + dp_registry::backend::sfwk::serviceDecl, + dp_registry::backend::executable::serviceDecl, + dp_manager::factory::serviceDecl, + dp_log::serviceDecl, + dp_info::serviceDecl, + dp_manager::serviceDecl); +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/dp_xml.cxx b/desktop/source/deployment/dp_xml.cxx new file mode 100644 index 000000000000..b46d9835548c --- /dev/null +++ b/desktop/source/deployment/dp_xml.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_misc.h" +#include "dp_xml.h" +#include "rtl/ustrbuf.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/xml/sax/XParser.hpp" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace dp_misc +{ + +//============================================================================== +void xml_parse( + Reference<xml::sax::XDocumentHandler> const & xDocHandler, + ::ucbhelper::Content & ucb_content, + Reference<XComponentContext> const & xContext ) +{ + // raise sax parser: + Reference<xml::sax::XParser> xParser( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.sax.Parser"), xContext ), UNO_QUERY_THROW ); + + // error handler, entity resolver omitted + xParser->setDocumentHandler( xDocHandler ); + xml::sax::InputSource source; + source.aInputStream = ucb_content.openStream(); + source.sSystemId = ucb_content.getURL(); + xParser->parseStream( source ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/deploymentgui.component b/desktop/source/deployment/gui/deploymentgui.component new file mode 100755 index 000000000000..d613f482e791 --- /dev/null +++ b/desktop/source/deployment/gui/deploymentgui.component @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.deployment.ui.LicenseDialog"> + <service name="com.sun.star.deployment.ui.LicenseDialog"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.ui.PackageManagerDialog"> + <service name="com.sun.star.deployment.ui.PackageManagerDialog"/> + </implementation> + <implementation name="com.sun.star.comp.deployment.ui.UpdateRequiredDialog"> + <service name="com.sun.star.deployment.ui.UpdateRequiredDialog"/> + </implementation> +</component> diff --git a/desktop/source/deployment/gui/descedit.cxx b/desktop/source/deployment/gui/descedit.cxx new file mode 100644 index 000000000000..1faaa9f9bae4 --- /dev/null +++ b/desktop/source/deployment/gui/descedit.cxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <vcl/scrbar.hxx> +#include <svtools/txtattr.hxx> +#include <svtools/xtextedt.hxx> + +#include "descedit.hxx" + +#include "dp_gui.hrc" + +using dp_gui::DescriptionEdit; + +// DescriptionEdit ------------------------------------------------------- + +DescriptionEdit::DescriptionEdit( Window* pParent, const ResId& rResId ) : + + ExtMultiLineEdit( pParent, rResId ), + + m_bIsVerticalScrollBarHidden( true ) + +{ + Init(); +} + +// ----------------------------------------------------------------------- + +void DescriptionEdit::Init() +{ + Clear(); + // no tabstop + SetStyle( ( GetStyle() & ~WB_TABSTOP ) | WB_NOTABSTOP ); + // read-only + SetReadOnly(); + // no cursor + EnableCursor( sal_False ); +} + +// ----------------------------------------------------------------------- + +void DescriptionEdit::UpdateScrollBar() +{ + if ( m_bIsVerticalScrollBarHidden ) + { + ScrollBar* pVScrBar = GetVScrollBar(); + if ( pVScrBar && pVScrBar->GetVisibleSize() < pVScrBar->GetRangeMax() ) + { + pVScrBar->Show(); + m_bIsVerticalScrollBarHidden = false; + } + } +} + +// ----------------------------------------------------------------------- + +void DescriptionEdit::Clear() +{ + SetText( String() ); + + m_bIsVerticalScrollBarHidden = true; + ScrollBar* pVScrBar = GetVScrollBar(); + if ( pVScrBar ) + pVScrBar->Hide(); +} + +// ----------------------------------------------------------------------- + +void DescriptionEdit::SetDescription( const String& rDescription ) +{ + SetText( rDescription ); + UpdateScrollBar(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/descedit.hxx b/desktop/source/deployment/gui/descedit.hxx new file mode 100644 index 000000000000..ed8b8f9c333f --- /dev/null +++ b/desktop/source/deployment/gui/descedit.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_GUI_DP_GUI_DESCEDIT_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_DESCEDIT_HXX + +#include "svtools/svmedit2.hxx" + +/// @HTML + +namespace dp_gui +{ + + class DescriptionEdit : public ExtMultiLineEdit + { + private: + bool m_bIsVerticalScrollBarHidden; + + void Init(); + void UpdateScrollBar(); + + public: + DescriptionEdit( Window* pParent, const ResId& rResId ); + inline ~DescriptionEdit() {} + + void Clear(); + void SetDescription( const String& rDescription ); + }; + +} // namespace dp_gui + +#endif // INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_DESCEDIT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui.h b/desktop/source/deployment/gui/dp_gui.h new file mode 100755 index 000000000000..1c57aa5b800e --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui.h @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_GUI_H +#define INCLUDED_DP_GUI_H + +#include "dp_gui_updatedata.hxx" +#include "dp_misc.h" +#include "dp_gui.hrc" +#include "rtl/ref.hxx" +#include "rtl/instance.hxx" +#include "osl/thread.hxx" +#include "cppuhelper/implbase2.hxx" +#include "vcl/svapp.hxx" +#include "vcl/dialog.hxx" +#include "vcl/button.hxx" +#include "vcl/fixed.hxx" +#include "salhelper/simplereferenceobject.hxx" +#include "svtools/svtabbx.hxx" +#include "svtools/headbar.hxx" +#include "com/sun/star/ucb/XContentEventListener.hpp" +#include "osl/mutex.hxx" +#include <list> +#include <memory> +#include <queue> + +namespace com { namespace sun { namespace star { + namespace container { + class XNameAccess; + } + namespace frame { + class XDesktop; + } + namespace awt { + class XWindow; + } + namespace uno { + class XComponentContext; + } + namespace deployment { + class XPackageManagerFactory; + } +} } } + +namespace svt { + class FixedHyperlink; +} + +namespace dp_gui { + +enum PackageState { REGISTERED, NOT_REGISTERED, AMBIGUOUS, NOT_AVAILABLE }; + +//============================================================================== + +class SelectedPackage: public salhelper::SimpleReferenceObject { +public: + SelectedPackage() {} + SelectedPackage( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> &xPackage) + : m_xPackage( xPackage ) + {} + + virtual ~SelectedPackage(); + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> getPackage() const { return m_xPackage; } + +private: + SelectedPackage(SelectedPackage &); // not defined + void operator =(SelectedPackage &); // not defined + + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> m_xPackage; +}; + +} // namespace dp_gui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui.hrc b/desktop/source/deployment/gui/dp_gui.hrc new file mode 100755 index 000000000000..492405164aa2 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui.hrc @@ -0,0 +1,181 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_GUI_HRC +#define INCLUDED_DP_GUI_HRC + +#include "deployment.hrc" +#include "helpid.hrc" + +// Package Manager Dialog: +#define RID_DLG_EXTENSION_MANAGER RID_DEPLOYMENT_GUI_START +#define RID_DLG_UPDATE_REQUIRED (RID_DEPLOYMENT_GUI_START + 11) + +#define RID_EM_BTN_CLOSE 10 +#define RID_EM_BTN_HELP 11 +#define RID_EM_BTN_ADD 12 +#define RID_EM_BTN_CHECK_UPDATES 13 +#define RID_EM_BTN_OPTIONS 14 +#define RID_EM_BTN_CANCEL 15 +#define RID_EM_FT_GET_EXTENSIONS 20 +#define RID_EM_FT_PROGRESS 21 +#define RID_EM_FT_MSG 22 + +// local RIDs: +#define PB_LICENSE_DOWN 50 +#define ML_LICENSE 51 +#define BTN_LICENSE_DECLINE 53 +#define FT_LICENSE_HEADER 54 +#define FT_LICENSE_BODY_1 55 +#define FT_LICENSE_BODY_1_TXT 56 +#define FT_LICENSE_BODY_2 57 +#define FT_LICENSE_BODY_2_TXT 58 +#define FL_LICENSE 69 +#define FI_LICENSE_ARROW1 60 +#define FI_LICENSE_ARROW2 61 +#define BTN_LICENSE_ACCEPT 63 + +// local RIDs for "Download and Install" dialog + +#define RID_DLG_UPDATE_INSTALL_ABORT 2 +#define RID_DLG_UPDATE_INSTALL_OK 3 +#define RID_DLG_UPDATE_INSTALL_DOWNLOADING 4 +#define RID_DLG_UPDATE_INSTALL_INSTALLING 5 +#define RID_DLG_UPDATE_INSTALL_FINISHED 6 +#define RID_DLG_UPDATE_INSTALL_LINE 7 +#define RID_DLG_UPDATE_INSTALL_HELP 8 +#define RID_DLG_UPDATE_INSTALL_STATUSBAR 9 +#define RID_DLG_UPDATE_INSTALL_EXTENSION_NAME 10 +#define RID_DLG_UPDATE_INSTALL_RESULTS 11 +#define RID_DLG_UPDATE_INSTALL_INFO 12 +#define RID_DLG_UPDATE_INSTALL_NO_ERRORS 13 +#define RID_DLG_UPDATE_INSTALL_THIS_ERROR_OCCURRED 14 +#define RID_DLG_UPDATE_INSTALL_ERROR_DOWNLOAD 15 +#define RID_DLG_UPDATE_INSTALL_ERROR_INSTALLATION 16 +#define RID_DLG_UPDATE_INSTALL_ERROR_LIC_DECLINED 17 +#define RID_DLG_UPDATE_INSTALL_EXTENSION_NOINSTALL 18 + +#define RID_DLG_DEPENDENCIES (RID_DEPLOYMENT_GUI_START + 1) +#define RID_DLG_DEPENDENCIES_TEXT 1 +#define RID_DLG_DEPENDENCIES_LIST 2 +#define RID_DLG_DEPENDENCIES_OK 3 + +#define RID_QUERYBOX_INSTALL_FOR_ALL (RID_DEPLOYMENT_GUI_START + 2) +#define RID_WARNINGBOX_VERSION_LESS (RID_DEPLOYMENT_GUI_START + 3) +#define RID_STR_WARNINGBOX_VERSION_LESS_DIFFERENT_NAMES (RID_DEPLOYMENT_GUI_START + 4) +#define RID_WARNINGBOX_VERSION_EQUAL (RID_DEPLOYMENT_GUI_START + 5) +#define RID_STR_WARNINGBOX_VERSION_EQUAL_DIFFERENT_NAMES (RID_DEPLOYMENT_GUI_START + 6) +#define RID_WARNINGBOX_VERSION_GREATER (RID_DEPLOYMENT_GUI_START + 7) +#define RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES (RID_DEPLOYMENT_GUI_START + 8) +#define RID_WARNINGBOX_INSTALL_EXTENSION (RID_DEPLOYMENT_GUI_START + 9) + +#define RID_DLG_UPDATE (RID_DEPLOYMENT_GUI_START + 10) + +#define RID_DLG_UPDATE_CHECKING 1 +#define RID_DLG_UPDATE_THROBBER 2 +#define RID_DLG_UPDATE_UPDATE 3 +#define RID_DLG_UPDATE_UPDATES 4 +#define RID_DLG_UPDATE_ALL 5 +#define RID_DLG_UPDATE_DESCRIPTION 6 +#define RID_DLG_UPDATE_DESCRIPTIONS 7 +#define RID_DLG_UPDATE_LINE 8 +#define RID_DLG_UPDATE_HELP 9 +#define RID_DLG_UPDATE_OK 10 +#define RID_DLG_UPDATE_CLOSE 11 +#define RID_DLG_UPDATE_NORMALALERT 12 +#define RID_DLG_UPDATE_ERROR 14 +#define RID_DLG_UPDATE_NONE 15 +#define RID_DLG_UPDATE_NOINSTALLABLE 16 +#define RID_DLG_UPDATE_FAILURE 17 +#define RID_DLG_UPDATE_UNKNOWNERROR 18 +#define RID_DLG_UPDATE_NODESCRIPTION 19 +#define RID_DLG_UPDATE_NOINSTALL 20 +#define RID_DLG_UPDATE_NODEPENDENCY 21 +#define RID_DLG_UPDATE_NODEPENDENCY_CUR_VER 22 +#define RID_DLG_UPDATE_NOPERMISSION 23 +#define RID_DLG_UPDATE_NOPERMISSION_VISTA 24 +#define RID_DLG_UPDATE_BROWSERBASED 25 +#define RID_DLG_UPDATE_PUBLISHER_LABEL 26 +#define RID_DLG_UPDATE_PUBLISHER_LINK 27 +#define RID_DLG_UPDATE_RELEASENOTES_LABEL 28 +#define RID_DLG_UPDATE_RELEASENOTES_LINK 29 +#define RID_DLG_UPDATE_NOUPDATE 30 +#define RID_DLG_UPDATE_VERSION 31 +#define RID_DLG_UPDATE_IGNORE 32 +#define RID_DLG_UPDATE_ENABLE 33 +#define RID_DLG_UPDATE_IGNORE_ALL 34 +#define RID_DLG_UPDATE_IGNORED_UPDATE 35 + + + +#define RID_DLG_UPDATEINSTALL (RID_DEPLOYMENT_GUI_START + 20) +#define RID_INFOBOX_UPDATE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START + 21) + +#define RID_IMG_WARNING (RID_DEPLOYMENT_GUI_START+56) +#define RID_IMG_LOCKED (RID_DEPLOYMENT_GUI_START+58) +#define RID_IMG_EXTENSION (RID_DEPLOYMENT_GUI_START+60) +#define RID_IMG_SHARED (RID_DEPLOYMENT_GUI_START+62) + +#define RID_STR_ADD_PACKAGES (RID_DEPLOYMENT_GUI_START+70) + +#define RID_CTX_ITEM_REMOVE (RID_DEPLOYMENT_GUI_START+80) +#define RID_CTX_ITEM_ENABLE (RID_DEPLOYMENT_GUI_START+81) +#define RID_CTX_ITEM_DISABLE (RID_DEPLOYMENT_GUI_START+82) +#define RID_CTX_ITEM_CHECK_UPDATE (RID_DEPLOYMENT_GUI_START+83) +#define RID_CTX_ITEM_OPTIONS (RID_DEPLOYMENT_GUI_START+84) + +#define RID_STR_ADDING_PACKAGES (RID_DEPLOYMENT_GUI_START+85) +#define RID_STR_REMOVING_PACKAGES (RID_DEPLOYMENT_GUI_START+86) +#define RID_STR_ENABLING_PACKAGES (RID_DEPLOYMENT_GUI_START+87) +#define RID_STR_DISABLING_PACKAGES (RID_DEPLOYMENT_GUI_START+88) +#define RID_STR_ACCEPT_LICENSE (RID_DEPLOYMENT_GUI_START+89) + +#define RID_STR_INSTALL_FOR_ALL (RID_DEPLOYMENT_GUI_START+90) +#define RID_STR_INSTALL_FOR_ME (RID_DEPLOYMENT_GUI_START+91) +#define RID_STR_ERROR_UNKNOWN_STATUS (RID_DEPLOYMENT_GUI_START+92) +#define RID_STR_CLOSE_BTN (RID_DEPLOYMENT_GUI_START+93) +#define RID_STR_EXIT_BTN (RID_DEPLOYMENT_GUI_START+94) +#define RID_STR_NO_ADMIN_PRIVILEGE (RID_DEPLOYMENT_GUI_START+95) +#define RID_STR_ERROR_MISSING_DEPENDENCIES (RID_DEPLOYMENT_GUI_START+96) +#define RID_STR_ERROR_MISSING_LICENSE (RID_DEPLOYMENT_GUI_START+97) +#define RID_STR_SHOW_LICENSE_CMD (RID_DEPLOYMENT_GUI_START+98) + +#define WARNINGBOX_CONCURRENTINSTANCE (RID_DEPLOYMENT_GUI_START+100) + +#define RID_STR_UNSUPPORTED_PLATFORM (RID_DEPLOYMENT_GUI_START+101) +#define RID_WARNINGBOX_UPDATE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START+102) +#define RID_WARNINGBOX_REMOVE_EXTENSION (RID_DEPLOYMENT_GUI_START+103) +#define RID_WARNINGBOX_REMOVE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START+104) +#define RID_WARNINGBOX_ENABLE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START+105) +#define RID_WARNINGBOX_DISABLE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START+106) +#define RID_DLG_SHOW_LICENSE (RID_DEPLOYMENT_GUI_START+107) + +#define RID_DLG_LICENSE RID_DEPLOYMENT_LICENSE_START + + + +#endif diff --git a/desktop/source/deployment/gui/dp_gui_autoscrolledit.cxx b/desktop/source/deployment/gui/dp_gui_autoscrolledit.cxx new file mode 100644 index 000000000000..5e766b9470cb --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_autoscrolledit.cxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "svtools/svmedit2.hxx" +#include "svl/lstner.hxx" +#include "svtools/xtextedt.hxx" +#include "vcl/scrbar.hxx" + +#include "dp_gui_autoscrolledit.hxx" + + +namespace dp_gui { + + +AutoScrollEdit::AutoScrollEdit( Window* pParent, const ResId& rResId ) + : ExtMultiLineEdit( pParent, rResId ) +{ + ScrollBar* pScroll = GetVScrollBar(); + if (pScroll) + pScroll->Hide(); + StartListening( *GetTextEngine() ); +} + +AutoScrollEdit::~AutoScrollEdit() +{ + EndListeningAll(); +} + +void AutoScrollEdit::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.IsA( TYPE(TextHint) ) ) + { + sal_uLong nId = ((const TextHint&)rHint).GetId(); + if ( nId == TEXT_HINT_VIEWSCROLLED ) + { + ScrollBar* pScroll = GetVScrollBar(); + if ( pScroll ) + pScroll->Show(); + } + } +} + + +} // namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_autoscrolledit.hxx b/desktop/source/deployment/gui/dp_gui_autoscrolledit.hxx new file mode 100644 index 000000000000..c49477358c1b --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_autoscrolledit.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_GUI_DP_GUI_AUTOSCROLLEDIT_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_AUTOSCROLLEDIT_HXX + +#include "svtools/svmedit2.hxx" +#include "svl/lstner.hxx" + +namespace dp_gui { + +/** This control shows automatically the vertical scroll bar if text is inserted, + that does not fit into the text area. In the resource one uses MultiLineEdit + and needs to set VScroll = TRUE +*/ +class AutoScrollEdit : public ExtMultiLineEdit, public SfxListener +{ +public: + AutoScrollEdit( Window* pParent, const ResId& rResId ); + ~AutoScrollEdit(); + + using ExtMultiLineEdit::Notify; + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); +}; + +} // namespace dp_gui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_backend.src b/desktop/source/deployment/gui/dp_gui_backend.src new file mode 100644 index 000000000000..e1f242a600c4 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_backend.src @@ -0,0 +1,86 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_gui.hrc" + +// package bundle: +Image RID_IMG_DEF_PACKAGE_BUNDLE +{ + ImageBitmap = Bitmap { File = "sx03256.bmp"; }; + MASKCOLOR +}; + +// script, dialog: +Image RID_IMG_SCRIPTLIB +{ + ImageBitmap = Bitmap { File = "im30820.bmp"; }; + MASKCOLOR +}; + +Image RID_IMG_DIALOGLIB +{ + ImageBitmap = Bitmap { File = "dialogfolder_16.bmp"; }; + MASKCOLOR +}; + +// configuration: +Image RID_IMG_CONF_XML +{ + ImageBitmap = Bitmap { File = "xml_16.bmp"; }; + MASKCOLOR +}; + +// component, typelib: +Image RID_IMG_COMPONENT +{ + ImageBitmap = Bitmap { File = "component_16.bmp"; }; + MASKCOLOR +}; + +Image RID_IMG_JAVA_COMPONENT +{ + ImageBitmap = Bitmap { File = "javacomponent_16.bmp"; }; + MASKCOLOR +}; + +Image RID_IMG_TYPELIB +{ + ImageBitmap = Bitmap { File = "library_16.bmp"; }; + MASKCOLOR +}; + +Image RID_IMG_JAVA_TYPELIB +{ + ImageBitmap = Bitmap { File = "javalibrary_16.bmp"; }; + MASKCOLOR +}; + +Image RID_IMG_HELP +{ + ImageBitmap = Bitmap { File = "sc_helperdialog.bmp"; }; + MASKCOLOR +}; diff --git a/desktop/source/deployment/gui/dp_gui_dependencydialog.cxx b/desktop/source/deployment/gui/dp_gui_dependencydialog.cxx new file mode 100644 index 000000000000..7019db610b85 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dependencydialog.cxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "sal/config.h" + +#include <algorithm> +#include <vector> + +#include "rtl/ustring.hxx" +#include "tools/gen.hxx" +#include "tools/resid.hxx" +#include "tools/resmgr.hxx" +#include "tools/solar.h" +#include "tools/string.hxx" +#include "vcl/dialog.hxx" + +#include "dp_gui.hrc" +#include "dp_gui_dependencydialog.hxx" +#include "dp_gui_shared.hxx" + +class Window; + +using dp_gui::DependencyDialog; + +DependencyDialog::DependencyDialog( + Window * parent, std::vector< rtl::OUString > const & dependencies): + ModalDialog(parent, DpGuiResId(RID_DLG_DEPENDENCIES) ), + m_text(this, DpGuiResId(RID_DLG_DEPENDENCIES_TEXT)), + m_list(this, DpGuiResId(RID_DLG_DEPENDENCIES_LIST)), + m_ok(this, DpGuiResId(RID_DLG_DEPENDENCIES_OK)), + m_listDelta( + GetOutputSizePixel().Width() - m_list.GetSizePixel().Width(), + GetOutputSizePixel().Height() - m_list.GetSizePixel().Height()) +{ + FreeResource(); + SetMinOutputSizePixel(GetOutputSizePixel()); + m_list.SetReadOnly(); + for (std::vector< rtl::OUString >::const_iterator i(dependencies.begin()); + i != dependencies.end(); ++i) + { + m_list.InsertEntry(*i); + } +} + +DependencyDialog::~DependencyDialog() {} + +void DependencyDialog::Resize() { + long n = m_ok.GetPosPixel().Y() - + (m_list.GetPosPixel().Y() + m_list.GetSizePixel().Height()); + m_list.SetSizePixel( + Size( + GetOutputSizePixel().Width() - m_listDelta.Width(), + GetOutputSizePixel().Height() - m_listDelta.Height())); + m_ok.SetPosPixel( + Point( + (m_list.GetPosPixel().X() + + (m_list.GetSizePixel().Width() - m_ok.GetSizePixel().Width()) / 2), + m_list.GetPosPixel().Y() + m_list.GetSizePixel().Height() + n)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_dependencydialog.hxx b/desktop/source/deployment/gui/dp_gui_dependencydialog.hxx new file mode 100644 index 000000000000..48ef45fd15c0 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dependencydialog.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_GUI_DP_GUI_DEPENDENCYDIALOG_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_DEPENDENCYDIALOG_HXX + +#include "sal/config.h" + +#include <vector> +#include "tools/gen.hxx" +#include "vcl/button.hxx" +#include "vcl/dialog.hxx" +#include "vcl/fixed.hxx" +#include "vcl/lstbox.hxx" + +class Window; +namespace rtl { class OUString; } + +namespace dp_gui { + +class DependencyDialog: public ModalDialog { +public: + DependencyDialog( + Window * parent, std::vector< rtl::OUString > const & dependencies); + + ~DependencyDialog(); + +private: + DependencyDialog(DependencyDialog &); // not defined + void operator =(DependencyDialog &); // not defined + + virtual void Resize(); + + FixedText m_text; + ListBox m_list; + OKButton m_ok; + Size m_listDelta; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_dependencydialog.src b/desktop/source/deployment/gui/dp_gui_dependencydialog.src new file mode 100644 index 000000000000..e7adbce9992b --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dependencydialog.src @@ -0,0 +1,72 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "svtools/controldims.hrc" + +#include "dp_gui.hrc" + +#define LOCAL_WIDTH (50 * RSC_BS_CHARWIDTH) +#define LOCAL_TEXT_HEIGHT (2 * RSC_CD_FIXEDTEXT_HEIGHT) +#define LOCAL_LIST_HEIGHT (6 * RSC_BS_CHARHEIGHT) + +ModalDialog RID_DLG_DEPENDENCIES { + HelpID = "desktop:ModalDialog:RID_DLG_DEPENDENCIES"; + Size = MAP_APPFONT( + (RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH + + RSC_SP_DLG_INNERBORDER_RIGHT), + (RSC_SP_DLG_INNERBORDER_TOP + LOCAL_TEXT_HEIGHT + RSC_SP_CTRL_DESC_Y + + LOCAL_LIST_HEIGHT + RSC_SP_CTRL_Y + RSC_CD_PUSHBUTTON_HEIGHT + + RSC_SP_DLG_INNERBORDER_BOTTOM)); + Text[en-US] = "System dependencies check"; + Sizeable = TRUE; + Moveable = TRUE; + Closeable = TRUE; + FixedText RID_DLG_DEPENDENCIES_TEXT { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP); + Size = MAP_APPFONT(LOCAL_WIDTH, LOCAL_TEXT_HEIGHT); + Text[en-US] = "The extension cannot be installed as the following\nsystem dependencies are not fulfilled:"; + NoLabel = TRUE; + }; + ListBox RID_DLG_DEPENDENCIES_LIST { + HelpID = "desktop:ListBox:RID_DLG_DEPENDENCIES:RID_DLG_DEPENDENCIES_LIST"; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + LOCAL_TEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, LOCAL_LIST_HEIGHT); + }; + OKButton RID_DLG_DEPENDENCIES_OK { + Pos = MAP_APPFONT( + (RSC_SP_DLG_INNERBORDER_LEFT + + (LOCAL_WIDTH - RSC_CD_PUSHBUTTON_WIDTH) / 2), + (RSC_SP_DLG_INNERBORDER_TOP + LOCAL_TEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT + RSC_SP_CTRL_Y)); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + DefButton = TRUE; + }; +}; diff --git a/desktop/source/deployment/gui/dp_gui_dialog.src b/desktop/source/deployment/gui/dp_gui_dialog.src new file mode 100644 index 000000000000..d8c3f77c4635 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dialog.src @@ -0,0 +1,387 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "svtools/controldims.hrc" +#include "dp_gui.hrc" + +String RID_STR_ADD_PACKAGES +{ + Text [ en-US ] = "Add Extension(s)"; +}; + +String RID_CTX_ITEM_REMOVE +{ + Text [ en-US ] = "~Remove"; +}; + +String RID_CTX_ITEM_ENABLE +{ + Text [ en-US ] = "~Enable"; +}; + +String RID_CTX_ITEM_DISABLE +{ + Text [ en-US ] = "~Disable"; +}; + +String RID_CTX_ITEM_CHECK_UPDATE +{ + Text [ en-US ] = "~Update..."; +}; + +String RID_CTX_ITEM_OPTIONS +{ + Text [ en-US ] = "~Options..."; +}; + + +String RID_STR_ADDING_PACKAGES +{ + Text [ en-US ] = "Adding %EXTENSION_NAME"; +}; + +String RID_STR_REMOVING_PACKAGES +{ + Text [ en-US ] = "Removing %EXTENSION_NAME"; +}; + +String RID_STR_ENABLING_PACKAGES +{ + Text [ en-US ] = "Enabling %EXTENSION_NAME"; +}; + +String RID_STR_DISABLING_PACKAGES +{ + Text [ en-US ] = "Disabling %EXTENSION_NAME"; +}; + +String RID_STR_ACCEPT_LICENSE +{ + Text [ en-US ] = "Accept license for %EXTENSION_NAME"; +}; + +String RID_STR_INSTALL_FOR_ALL +{ + Text [ en-US ] = "~For all users"; +}; + +String RID_STR_INSTALL_FOR_ME +{ + Text [ en-US ] = "~Only for me"; +}; + +String RID_STR_ERROR_UNKNOWN_STATUS +{ + Text [ en-US ] = "Error: The status of this extension is unknown"; +}; + +String RID_STR_CLOSE_BTN +{ + Text [ en-US ] = "Close"; +}; + +String RID_STR_EXIT_BTN +{ + Text [ en-US ] = "Quit"; +}; + +String RID_STR_NO_ADMIN_PRIVILEGE +{ + Text [ en-US ] = "%PRODUCTNAME has been updated to a new version. " + "Some shared %PRODUCTNAME extensions are not compatible with this version and need to be updated before %PRODUCTNAME can be started.\n\n" + "Updating of shared extension requires administrator privileges. Contact your system administrator to update the following shared extensions:"; +}; + +String RID_STR_ERROR_MISSING_DEPENDENCIES +{ + Text [ en-US ] = "The extension cannot be enabled as the following system dependencies are not fulfilled:"; +}; + +String RID_STR_ERROR_MISSING_LICENSE +{ + Text [ en-US ] = "This extension is disabled because you haven't accepted the license yet.\n"; +}; + +String RID_STR_SHOW_LICENSE_CMD +{ + Text [ en-US ] = "Show license"; +}; + +// Dialog layout +// --------------------------------------------------- +// row 1 | multi line edit +// --------------------------------------------------- +// row 2 | fixed text +// --------------------------------------------------- +// row 3 | img | fixed text | fixed text | button +// ---------------------------------------------------- +// row 4 | img | fixed text | fixed text +// --------------------------------------------------- +// row 5 |fixed line +// --------------------------------------------------- +// row 6 | | |button | button +// --------------------------------------------------- +// | col 1 | col 2 | col3 | col4 | col5 + +//To change the overall size of the multi line edit change +//ROW1_HEIGHT and COL3_WIDTH + +#define ROW1_Y RSC_SP_DLG_INNERBORDER_TOP +#define ROW1_HEIGHT 16*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW2_Y ROW1_Y+ROW1_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW2_HEIGHT 3*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW3_Y ROW2_Y+ROW2_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW3_HEIGHT 3*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW4_Y ROW3_Y+ROW3_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW4_HEIGHT 3*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW5_Y ROW4_Y+ROW4_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW5_HEIGHT RSC_CD_FIXEDTEXT_HEIGHT +#define ROW6_Y ROW5_Y+ROW5_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW6_HEIGHT RSC_CD_PUSHBUTTON_HEIGHT + +#define LIC_DLG_HEIGHT ROW6_Y+ROW6_HEIGHT+RSC_SP_DLG_INNERBORDER_BOTTOM + +#define COL1_X RSC_SP_DLG_INNERBORDER_LEFT +#define IMG_ARROW_WIDTH 16 +#define COL1_WIDTH IMG_ARROW_WIDTH +#define COL2_X COL1_X+COL1_WIDTH +#define COL2_WIDTH 10 +#define COL3_X COL2_X+COL2_WIDTH+RSC_SP_CTRL_GROUP_X +#define COL3_WIDTH 150 +#define COL4_X COL3_X+COL3_WIDTH +#define COL4_WIDTH RSC_CD_PUSHBUTTON_WIDTH+RSC_SP_CTRL_GROUP_X +#define COL5_X COL4_X+COL4_WIDTH + +#define LIC_DLG_WIDTH COL5_X+RSC_CD_PUSHBUTTON_WIDTH+RSC_SP_DLG_INNERBORDER_RIGHT +#define BODYWIDTH LIC_DLG_WIDTH-RSC_SP_DLG_INNERBORDER_LEFT-RSC_SP_DLG_INNERBORDER_RIGHT + +ModalDialog RID_DLG_LICENSE +{ + HelpID = "desktop:ModalDialog:RID_DLG_LICENSE"; + Text [ en-US ] = "Extension Software License Agreement"; + + Size = MAP_APPFONT(LIC_DLG_WIDTH, LIC_DLG_HEIGHT); + OutputSize = TRUE; + SVLook = TRUE; + Moveable = TRUE; + Closeable = TRUE; + Sizeable = FALSE; + + MultiLineEdit ML_LICENSE + { + HelpID = "desktop:MultiLineEdit:RID_DLG_LICENSE:ML_LICENSE"; + Pos = MAP_APPFONT(COL1_X, ROW1_Y); + Size = MAP_APPFONT(BODYWIDTH, ROW1_HEIGHT); + Border = TRUE; + VScroll = TRUE; + ReadOnly = TRUE; + }; + + FixedText FT_LICENSE_HEADER + { + Pos = MAP_APPFONT(COL1_X, ROW2_Y); + Size = MAP_APPFONT(COL1_WIDTH+COL2_WIDTH+COL3_WIDTH+COL4_WIDTH, ROW2_HEIGHT); + WordBreak = TRUE; + NoLabel = TRUE; + Text [ en-US ] = "Please follow these steps to proceed with the installation of the extension:"; + }; + + FixedText FT_LICENSE_BODY_1 + { + Pos = MAP_APPFONT(COL2_X, ROW3_Y); + Size = MAP_APPFONT( COL2_WIDTH, ROW3_HEIGHT ); + NoLabel = TRUE; + Text [ en-US ] = "1."; + }; + + //spans col3 + col4 + FixedText FT_LICENSE_BODY_1_TXT + { + Pos = MAP_APPFONT(COL3_X, ROW3_Y); + Size = MAP_APPFONT(COL3_WIDTH+COL4_WIDTH, ROW3_HEIGHT); + WordBreak = TRUE; + NoLabel = TRUE; + Text [ en-US ] = "Read the complete License Agreement. Use the scroll bar or the \'Scroll Down\' button in this dialog to view the entire license text."; + }; + + FixedText FT_LICENSE_BODY_2 + { + Pos = MAP_APPFONT(COL2_X, ROW4_Y); + Size = MAP_APPFONT(COL2_WIDTH, ROW4_HEIGHT); + NoLabel = TRUE; + Text [ en-US ] = "2."; + }; + + FixedText FT_LICENSE_BODY_2_TXT + { + Pos = MAP_APPFONT(COL3_X, ROW4_Y); + Size = MAP_APPFONT(COL3_WIDTH+COL4_WIDTH, ROW4_HEIGHT); + WordBreak = TRUE; + NoLabel = TRUE; + Text [ en-US ] = "Accept the License Agreement for the extension by pressing the \'Accept\' button."; + + }; + + PushButton PB_LICENSE_DOWN + { + HelpID = "desktop:PushButton:RID_DLG_LICENSE:PB_LICENSE_DOWN"; + TabStop = TRUE ; + Pos = MAP_APPFONT(COL5_X , ROW3_Y) ; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT) ; + Text [ en-US ] = "~Scroll Down"; + + }; + + FixedLine FL_LICENSE + { + Pos = MAP_APPFONT ( 0, ROW5_Y) ; + Size = MAP_APPFONT ( LIC_DLG_WIDTH, ROW5_HEIGHT ) ; + }; + + FixedImage FI_LICENSE_ARROW1 + { + Pos = MAP_APPFONT (COL1_X, ROW3_Y) ; + Size = (16, 16); + Fixed = Image + { + ImageBitmap = Bitmap { File = "sc06300.png"; }; + MASKCOLOR + }; + }; + + FixedImage FI_LICENSE_ARROW2 + { + Pos = MAP_APPFONT (COL1_X, ROW4_Y) ; + Size = (16,16); + Fixed = Image + { + ImageBitmap = Bitmap { File = "sc06300.png"; }; + MASKCOLOR + }; + }; + + OKButton BTN_LICENSE_ACCEPT + { + Pos = MAP_APPFONT(COL4_X, ROW6_Y); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + + TabStop = TRUE; + DefButton = TRUE; + Text [ en-US ] = "Accept"; + }; + + CancelButton BTN_LICENSE_DECLINE + { + Pos = MAP_APPFONT(COL5_X, ROW6_Y); + Size = MAP_APPFONT( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + Text [ en-US ] = "Decline" ; + TabStop = TRUE; + }; + +}; + +ModalDialog RID_DLG_SHOW_LICENSE +{ + Text [ en-US ] = "Extension Software License Agreement"; + Size = MAP_APPFONT( 300, 200 ); + OutputSize = TRUE; + SVLook = TRUE; + Moveable = TRUE; + Closeable = TRUE; + Sizeable = TRUE; + + MultiLineEdit ML_LICENSE + { + Pos = MAP_APPFONT( 5, 5 ); + Size = MAP_APPFONT( 300 - 10, 200 - 15 - RSC_CD_PUSHBUTTON_HEIGHT ); + Border = TRUE; + VScroll = TRUE; + ReadOnly = TRUE; + }; + + OKButton RID_EM_BTN_CLOSE + { + TabStop = TRUE; + DefButton = TRUE; + Text [ en-US ] = "Close"; + Pos = MAP_APPFONT( (300-RSC_CD_PUSHBUTTON_WIDTH)/2, 200 - 5 - RSC_CD_PUSHBUTTON_HEIGHT ); + Size = MAP_APPFONT( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; +}; + + + +WarningBox RID_WARNINGBOX_INSTALL_EXTENSION { + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_OK; + Message[en-US] = "You are about to install the extension \'%NAME\'.\n" + "Click \'OK\' to proceed with the installation.\n" + "Click \'Cancel\' to stop the installation."; +}; + +WarningBox RID_WARNINGBOX_REMOVE_EXTENSION { + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "You are about to remove the extension \'%NAME\'.\n" + "Click \'OK\' to remove the extension.\n" + "Click \'Cancel\' to stop removing the extension."; +}; + +WARNINGBOX RID_WARNINGBOX_REMOVE_SHARED_EXTENSION +{ + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "Make sure that no further users are working with the same " + "%PRODUCTNAME, when changing shared extensions in a multi user environment.\n" + "Click \'OK\' to remove the extension.\n" + "Click \'Cancel\' to stop removing the extension."; +}; + +WARNINGBOX RID_WARNINGBOX_ENABLE_SHARED_EXTENSION +{ + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "Make sure that no further users are working with the same " + "%PRODUCTNAME, when changing shared extensions in a multi user environment.\n" + "Click \'OK\' to enable the extension.\n" + "Click \'Cancel\' to stop enabling the extension."; +}; + +WARNINGBOX RID_WARNINGBOX_DISABLE_SHARED_EXTENSION +{ + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "Make sure that no further users are working with the same " + "%PRODUCTNAME, when changing shared extensions in a multi user environment.\n" + "Click \'OK\' to disable the extension.\n" + "Click \'Cancel\' to stop disabling the extension."; +}; + + +String RID_STR_UNSUPPORTED_PLATFORM +{ + Text [ en-US ] = "The extension \'%Name\' does not work on this computer."; +}; diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.cxx b/desktop/source/deployment/gui/dp_gui_dialog2.cxx new file mode 100644 index 000000000000..01e7f92aac6b --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dialog2.cxx @@ -0,0 +1,1827 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_gui.hrc" +#include "svtools/controldims.hrc" +#include "svtools/svtools.hrc" + +#include "dp_gui.h" +#include "dp_gui_dialog2.hxx" +#include "dp_gui_extlistbox.hxx" +#include "dp_gui_shared.hxx" +#include "dp_gui_theextmgr.hxx" +#include "dp_gui_extensioncmdqueue.hxx" +#include "dp_misc.h" +#include "dp_ucb.h" +#include "dp_update.hxx" +#include "dp_identifier.hxx" +#include "dp_descriptioninfoset.hxx" + +#include "vcl/ctrl.hxx" +#include "vcl/menu.hxx" +#include "vcl/msgbox.hxx" +#include "vcl/scrbar.hxx" +#include "vcl/svapp.hxx" + +#include "osl/mutex.hxx" + +#include "svtools/extensionlistbox.hxx" + +#include "sfx2/sfxdlg.hxx" + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/bootstrap.hxx" + +#include "comphelper/processfactory.hxx" +#include "ucbhelper/content.hxx" +#include "unotools/collatorwrapper.hxx" + +#include "com/sun/star/beans/StringPair.hpp" + +#include "com/sun/star/i18n/CollatorOptions.hpp" + +#include "com/sun/star/system/SystemShellExecuteFlags.hpp" +#include "com/sun/star/system/XSystemShellExecute.hpp" + +#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" +#include "com/sun/star/ui/dialogs/TemplateDescription.hpp" +#include "com/sun/star/ui/dialogs/XFilePicker.hpp" +#include "com/sun/star/ui/dialogs/XFilterManager.hpp" + +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" + +#include <map> +#include <vector> +#include <boost/shared_ptr.hpp> + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +using namespace ::com::sun::star; +using namespace ::com::sun::star::system; + +using ::rtl::OUString; + + +namespace dp_gui { + +#define TOP_OFFSET 5 +#define LINE_SIZE 4 +#define PROGRESS_WIDTH 60 +#define PROGRESS_HEIGHT 14 + +//------------------------------------------------------------------------------ +struct StrAllFiles : public rtl::StaticWithInit< OUString, StrAllFiles > +{ + const OUString operator () () { + const SolarMutexGuard guard; + ::std::auto_ptr< ResMgr > const resmgr( ResMgr::CreateResMgr( "fps_office" ) ); + OSL_ASSERT( resmgr.get() != 0 ); + String ret( ResId( STR_FILTERNAME_ALL, *resmgr.get() ) ); + return ret; + } +}; + +//------------------------------------------------------------------------------ +// ExtBoxWithBtns_Impl +//------------------------------------------------------------------------------ + +enum MENU_COMMAND +{ + CMD_NONE = 0, + CMD_REMOVE = 1, + CMD_ENABLE, + CMD_DISABLE, + CMD_UPDATE, + CMD_SHOW_LICENSE +}; + +class ExtBoxWithBtns_Impl : public ExtensionBox_Impl +{ + Size m_aOutputSize; + bool m_bInterfaceLocked; + + PushButton *m_pOptionsBtn; + PushButton *m_pEnableBtn; + PushButton *m_pRemoveBtn; + + ExtMgrDialog *m_pParent; + + void SetButtonPos( const Rectangle& rRect ); + void SetButtonStatus( const TEntry_Impl pEntry ); + bool HandleTabKey( bool bReverse ); + MENU_COMMAND ShowPopupMenu( const Point &rPos, const long nPos ); + + //----------------- + DECL_DLLPRIVATE_LINK( ScrollHdl, ScrollBar * ); + + DECL_DLLPRIVATE_LINK( HandleOptionsBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleEnableBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleRemoveBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleHyperlink, svt::FixedHyperlink * ); + +public: + ExtBoxWithBtns_Impl( ExtMgrDialog* pParent, TheExtensionManager *pManager ); + ~ExtBoxWithBtns_Impl(); + + virtual void MouseButtonDown( const MouseEvent& rMEvt ); + virtual long Notify( NotifyEvent& rNEvt ); + + const Size GetMinOutputSizePixel() const; + + virtual void RecalcAll(); + virtual void selectEntry( const long nPos ); + //----------------- + void enableButtons( bool bEnable ); +}; + +//------------------------------------------------------------------------------ +ExtBoxWithBtns_Impl::ExtBoxWithBtns_Impl( ExtMgrDialog* pParent, TheExtensionManager *pManager ) : + ExtensionBox_Impl( pParent, pManager ), + m_bInterfaceLocked( false ), + m_pOptionsBtn( NULL ), + m_pEnableBtn( NULL ), + m_pRemoveBtn( NULL ), + m_pParent( pParent ) +{ + m_pOptionsBtn = new PushButton( this, WB_TABSTOP ); + m_pEnableBtn = new PushButton( this, WB_TABSTOP ); + m_pRemoveBtn = new PushButton( this, WB_TABSTOP ); + + SetHelpId( HID_EXTENSION_MANAGER_LISTBOX ); + m_pOptionsBtn->SetHelpId( HID_EXTENSION_MANAGER_LISTBOX_OPTIONS ); + m_pEnableBtn->SetHelpId( HID_EXTENSION_MANAGER_LISTBOX_DISABLE ); + m_pRemoveBtn->SetHelpId( HID_EXTENSION_MANAGER_LISTBOX_REMOVE ); + + m_pOptionsBtn->SetClickHdl( LINK( this, ExtBoxWithBtns_Impl, HandleOptionsBtn ) ); + m_pEnableBtn->SetClickHdl( LINK( this, ExtBoxWithBtns_Impl, HandleEnableBtn ) ); + m_pRemoveBtn->SetClickHdl( LINK( this, ExtBoxWithBtns_Impl, HandleRemoveBtn ) ); + + m_pOptionsBtn->SetText( DialogHelper::getResourceString( RID_CTX_ITEM_OPTIONS ) ); + m_pEnableBtn->SetText( DialogHelper::getResourceString( RID_CTX_ITEM_DISABLE ) ); + m_pRemoveBtn->SetText( DialogHelper::getResourceString( RID_CTX_ITEM_REMOVE ) ); + + Size aSize = LogicToPixel( Size( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ), + MapMode( MAP_APPFONT ) ); + m_pOptionsBtn->SetSizePixel( aSize ); + m_pEnableBtn->SetSizePixel( aSize ); + m_pRemoveBtn->SetSizePixel( aSize ); + + SetExtraSize( aSize.Height() + 2 * TOP_OFFSET ); + + SetScrollHdl( LINK( this, ExtBoxWithBtns_Impl, ScrollHdl ) ); +} + +//------------------------------------------------------------------------------ +ExtBoxWithBtns_Impl::~ExtBoxWithBtns_Impl() +{ + delete m_pOptionsBtn; + delete m_pEnableBtn; + delete m_pRemoveBtn; +} + +//------------------------------------------------------------------------------ +const Size ExtBoxWithBtns_Impl::GetMinOutputSizePixel() const +{ + Size aMinSize( ExtensionBox_Impl::GetMinOutputSizePixel() ); + long nHeight = aMinSize.Height(); + nHeight += m_pOptionsBtn->GetSizePixel().Height(); + nHeight += 2 * TOP_OFFSET; + long nWidth = m_pOptionsBtn->GetSizePixel().Width(); + nWidth *= 3; + nWidth += 5*TOP_OFFSET + 20; + + return Size( nWidth, nHeight ); +} + +// ----------------------------------------------------------------------- +void ExtBoxWithBtns_Impl::RecalcAll() +{ + const sal_Int32 nActive = getSelIndex(); + + if ( nActive != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + { + SetButtonStatus( GetEntryData( nActive) ); + } + else + { + m_pOptionsBtn->Hide(); + m_pEnableBtn->Hide(); + m_pRemoveBtn->Hide(); + } + + ExtensionBox_Impl::RecalcAll(); + + if ( nActive != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + SetButtonPos( GetEntryRect( nActive ) ); +} + + +//------------------------------------------------------------------------------ +//This function may be called with nPos < 0 +void ExtBoxWithBtns_Impl::selectEntry( const long nPos ) +{ + if ( HasActive() && ( nPos == getSelIndex() ) ) + return; + + ExtensionBox_Impl::selectEntry( nPos ); +} + +// ----------------------------------------------------------------------- +void ExtBoxWithBtns_Impl::SetButtonPos( const Rectangle& rRect ) +{ + Size aBtnSize( m_pOptionsBtn->GetSizePixel() ); + Point aBtnPos( rRect.Left() + ICON_OFFSET, + rRect.Bottom() - TOP_OFFSET - aBtnSize.Height() ); + + m_pOptionsBtn->SetPosPixel( aBtnPos ); + aBtnPos.X() = rRect.Right() - TOP_OFFSET - aBtnSize.Width(); + m_pRemoveBtn->SetPosPixel( aBtnPos ); + aBtnPos.X() -= ( TOP_OFFSET + aBtnSize.Width() ); + m_pEnableBtn->SetPosPixel( aBtnPos ); +} + +// ----------------------------------------------------------------------- +void ExtBoxWithBtns_Impl::SetButtonStatus( const TEntry_Impl pEntry ) +{ + bool bShowOptionBtn = true; + + pEntry->m_bHasButtons = false; + if ( ( pEntry->m_eState == REGISTERED ) || ( pEntry->m_eState == NOT_AVAILABLE ) ) + { + m_pEnableBtn->SetText( DialogHelper::getResourceString( RID_CTX_ITEM_DISABLE ) ); + m_pEnableBtn->SetHelpId( HID_EXTENSION_MANAGER_LISTBOX_DISABLE ); + } + else + { + m_pEnableBtn->SetText( DialogHelper::getResourceString( RID_CTX_ITEM_ENABLE ) ); + m_pEnableBtn->SetHelpId( HID_EXTENSION_MANAGER_LISTBOX_ENABLE ); + bShowOptionBtn = false; + } + + if ( ( !pEntry->m_bUser || ( pEntry->m_eState == NOT_AVAILABLE ) || pEntry->m_bMissingDeps ) + && !pEntry->m_bMissingLic ) + m_pEnableBtn->Hide(); + else + { + m_pEnableBtn->Enable( !pEntry->m_bLocked ); + m_pEnableBtn->Show(); + pEntry->m_bHasButtons = true; + } + + if ( pEntry->m_bHasOptions && bShowOptionBtn ) + { + m_pOptionsBtn->Enable( pEntry->m_bHasOptions ); + m_pOptionsBtn->Show(); + pEntry->m_bHasButtons = true; + } + else + m_pOptionsBtn->Hide(); + + if ( pEntry->m_bUser || pEntry->m_bShared ) + { + m_pRemoveBtn->Enable( !pEntry->m_bLocked ); + m_pRemoveBtn->Show(); + pEntry->m_bHasButtons = true; + } + else + m_pRemoveBtn->Hide(); +} + +// ----------------------------------------------------------------------- +bool ExtBoxWithBtns_Impl::HandleTabKey( bool bReverse ) +{ + sal_Int32 nIndex = getSelIndex(); + + if ( nIndex == EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + return false; + + PushButton *pNext = NULL; + + if ( m_pOptionsBtn->HasFocus() ) { + if ( !bReverse && !GetEntryData( nIndex )->m_bLocked ) + pNext = m_pEnableBtn; + } + else if ( m_pEnableBtn->HasFocus() ) { + if ( !bReverse ) + pNext = m_pRemoveBtn; + else if ( GetEntryData( nIndex )->m_bHasOptions ) + pNext = m_pOptionsBtn; + } + else if ( m_pRemoveBtn->HasFocus() ) { + if ( bReverse ) + pNext = m_pEnableBtn; + } + else { + if ( !bReverse ) { + if ( GetEntryData( nIndex )->m_bHasOptions ) + pNext = m_pOptionsBtn; + else if ( ! GetEntryData( nIndex )->m_bLocked ) + pNext = m_pEnableBtn; + } else { + if ( ! GetEntryData( nIndex )->m_bLocked ) + pNext = m_pRemoveBtn; + else if ( GetEntryData( nIndex )->m_bHasOptions ) + pNext = m_pOptionsBtn; + } + } + + if ( pNext ) + { + pNext->GrabFocus(); + return true; + } + else + return false; +} + +// ----------------------------------------------------------------------- +MENU_COMMAND ExtBoxWithBtns_Impl::ShowPopupMenu( const Point & rPos, const long nPos ) +{ + if ( nPos >= (long) getItemCount() ) + return CMD_NONE; + + PopupMenu aPopup; + + aPopup.InsertItem( CMD_UPDATE, DialogHelper::getResourceString( RID_CTX_ITEM_CHECK_UPDATE ) ); + + if ( ! GetEntryData( nPos )->m_bLocked ) + { + if ( GetEntryData( nPos )->m_bUser ) + { + if ( GetEntryData( nPos )->m_eState == REGISTERED ) + aPopup.InsertItem( CMD_DISABLE, DialogHelper::getResourceString( RID_CTX_ITEM_DISABLE ) ); + else if ( GetEntryData( nPos )->m_eState != NOT_AVAILABLE ) + aPopup.InsertItem( CMD_ENABLE, DialogHelper::getResourceString( RID_CTX_ITEM_ENABLE ) ); + } + aPopup.InsertItem( CMD_REMOVE, DialogHelper::getResourceString( RID_CTX_ITEM_REMOVE ) ); + } + + if ( GetEntryData( nPos )->m_sLicenseText.Len() ) + aPopup.InsertItem( CMD_SHOW_LICENSE, DialogHelper::getResourceString( RID_STR_SHOW_LICENSE_CMD ) ); + + return (MENU_COMMAND) aPopup.Execute( this, rPos ); +} + +//------------------------------------------------------------------------------ +void ExtBoxWithBtns_Impl::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( m_bInterfaceLocked ) + return; + + const Point aMousePos( rMEvt.GetPosPixel() ); + const long nPos = PointToPos( aMousePos ); + + if ( rMEvt.IsRight() ) + { + switch( ShowPopupMenu( aMousePos, nPos ) ) + { + case CMD_NONE: break; + case CMD_ENABLE: m_pParent->enablePackage( GetEntryData( nPos )->m_xPackage, true ); + break; + case CMD_DISABLE: m_pParent->enablePackage( GetEntryData( nPos )->m_xPackage, false ); + break; + case CMD_UPDATE: m_pParent->updatePackage( GetEntryData( nPos )->m_xPackage ); + break; + case CMD_REMOVE: m_pParent->removePackage( GetEntryData( nPos )->m_xPackage ); + break; + case CMD_SHOW_LICENSE: + { + ShowLicenseDialog aLicenseDlg( m_pParent, GetEntryData( nPos )->m_xPackage ); + aLicenseDlg.Execute(); + break; + } + } + } + else if ( rMEvt.IsLeft() ) + { + const SolarMutexGuard aGuard; + if ( rMEvt.IsMod1() && HasActive() ) + selectEntry( EXTENSION_LISTBOX_ENTRY_NOTFOUND ); // Selecting an not existing entry will deselect the current one + else + selectEntry( nPos ); + } +} + +//------------------------------------------------------------------------------ +long ExtBoxWithBtns_Impl::Notify( NotifyEvent& rNEvt ) +{ + bool bHandled = false; + + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); + KeyCode aKeyCode = pKEvt->GetKeyCode(); + sal_uInt16 nKeyCode = aKeyCode.GetCode(); + + if ( nKeyCode == KEY_TAB ) + bHandled = HandleTabKey( aKeyCode.IsShift() ); + } + + if ( !bHandled ) + return ExtensionBox_Impl::Notify( rNEvt ); + else + return true; +} + +//------------------------------------------------------------------------------ +void ExtBoxWithBtns_Impl::enableButtons( bool bEnable ) +{ + m_bInterfaceLocked = ! bEnable; + + if ( bEnable ) + { + sal_Int32 nIndex = getSelIndex(); + if ( nIndex != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + SetButtonStatus( GetEntryData( nIndex ) ); + } + else + { + m_pOptionsBtn->Enable( false ); + m_pRemoveBtn->Enable( false ); + m_pEnableBtn->Enable( false ); + } +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtBoxWithBtns_Impl, ScrollHdl, ScrollBar*, pScrBar ) +{ + long nDelta = pScrBar->GetDelta(); + + Point aNewOptPt( m_pOptionsBtn->GetPosPixel() - Point( 0, nDelta ) ); + Point aNewRemPt( m_pRemoveBtn->GetPosPixel() - Point( 0, nDelta ) ); + Point aNewEnPt( m_pEnableBtn->GetPosPixel() - Point( 0, nDelta ) ); + + DoScroll( nDelta ); + + m_pOptionsBtn->SetPosPixel( aNewOptPt ); + m_pRemoveBtn->SetPosPixel( aNewRemPt ); + m_pEnableBtn->SetPosPixel( aNewEnPt ); + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtBoxWithBtns_Impl, HandleOptionsBtn, void*, EMPTYARG ) +{ + const sal_Int32 nActive = getSelIndex(); + + if ( nActive != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + { + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + + if ( pFact ) + { + OUString sExtensionId = GetEntryData( nActive )->m_xPackage->getIdentifier().Value; + VclAbstractDialog* pDlg = pFact->CreateOptionsDialog( this, sExtensionId, rtl::OUString() ); + + pDlg->Execute(); + + delete pDlg; + } + } + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtBoxWithBtns_Impl, HandleEnableBtn, void*, EMPTYARG ) +{ + const sal_Int32 nActive = getSelIndex(); + + if ( nActive != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + { + TEntry_Impl pEntry = GetEntryData( nActive ); + + if ( pEntry->m_bMissingLic ) + m_pParent->acceptLicense( pEntry->m_xPackage ); + else + { + const bool bEnable( pEntry->m_eState != REGISTERED ); + m_pParent->enablePackage( pEntry->m_xPackage, bEnable ); + } + } + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtBoxWithBtns_Impl, HandleRemoveBtn, void*, EMPTYARG ) +{ + const sal_Int32 nActive = getSelIndex(); + + if ( nActive != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + { + TEntry_Impl pEntry = GetEntryData( nActive ); + m_pParent->removePackage( pEntry->m_xPackage ); + } + + return 1; +} + +//------------------------------------------------------------------------------ +// DialogHelper +//------------------------------------------------------------------------------ +DialogHelper::DialogHelper( const uno::Reference< uno::XComponentContext > &xContext, + Dialog *pWindow ) : + m_pVCLWindow( pWindow ), + m_nEventID( 0 ), + m_bIsBusy( false ) +{ + m_xContext = xContext; +} + +//------------------------------------------------------------------------------ +DialogHelper::~DialogHelper() +{ + if ( m_nEventID ) + Application::RemoveUserEvent( m_nEventID ); +} + +//------------------------------------------------------------------------------ +ResId DialogHelper::getResId( sal_uInt16 nId ) +{ + const SolarMutexGuard guard; + return ResId( nId, *DeploymentGuiResMgr::get() ); +} + +//------------------------------------------------------------------------------ +String DialogHelper::getResourceString( sal_uInt16 id ) +{ + // init with non-acquired solar mutex: + BrandName::get(); + const SolarMutexGuard guard; + String ret( ResId( id, *DeploymentGuiResMgr::get() ) ); + if (ret.SearchAscii( "%PRODUCTNAME" ) != STRING_NOTFOUND) { + ret.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() ); + } + return ret; +} + +//------------------------------------------------------------------------------ +bool DialogHelper::IsSharedPkgMgr( const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( xPackage->getRepositoryName().equals( OUSTR("shared") ) ) + return true; + else + return false; +} + +//------------------------------------------------------------------------------ +bool DialogHelper::continueOnSharedExtension( const uno::Reference< deployment::XPackage > &xPackage, + Window *pParent, + const sal_uInt16 nResID, + bool &bHadWarning ) +{ + if ( !bHadWarning && IsSharedPkgMgr( xPackage ) ) + { + const SolarMutexGuard guard; + WarningBox aInfoBox( pParent, getResId( nResID ) ); + String aMsgText = aInfoBox.GetMessText(); + aMsgText.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() ); + aInfoBox.SetMessText( aMsgText ); + + bHadWarning = true; + + if ( RET_OK == aInfoBox.Execute() ) + return true; + else + return false; + } + else + return true; +} + +//------------------------------------------------------------------------------ +void DialogHelper::openWebBrowser( const OUString & sURL, const OUString &sTitle ) const +{ + if ( ! sURL.getLength() ) // Nothing to do, when the URL is empty + return; + + try + { + uno::Reference< XSystemShellExecute > xSystemShellExecute( + m_xContext->getServiceManager()->createInstanceWithContext( OUSTR( "com.sun.star.system.SystemShellExecute" ), m_xContext), uno::UNO_QUERY_THROW); + //throws css::lang::IllegalArgumentException, css::system::SystemShellExecuteException + xSystemShellExecute->execute( sURL, OUString(), SystemShellExecuteFlags::DEFAULTS ); + } + catch ( uno::Exception& ) + { + uno::Any exc( ::cppu::getCaughtException() ); + OUString msg( ::comphelper::anyToString( exc ) ); + const SolarMutexGuard guard; + ErrorBox aErrorBox( NULL, WB_OK, msg ); + aErrorBox.SetText( sTitle ); + aErrorBox.Execute(); + } +} + +//------------------------------------------------------------------------------ +bool DialogHelper::installExtensionWarn( const OUString &rExtensionName ) const +{ + const SolarMutexGuard guard; + WarningBox aInfo( m_pVCLWindow, getResId( RID_WARNINGBOX_INSTALL_EXTENSION ) ); + + String sText( aInfo.GetMessText() ); + sText.SearchAndReplaceAllAscii( "%NAME", rExtensionName ); + aInfo.SetMessText( sText ); + + return ( RET_OK == aInfo.Execute() ); +} + +//------------------------------------------------------------------------------ +bool DialogHelper::installForAllUsers( bool &bInstallForAll ) const +{ + const SolarMutexGuard guard; + QueryBox aQuery( m_pVCLWindow, getResId( RID_QUERYBOX_INSTALL_FOR_ALL ) ); + + String sMsgText = aQuery.GetMessText(); + sMsgText.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() ); + aQuery.SetMessText( sMsgText ); + + sal_uInt16 nYesBtnID = aQuery.GetButtonId( 0 ); + sal_uInt16 nNoBtnID = aQuery.GetButtonId( 1 ); + + if ( nYesBtnID != BUTTONDIALOG_BUTTON_NOTFOUND ) + aQuery.SetButtonText( nYesBtnID, getResourceString( RID_STR_INSTALL_FOR_ME ) ); + if ( nNoBtnID != BUTTONDIALOG_BUTTON_NOTFOUND ) + aQuery.SetButtonText( nNoBtnID, getResourceString( RID_STR_INSTALL_FOR_ALL ) ); + + short nRet = aQuery.Execute(); + + if ( nRet == RET_CANCEL ) + return false; + + bInstallForAll = ( nRet == RET_NO ); + return true; +} + +//------------------------------------------------------------------------------ +void DialogHelper::PostUserEvent( const Link& rLink, void* pCaller ) +{ + if ( m_nEventID ) + Application::RemoveUserEvent( m_nEventID ); + + m_nEventID = Application::PostUserEvent( rLink, pCaller ); +} + +//------------------------------------------------------------------------------ +// ExtMgrDialog +//------------------------------------------------------------------------------ +ExtMgrDialog::ExtMgrDialog( Window *pParent, TheExtensionManager *pManager ) : + ModelessDialog( pParent, getResId( RID_DLG_EXTENSION_MANAGER ) ), + DialogHelper( pManager->getContext(), (Dialog*) this ), + m_aAddBtn( this, getResId( RID_EM_BTN_ADD ) ), + m_aUpdateBtn( this, getResId( RID_EM_BTN_CHECK_UPDATES ) ), + m_aCloseBtn( this, getResId( RID_EM_BTN_CLOSE ) ), + m_aHelpBtn( this, getResId( RID_EM_BTN_HELP ) ), + m_aDivider( this ), + m_aGetExtensions( this, getResId( RID_EM_FT_GET_EXTENSIONS ) ), + m_aProgressText( this, getResId( RID_EM_FT_PROGRESS ) ), + m_aProgressBar( this, WB_BORDER + WB_3DLOOK ), + m_aCancelBtn( this, getResId( RID_EM_BTN_CANCEL ) ), + m_sAddPackages( getResourceString( RID_STR_ADD_PACKAGES ) ), + m_bHasProgress( false ), + m_bProgressChanged( false ), + m_bStartProgress( false ), + m_bStopProgress( false ), + m_bUpdateWarning( false ), + m_bEnableWarning( false ), + m_bDisableWarning( false ), + m_bDeleteWarning( false ), + m_nProgress( 0 ), + m_pManager( pManager ) +{ + // free local resources (RID < 256): + FreeResource(); + + m_pExtensionBox = new ExtBoxWithBtns_Impl( this, pManager ); + m_pExtensionBox->SetHyperlinkHdl( LINK( this, ExtMgrDialog, HandleHyperlink ) ); + + m_aAddBtn.SetClickHdl( LINK( this, ExtMgrDialog, HandleAddBtn ) ); + m_aUpdateBtn.SetClickHdl( LINK( this, ExtMgrDialog, HandleUpdateBtn ) ); + m_aGetExtensions.SetClickHdl( LINK( this, ExtMgrDialog, HandleHyperlink ) ); + m_aCancelBtn.SetClickHdl( LINK( this, ExtMgrDialog, HandleCancelBtn ) ); + + // resize update button + Size aBtnSize = m_aUpdateBtn.GetSizePixel(); + String sTitle = m_aUpdateBtn.GetText(); + long nWidth = m_aUpdateBtn.GetCtrlTextWidth( sTitle ); + nWidth += 2 * m_aUpdateBtn.GetTextHeight(); + if ( nWidth > aBtnSize.Width() ) + m_aUpdateBtn.SetSizePixel( Size( nWidth, aBtnSize.Height() ) ); + + // minimum size: + SetMinOutputSizePixel( + Size( // width: + (3 * m_aHelpBtn.GetSizePixel().Width()) + + m_aUpdateBtn.GetSizePixel().Width() + + (5 * RSC_SP_DLG_INNERBORDER_LEFT ), + // height: + (1 * m_aHelpBtn.GetSizePixel().Height()) + + (1 * m_aGetExtensions.GetSizePixel().Height()) + + (1 * m_pExtensionBox->GetMinOutputSizePixel().Height()) + + (3 * RSC_SP_DLG_INNERBORDER_LEFT) ) ); + + m_aDivider.Show(); + m_aProgressBar.Hide(); + + m_aUpdateBtn.Enable( false ); + + m_aTimeoutTimer.SetTimeout( 500 ); // mSec + m_aTimeoutTimer.SetTimeoutHdl( LINK( this, ExtMgrDialog, TimeOutHdl ) ); +} + +//------------------------------------------------------------------------------ +ExtMgrDialog::~ExtMgrDialog() +{ + m_aTimeoutTimer.Stop(); + delete m_pExtensionBox; +} + +//------------------------------------------------------------------------------ +void ExtMgrDialog::setGetExtensionsURL( const ::rtl::OUString &rURL ) +{ + m_aGetExtensions.SetURL( rURL ); +} + +//------------------------------------------------------------------------------ +long ExtMgrDialog::addPackageToList( const uno::Reference< deployment::XPackage > &xPackage, + bool bLicenseMissing ) +{ + const SolarMutexGuard aGuard; + m_aUpdateBtn.Enable( true ); + return m_pExtensionBox->addEntry( xPackage, bLicenseMissing ); +} + +//------------------------------------------------------------------------------ +void ExtMgrDialog::prepareChecking() +{ + m_pExtensionBox->prepareChecking(); +} + +//------------------------------------------------------------------------------ +void ExtMgrDialog::checkEntries() +{ + const SolarMutexGuard guard; + m_pExtensionBox->checkEntries(); +} + +//------------------------------------------------------------------------------ +bool ExtMgrDialog::removeExtensionWarn( const OUString &rExtensionName ) const +{ + const SolarMutexGuard guard; + WarningBox aInfo( const_cast< ExtMgrDialog* >(this), getResId( RID_WARNINGBOX_REMOVE_EXTENSION ) ); + + String sText( aInfo.GetMessText() ); + sText.SearchAndReplaceAllAscii( "%NAME", rExtensionName ); + aInfo.SetMessText( sText ); + + return ( RET_OK == aInfo.Execute() ); +} + +//------------------------------------------------------------------------------ +bool ExtMgrDialog::enablePackage( const uno::Reference< deployment::XPackage > &xPackage, + bool bEnable ) +{ + if ( !xPackage.is() ) + return false; + + if ( bEnable ) + { + if ( ! continueOnSharedExtension( xPackage, this, RID_WARNINGBOX_ENABLE_SHARED_EXTENSION, m_bEnableWarning ) ) + return false; + } + else + { + if ( ! continueOnSharedExtension( xPackage, this, RID_WARNINGBOX_DISABLE_SHARED_EXTENSION, m_bDisableWarning ) ) + return false; + } + + m_pManager->getCmdQueue()->enableExtension( xPackage, bEnable ); + + return true; +} + +//------------------------------------------------------------------------------ +bool ExtMgrDialog::removePackage( const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return false; + + if ( !IsSharedPkgMgr( xPackage ) || m_bDeleteWarning ) + { + if ( ! removeExtensionWarn( xPackage->getDisplayName() ) ) + return false; + } + + if ( ! continueOnSharedExtension( xPackage, this, RID_WARNINGBOX_REMOVE_SHARED_EXTENSION, m_bDeleteWarning ) ) + return false; + + m_pManager->getCmdQueue()->removeExtension( xPackage ); + + return true; +} + +//------------------------------------------------------------------------------ +bool ExtMgrDialog::updatePackage( const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return false; + + // get the extension with highest version + uno::Sequence<uno::Reference<deployment::XPackage> > seqExtensions = + m_pManager->getExtensionManager()->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(xPackage), xPackage->getName(), uno::Reference<ucb::XCommandEnvironment>()); + uno::Reference<deployment::XPackage> extension = + dp_misc::getExtensionWithHighestVersion(seqExtensions); + OSL_ASSERT(extension.is()); + std::vector< css::uno::Reference< css::deployment::XPackage > > vEntries; + vEntries.push_back(extension); + + m_pManager->getCmdQueue()->checkForUpdates( vEntries ); + + return true; +} + +//------------------------------------------------------------------------------ +bool ExtMgrDialog::acceptLicense( const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return false; + + m_pManager->getCmdQueue()->acceptLicense( xPackage ); + + return true; +} + +//------------------------------------------------------------------------------ +uno::Sequence< OUString > ExtMgrDialog::raiseAddPicker() +{ + const uno::Any mode( static_cast< sal_Int16 >( ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE ) ); + const uno::Reference< uno::XComponentContext > xContext( m_pManager->getContext() ); + const uno::Reference< ui::dialogs::XFilePicker > xFilePicker( + xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + OUSTR("com.sun.star.ui.dialogs.FilePicker"), + uno::Sequence< uno::Any >( &mode, 1 ), xContext ), uno::UNO_QUERY_THROW ); + xFilePicker->setTitle( m_sAddPackages ); + + if ( m_sLastFolderURL.Len() ) + xFilePicker->setDisplayDirectory( m_sLastFolderURL ); + + // collect and set filter list: + typedef ::std::map< OUString, OUString > t_string2string; + t_string2string title2filter; + OUString sDefaultFilter( StrAllFiles::get() ); + + const uno::Sequence< uno::Reference< deployment::XPackageTypeInfo > > packageTypes( + m_pManager->getExtensionManager()->getSupportedPackageTypes() ); + + for ( sal_Int32 pos = 0; pos < packageTypes.getLength(); ++pos ) + { + uno::Reference< deployment::XPackageTypeInfo > const & xPackageType = packageTypes[ pos ]; + const OUString filter( xPackageType->getFileFilter() ); + if (filter.getLength() > 0) + { + const OUString title( xPackageType->getShortDescription() ); + const ::std::pair< t_string2string::iterator, bool > insertion( + title2filter.insert( t_string2string::value_type( title, filter ) ) ); + if ( ! insertion.second ) + { // already existing, append extensions: + ::rtl::OUStringBuffer buf; + buf.append( insertion.first->second ); + buf.append( static_cast<sal_Unicode>(';') ); + buf.append( filter ); + insertion.first->second = buf.makeStringAndClear(); + } + if ( xPackageType->getMediaType() == OUSTR( "application/vnd.sun.star.package-bundle" ) ) + sDefaultFilter = title; + } + } + + const uno::Reference< ui::dialogs::XFilterManager > xFilterManager( xFilePicker, uno::UNO_QUERY_THROW ); + // All files at top: + xFilterManager->appendFilter( StrAllFiles::get(), OUSTR("*.*") ); + // then supported ones: + t_string2string::const_iterator iPos( title2filter.begin() ); + const t_string2string::const_iterator iEnd( title2filter.end() ); + for ( ; iPos != iEnd; ++iPos ) { + try { + xFilterManager->appendFilter( iPos->first, iPos->second ); + } + catch (lang::IllegalArgumentException & exc) { + OSL_FAIL( ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + (void) exc; + } + } + xFilterManager->setCurrentFilter( sDefaultFilter ); + + if ( xFilePicker->execute() != ui::dialogs::ExecutableDialogResults::OK ) + return uno::Sequence<OUString>(); // cancelled + + m_sLastFolderURL = xFilePicker->getDisplayDirectory(); + uno::Sequence< OUString > files( xFilePicker->getFiles() ); + OSL_ASSERT( files.getLength() > 0 ); + return files; +} + +//------------------------------------------------------------------------------ +IMPL_LINK( ExtMgrDialog, HandleCancelBtn, void*, EMPTYARG ) +{ + if ( m_xAbortChannel.is() ) + { + try + { + m_xAbortChannel->sendAbort(); + } + catch ( uno::RuntimeException & ) + { + OSL_FAIL( "### unexpected RuntimeException!" ); + } + } + return 1; +} + +// ------------------------------------------------------------------------------ +IMPL_LINK( ExtMgrDialog, startProgress, void*, _bLockInterface ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + bool bLockInterface = (bool) _bLockInterface; + + if ( m_bStartProgress && !m_bHasProgress ) + m_aTimeoutTimer.Start(); + + if ( m_bStopProgress ) + { + if ( m_aProgressBar.IsVisible() ) + m_aProgressBar.SetValue( 100 ); + m_xAbortChannel.clear(); + + OSL_TRACE( " startProgress handler: stop\n" ); + } + else + { + OSL_TRACE( " startProgress handler: start\n" ); + } + + m_aCancelBtn.Enable( bLockInterface ); + m_aAddBtn.Enable( !bLockInterface ); + m_aUpdateBtn.Enable( !bLockInterface && m_pExtensionBox->getItemCount() ); + m_pExtensionBox->enableButtons( !bLockInterface ); + + clearEventID(); + + return 0; +} + +// ------------------------------------------------------------------------------ +void ExtMgrDialog::showProgress( bool _bStart ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + bool bStart = _bStart; + + if ( bStart ) + { + m_nProgress = 0; + m_bStartProgress = true; + OSL_TRACE( "showProgress start\n" ); + } + else + { + m_nProgress = 100; + m_bStopProgress = true; + OSL_TRACE( "showProgress stop!\n" ); + } + + DialogHelper::PostUserEvent( LINK( this, ExtMgrDialog, startProgress ), (void*) bStart ); +} + +// ----------------------------------------------------------------------- +void ExtMgrDialog::updateProgress( const long nProgress ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_nProgress = nProgress; +} + +// ----------------------------------------------------------------------- +void ExtMgrDialog::updateProgress( const OUString &rText, + const uno::Reference< task::XAbortChannel > &xAbortChannel) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xAbortChannel = xAbortChannel; + m_sProgressText = rText; + m_bProgressChanged = true; +} + +//------------------------------------------------------------------------------ +void ExtMgrDialog::updatePackageInfo( const uno::Reference< deployment::XPackage > &xPackage ) +{ + const SolarMutexGuard aGuard; + m_pExtensionBox->updateEntry( xPackage ); +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtMgrDialog, HandleAddBtn, void*, EMPTYARG ) +{ + setBusy( true ); + + uno::Sequence< OUString > aFileList = raiseAddPicker(); + + if ( aFileList.getLength() ) + { + m_pManager->installPackage( aFileList[0] ); + } + + setBusy( false ); + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtMgrDialog, HandleUpdateBtn, void*, EMPTYARG ) +{ + m_pManager->checkUpdates( false, true ); + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtMgrDialog, HandleHyperlink, svt::FixedHyperlink*, pHyperlink ) +{ + openWebBrowser( pHyperlink->GetURL(), GetText() ); + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtMgrDialog, TimeOutHdl, Timer*, EMPTYARG ) +{ + if ( m_bStopProgress ) + { + m_bHasProgress = false; + m_bStopProgress = false; + m_aProgressText.Hide(); + m_aProgressBar.Hide(); + m_aCancelBtn.Hide(); + } + else + { + if ( m_bProgressChanged ) + { + m_bProgressChanged = false; + m_aProgressText.SetText( m_sProgressText ); + } + + if ( m_bStartProgress ) + { + m_bStartProgress = false; + m_bHasProgress = true; + m_aProgressBar.Show(); + m_aProgressText.Show(); + m_aCancelBtn.Enable(); + m_aCancelBtn.Show(); + } + + if ( m_aProgressBar.IsVisible() ) + m_aProgressBar.SetValue( (sal_uInt16) m_nProgress ); + + m_aTimeoutTimer.Start(); + } + + return 1; +} + +//------------------------------------------------------------------------------ +// VCL::Window / Dialog +void ExtMgrDialog::Resize() +{ + Size aTotalSize( GetOutputSizePixel() ); + Size aBtnSize( m_aHelpBtn.GetSizePixel() ); + Size aUpdBtnSize( m_aUpdateBtn.GetSizePixel() ); + + Point aPos( RSC_SP_DLG_INNERBORDER_LEFT, + aTotalSize.Height() - RSC_SP_DLG_INNERBORDER_BOTTOM - aBtnSize.Height() ); + + m_aHelpBtn.SetPosPixel( aPos ); + + aPos.X() = aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_RIGHT - aBtnSize.Width(); + m_aCloseBtn.SetPosPixel( aPos ); + + aPos.X() -= ( RSC_SP_CTRL_X + aUpdBtnSize.Width() ); + m_aUpdateBtn.SetPosPixel( aPos ); + + aPos.X() -= ( RSC_SP_CTRL_GROUP_Y + aBtnSize.Width() ); + m_aAddBtn.SetPosPixel( aPos ); + + Size aDivSize( aTotalSize.Width(), LINE_SIZE ); + aPos = Point( 0, aPos.Y() - LINE_SIZE - RSC_SP_DLG_INNERBORDER_BOTTOM ); + m_aDivider.SetPosSizePixel( aPos, aDivSize ); + + Size aFTSize( m_aGetExtensions.CalcMinimumSize() ); + aPos = Point( RSC_SP_DLG_INNERBORDER_LEFT, aPos.Y() - RSC_CD_FIXEDTEXT_HEIGHT - 2*RSC_SP_DLG_INNERBORDER_BOTTOM ); + + m_aGetExtensions.SetPosSizePixel( aPos, aFTSize ); + + aPos.X() = aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_RIGHT - aBtnSize.Width(); + m_aCancelBtn.SetPosPixel( Point( aPos.X(), aPos.Y() - ((aBtnSize.Height()-aFTSize.Height())/2) ) ); + + // Calc progress height + long nProgressHeight = aFTSize.Height(); + + if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) ) + { + ImplControlValue aValue; + Rectangle aControlRegion( Point( 0, 0 ), m_aProgressBar.GetSizePixel() ); + Rectangle aNativeControlRegion, aNativeContentRegion; + if( GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion, + CTRL_STATE_ENABLED, aValue, rtl::OUString(), + aNativeControlRegion, aNativeContentRegion ) != sal_False ) + { + nProgressHeight = aNativeControlRegion.GetHeight(); + } + } + + if ( nProgressHeight < PROGRESS_HEIGHT ) + nProgressHeight = PROGRESS_HEIGHT; + + aPos.X() -= ( RSC_SP_CTRL_GROUP_Y + PROGRESS_WIDTH ); + m_aProgressBar.SetPosSizePixel( Point( aPos.X(), aPos.Y() - ((nProgressHeight-aFTSize.Height())/2) ), + Size( PROGRESS_WIDTH, nProgressHeight ) ); + + Rectangle aRect1( m_aGetExtensions.GetPosPixel(), m_aGetExtensions.GetSizePixel() ); + Rectangle aRect2( m_aProgressBar.GetPosPixel(), m_aProgressBar.GetSizePixel() ); + + aFTSize.Width() = ( aRect2.Left() - aRect1.Right() ) - 2*RSC_SP_DLG_INNERBORDER_LEFT; + aPos.X() = aRect1.Right() + RSC_SP_DLG_INNERBORDER_LEFT; + m_aProgressText.SetPosSizePixel( aPos, aFTSize ); + + Size aSize( aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_LEFT - RSC_SP_DLG_INNERBORDER_RIGHT, + aTotalSize.Height() - 2*aBtnSize.Height() - LINE_SIZE - + RSC_SP_DLG_INNERBORDER_TOP - 3*RSC_SP_DLG_INNERBORDER_BOTTOM ); + + m_pExtensionBox->SetSizePixel( aSize ); +} +//------------------------------------------------------------------------------ +// VCL::Window / Dialog + +long ExtMgrDialog::Notify( NotifyEvent& rNEvt ) +{ + bool bHandled = false; + + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); + KeyCode aKeyCode = pKEvt->GetKeyCode(); + sal_uInt16 nKeyCode = aKeyCode.GetCode(); + + if ( nKeyCode == KEY_TAB ) + { + if ( aKeyCode.IsShift() ) { + if ( m_aAddBtn.HasFocus() ) { + m_pExtensionBox->GrabFocus(); + bHandled = true; + } + } else { + if ( m_aGetExtensions.HasFocus() ) { + m_pExtensionBox->GrabFocus(); + bHandled = true; + } + } + } + if ( aKeyCode.GetGroup() == KEYGROUP_CURSOR ) + bHandled = m_pExtensionBox->Notify( rNEvt ); + } +// VCLEVENT_WINDOW_CLOSE + if ( !bHandled ) + return ModelessDialog::Notify( rNEvt ); + else + return true; +} + +//------------------------------------------------------------------------------ +sal_Bool ExtMgrDialog::Close() +{ + bool bRet = m_pManager->queryTermination(); + if ( bRet ) + { + bRet = ModelessDialog::Close(); + m_pManager->terminateDialog(); + } + return bRet; +} + +//------------------------------------------------------------------------------ +// UpdateRequiredDialog +//------------------------------------------------------------------------------ +UpdateRequiredDialog::UpdateRequiredDialog( Window *pParent, TheExtensionManager *pManager ) : + ModalDialog( pParent, getResId( RID_DLG_UPDATE_REQUIRED ) ), + DialogHelper( pManager->getContext(), (Dialog*) this ), + m_aUpdateNeeded( this, getResId( RID_EM_FT_MSG ) ), + m_aUpdateBtn( this, getResId( RID_EM_BTN_CHECK_UPDATES ) ), + m_aCloseBtn( this, getResId( RID_EM_BTN_CLOSE ) ), + m_aHelpBtn( this, getResId( RID_EM_BTN_HELP ) ), + m_aCancelBtn( this, getResId( RID_EM_BTN_CANCEL ) ), + m_aDivider( this ), + m_aProgressText( this, getResId( RID_EM_FT_PROGRESS ) ), + m_aProgressBar( this, WB_BORDER + WB_3DLOOK ), + m_sAddPackages( getResourceString( RID_STR_ADD_PACKAGES ) ), + m_sCloseText( getResourceString( RID_STR_CLOSE_BTN ) ), + m_bHasProgress( false ), + m_bProgressChanged( false ), + m_bStartProgress( false ), + m_bStopProgress( false ), + m_bUpdateWarning( false ), + m_bDisableWarning( false ), + m_bHasLockedEntries( false ), + m_nProgress( 0 ), + m_pManager( pManager ) +{ + // free local resources (RID < 256): + FreeResource(); + + m_pExtensionBox = new ExtensionBox_Impl( this, pManager ); + m_pExtensionBox->SetHyperlinkHdl( LINK( this, UpdateRequiredDialog, HandleHyperlink ) ); + + m_aUpdateBtn.SetClickHdl( LINK( this, UpdateRequiredDialog, HandleUpdateBtn ) ); + m_aCloseBtn.SetClickHdl( LINK( this, UpdateRequiredDialog, HandleCloseBtn ) ); + m_aCancelBtn.SetClickHdl( LINK( this, UpdateRequiredDialog, HandleCancelBtn ) ); + + String aText = m_aUpdateNeeded.GetText(); + aText.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() ); + m_aUpdateNeeded.SetText( aText ); + + // resize update button + Size aBtnSize = m_aUpdateBtn.GetSizePixel(); + String sTitle = m_aUpdateBtn.GetText(); + long nWidth = m_aUpdateBtn.GetCtrlTextWidth( sTitle ); + nWidth += 2 * m_aUpdateBtn.GetTextHeight(); + if ( nWidth > aBtnSize.Width() ) + m_aUpdateBtn.SetSizePixel( Size( nWidth, aBtnSize.Height() ) ); + + // resize update button + aBtnSize = m_aCloseBtn.GetSizePixel(); + sTitle = m_aCloseBtn.GetText(); + nWidth = m_aCloseBtn.GetCtrlTextWidth( sTitle ); + nWidth += 2 * m_aCloseBtn.GetTextHeight(); + if ( nWidth > aBtnSize.Width() ) + m_aCloseBtn.SetSizePixel( Size( nWidth, aBtnSize.Height() ) ); + + // minimum size: + SetMinOutputSizePixel( + Size( // width: + (5 * m_aHelpBtn.GetSizePixel().Width()) + + (5 * RSC_SP_DLG_INNERBORDER_LEFT ), + // height: + (1 * m_aHelpBtn.GetSizePixel().Height()) + + (1 * m_aUpdateNeeded.GetSizePixel().Height()) + + (1 * m_pExtensionBox->GetMinOutputSizePixel().Height()) + + (3 * RSC_SP_DLG_INNERBORDER_LEFT) ) ); + + m_aDivider.Show(); + m_aProgressBar.Hide(); + m_aUpdateBtn.Enable( false ); + m_aCloseBtn.GrabFocus(); + + m_aTimeoutTimer.SetTimeout( 50 ); // mSec + m_aTimeoutTimer.SetTimeoutHdl( LINK( this, UpdateRequiredDialog, TimeOutHdl ) ); +} + +//------------------------------------------------------------------------------ +UpdateRequiredDialog::~UpdateRequiredDialog() +{ + m_aTimeoutTimer.Stop(); + + delete m_pExtensionBox; +} + +//------------------------------------------------------------------------------ +long UpdateRequiredDialog::addPackageToList( const uno::Reference< deployment::XPackage > &xPackage, + bool bLicenseMissing ) +{ + // We will only add entries to the list with unsatisfied dependencies + if ( !bLicenseMissing && !checkDependencies( xPackage ) ) + { + m_bHasLockedEntries |= m_pManager->isReadOnly( xPackage ); + const SolarMutexGuard aGuard; + m_aUpdateBtn.Enable( true ); + return m_pExtensionBox->addEntry( xPackage ); + } + return 0; +} + +//------------------------------------------------------------------------------ +void UpdateRequiredDialog::prepareChecking() +{ + m_pExtensionBox->prepareChecking(); +} + +//------------------------------------------------------------------------------ +void UpdateRequiredDialog::checkEntries() +{ + const SolarMutexGuard guard; + m_pExtensionBox->checkEntries(); + + if ( ! hasActiveEntries() ) + { + m_aCloseBtn.SetText( m_sCloseText ); + m_aCloseBtn.GrabFocus(); + } +} + +//------------------------------------------------------------------------------ +bool UpdateRequiredDialog::enablePackage( const uno::Reference< deployment::XPackage > &xPackage, + bool bEnable ) +{ + m_pManager->getCmdQueue()->enableExtension( xPackage, bEnable ); + + return true; +} + +//------------------------------------------------------------------------------ +IMPL_LINK( UpdateRequiredDialog, HandleCancelBtn, void*, EMPTYARG ) +{ + if ( m_xAbortChannel.is() ) + { + try + { + m_xAbortChannel->sendAbort(); + } + catch ( uno::RuntimeException & ) + { + OSL_FAIL( "### unexpected RuntimeException!" ); + } + } + return 1; +} + +// ------------------------------------------------------------------------------ +IMPL_LINK( UpdateRequiredDialog, startProgress, void*, _bLockInterface ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + bool bLockInterface = (bool) _bLockInterface; + + if ( m_bStartProgress && !m_bHasProgress ) + m_aTimeoutTimer.Start(); + + if ( m_bStopProgress ) + { + if ( m_aProgressBar.IsVisible() ) + m_aProgressBar.SetValue( 100 ); + m_xAbortChannel.clear(); + OSL_TRACE( " startProgress handler: stop\n" ); + } + else + { + OSL_TRACE( " startProgress handler: start\n" ); + } + + m_aCancelBtn.Enable( bLockInterface ); + m_aUpdateBtn.Enable( false ); + clearEventID(); + + return 0; +} + +// ------------------------------------------------------------------------------ +void UpdateRequiredDialog::showProgress( bool _bStart ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + bool bStart = _bStart; + + if ( bStart ) + { + m_nProgress = 0; + m_bStartProgress = true; + OSL_TRACE( "showProgress start\n" ); + } + else + { + m_nProgress = 100; + m_bStopProgress = true; + OSL_TRACE( "showProgress stop!\n" ); + } + + DialogHelper::PostUserEvent( LINK( this, UpdateRequiredDialog, startProgress ), (void*) bStart ); +} + +// ----------------------------------------------------------------------- +void UpdateRequiredDialog::updateProgress( const long nProgress ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_nProgress = nProgress; +} + +// ----------------------------------------------------------------------- +void UpdateRequiredDialog::updateProgress( const OUString &rText, + const uno::Reference< task::XAbortChannel > &xAbortChannel) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xAbortChannel = xAbortChannel; + m_sProgressText = rText; + m_bProgressChanged = true; +} + +//------------------------------------------------------------------------------ +void UpdateRequiredDialog::updatePackageInfo( const uno::Reference< deployment::XPackage > &xPackage ) +{ + // We will remove all updated packages with satisfied dependencies, but + // we will show all disabled entries so the user sees the result + // of the 'disable all' button + const SolarMutexGuard aGuard; + if ( isEnabled( xPackage ) && checkDependencies( xPackage ) ) + m_pExtensionBox->removeEntry( xPackage ); + else + m_pExtensionBox->updateEntry( xPackage ); + + if ( ! hasActiveEntries() ) + { + m_aCloseBtn.SetText( m_sCloseText ); + m_aCloseBtn.GrabFocus(); + } +} + +// ----------------------------------------------------------------------- +IMPL_LINK( UpdateRequiredDialog, HandleUpdateBtn, void*, EMPTYARG ) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + std::vector< uno::Reference< deployment::XPackage > > vUpdateEntries; + sal_Int32 nCount = m_pExtensionBox->GetEntryCount(); + + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + TEntry_Impl pEntry = m_pExtensionBox->GetEntryData( i ); + vUpdateEntries.push_back( pEntry->m_xPackage ); + } + + aGuard.clear(); + + m_pManager->getCmdQueue()->checkForUpdates( vUpdateEntries ); + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( UpdateRequiredDialog, HandleCloseBtn, void*, EMPTYARG ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !isBusy() ) + { + if ( m_bHasLockedEntries ) + EndDialog( -1 ); + else if ( hasActiveEntries() ) + disableAllEntries(); + else + EndDialog( 0 ); + } + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( UpdateRequiredDialog, HandleHyperlink, svt::FixedHyperlink*, pHyperlink ) +{ + openWebBrowser( pHyperlink->GetURL(), GetText() ); + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( UpdateRequiredDialog, TimeOutHdl, Timer*, EMPTYARG ) +{ + if ( m_bStopProgress ) + { + m_bHasProgress = false; + m_bStopProgress = false; + m_aProgressText.Hide(); + m_aProgressBar.Hide(); + m_aCancelBtn.Hide(); + } + else + { + if ( m_bProgressChanged ) + { + m_bProgressChanged = false; + m_aProgressText.SetText( m_sProgressText ); + } + + if ( m_bStartProgress ) + { + m_bStartProgress = false; + m_bHasProgress = true; + m_aProgressBar.Show(); + m_aProgressText.Show(); + m_aCancelBtn.Enable(); + m_aCancelBtn.Show(); + } + + if ( m_aProgressBar.IsVisible() ) + m_aProgressBar.SetValue( (sal_uInt16) m_nProgress ); + + m_aTimeoutTimer.Start(); + } + + return 1; +} + +//------------------------------------------------------------------------------ +// VCL::Window / Dialog +void UpdateRequiredDialog::Resize() +{ + Size aTotalSize( GetOutputSizePixel() ); + Size aBtnSize( m_aHelpBtn.GetSizePixel() ); + + Point aPos( RSC_SP_DLG_INNERBORDER_LEFT, + aTotalSize.Height() - RSC_SP_DLG_INNERBORDER_BOTTOM - aBtnSize.Height() ); + + m_aHelpBtn.SetPosPixel( aPos ); + + aPos.X() = aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_RIGHT - m_aCloseBtn.GetSizePixel().Width(); + m_aCloseBtn.SetPosPixel( aPos ); + + aPos.X() -= ( RSC_SP_CTRL_X + m_aUpdateBtn.GetSizePixel().Width() ); + m_aUpdateBtn.SetPosPixel( aPos ); + + Size aDivSize( aTotalSize.Width(), LINE_SIZE ); + aPos = Point( 0, aPos.Y() - LINE_SIZE - RSC_SP_DLG_INNERBORDER_BOTTOM ); + m_aDivider.SetPosSizePixel( aPos, aDivSize ); + + // Calc fixed text size + aPos = Point( RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP ); + Size aFTSize = m_aUpdateNeeded.CalcMinimumSize( aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_RIGHT - RSC_SP_DLG_INNERBORDER_LEFT ); + m_aUpdateNeeded.SetPosSizePixel( aPos, aFTSize ); + + // Calc list box size + Size aSize( aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_LEFT - RSC_SP_DLG_INNERBORDER_RIGHT, + aTotalSize.Height() - 2*aBtnSize.Height() - LINE_SIZE - + 2*RSC_SP_DLG_INNERBORDER_TOP - 3*RSC_SP_DLG_INNERBORDER_BOTTOM - aFTSize.Height() ); + aPos.Y() += aFTSize.Height()+RSC_SP_DLG_INNERBORDER_TOP; + + m_pExtensionBox->SetPosSizePixel( aPos, aSize ); + + aPos.X() = aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_RIGHT - aBtnSize.Width(); + aPos.Y() += aSize.Height()+RSC_SP_DLG_INNERBORDER_TOP; + m_aCancelBtn.SetPosPixel( aPos ); + + // Calc progress height + aFTSize = m_aProgressText.GetSizePixel(); + long nProgressHeight = aFTSize.Height(); + + if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) ) + { + ImplControlValue aValue; + Rectangle aControlRegion( Point( 0, 0 ), m_aProgressBar.GetSizePixel() ); + Rectangle aNativeControlRegion, aNativeContentRegion; + if( GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion, + CTRL_STATE_ENABLED, aValue, rtl::OUString(), + aNativeControlRegion, aNativeContentRegion ) != sal_False ) + { + nProgressHeight = aNativeControlRegion.GetHeight(); + } + } + + if ( nProgressHeight < PROGRESS_HEIGHT ) + nProgressHeight = PROGRESS_HEIGHT; + + aPos.X() -= ( RSC_SP_CTRL_GROUP_Y + PROGRESS_WIDTH ); + m_aProgressBar.SetPosSizePixel( Point( aPos.X(), aPos.Y() + ((aBtnSize.Height()-nProgressHeight)/2) ), + Size( PROGRESS_WIDTH, nProgressHeight ) ); + + aFTSize.Width() = aPos.X() - 2*RSC_SP_DLG_INNERBORDER_LEFT; + aPos.X() = RSC_SP_DLG_INNERBORDER_LEFT; + aPos.Y() += ( aBtnSize.Height() - aFTSize.Height() - 1 ) / 2; + m_aProgressText.SetPosSizePixel( aPos, aFTSize ); +} + +//------------------------------------------------------------------------------ +// VCL::Dialog +short UpdateRequiredDialog::Execute() +{ + if ( m_bHasLockedEntries ) + { + // Set other text, disable update btn, remove not shared entries from list; + m_aUpdateNeeded.SetText( DialogHelper::getResourceString( RID_STR_NO_ADMIN_PRIVILEGE ) ); + m_aCloseBtn.SetText( DialogHelper::getResourceString( RID_STR_EXIT_BTN ) ); + m_aUpdateBtn.Enable( false ); + m_pExtensionBox->RemoveUnlocked(); + Resize(); + } + + return Dialog::Execute(); +} + +//------------------------------------------------------------------------------ +// VCL::Dialog +sal_Bool UpdateRequiredDialog::Close() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !isBusy() ) + { + if ( m_bHasLockedEntries ) + EndDialog( -1 ); + else if ( hasActiveEntries() ) + disableAllEntries(); + else + EndDialog( 0 ); + } + + return false; +} + +//------------------------------------------------------------------------------ +// Check dependencies of all packages +//------------------------------------------------------------------------------ +bool UpdateRequiredDialog::isEnabled( const uno::Reference< deployment::XPackage > &xPackage ) const +{ + bool bRegistered = false; + try { + beans::Optional< beans::Ambiguous< sal_Bool > > option( xPackage->isRegistered( uno::Reference< task::XAbortChannel >(), + uno::Reference< ucb::XCommandEnvironment >() ) ); + if ( option.IsPresent ) + { + ::beans::Ambiguous< sal_Bool > const & reg = option.Value; + if ( reg.IsAmbiguous ) + bRegistered = false; + else + bRegistered = reg.Value ? true : false; + } + else + bRegistered = false; + } + catch ( uno::RuntimeException & ) { throw; } + catch ( uno::Exception & exc) { + (void) exc; + OSL_FAIL( ::rtl::OUStringToOString( exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + bRegistered = false; + } + + return bRegistered; +} + +//------------------------------------------------------------------------------ +bool UpdateRequiredDialog::checkDependencies( const uno::Reference< deployment::XPackage > &xPackage ) const +{ + if ( isEnabled( xPackage ) ) + { + bool bDependenciesValid = false; + try { + bDependenciesValid = xPackage->checkDependencies( uno::Reference< ucb::XCommandEnvironment >() ); + } + catch ( deployment::DeploymentException & ) {} + if ( ! bDependenciesValid ) + { + return false; + } + } + return true; +} + +//------------------------------------------------------------------------------ +bool UpdateRequiredDialog::hasActiveEntries() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + bool bRet = false; + long nCount = m_pExtensionBox->GetEntryCount(); + for ( long nIndex = 0; nIndex < nCount; nIndex++ ) + { + TEntry_Impl pEntry = m_pExtensionBox->GetEntryData( nIndex ); + + if ( !checkDependencies( pEntry->m_xPackage ) ) + { + bRet = true; + break; + } + } + + return bRet; +} + +//------------------------------------------------------------------------------ +void UpdateRequiredDialog::disableAllEntries() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + setBusy( true ); + + long nCount = m_pExtensionBox->GetEntryCount(); + for ( long nIndex = 0; nIndex < nCount; nIndex++ ) + { + TEntry_Impl pEntry = m_pExtensionBox->GetEntryData( nIndex ); + enablePackage( pEntry->m_xPackage, false ); + } + + setBusy( false ); + + if ( ! hasActiveEntries() ) + m_aCloseBtn.SetText( m_sCloseText ); +} + +//------------------------------------------------------------------------------ +// ShowLicenseDialog +//------------------------------------------------------------------------------ +ShowLicenseDialog::ShowLicenseDialog( Window * pParent, + const uno::Reference< deployment::XPackage > &xPackage ) : + ModalDialog( pParent, DialogHelper::getResId( RID_DLG_SHOW_LICENSE ) ), + m_aLicenseText( this, DialogHelper::getResId( ML_LICENSE ) ), + m_aCloseBtn( this, DialogHelper::getResId( RID_EM_BTN_CLOSE ) ) +{ + FreeResource(); + + OUString aText = xPackage->getLicenseText(); + m_aLicenseText.SetText( aText ); +} + +//------------------------------------------------------------------------------ +ShowLicenseDialog::~ShowLicenseDialog() +{} + +//------------------------------------------------------------------------------ +void ShowLicenseDialog::Resize() +{ + Size aTotalSize( GetOutputSizePixel() ); + Size aTextSize( aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_LEFT - RSC_SP_DLG_INNERBORDER_RIGHT, + aTotalSize.Height() - RSC_SP_DLG_INNERBORDER_TOP - 2*RSC_SP_DLG_INNERBORDER_BOTTOM + - m_aCloseBtn.GetSizePixel().Height() ); + + m_aLicenseText.SetPosSizePixel( Point( RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP ), + aTextSize ); + + Point aBtnPos( (aTotalSize.Width() - m_aCloseBtn.GetSizePixel().Width())/2, + aTotalSize.Height() - RSC_SP_DLG_INNERBORDER_BOTTOM + - m_aCloseBtn.GetSizePixel().Height() ); + m_aCloseBtn.SetPosPixel( aBtnPos ); +} + +//================================================================================= +// UpdateRequiredDialogService +//================================================================================= +UpdateRequiredDialogService::UpdateRequiredDialogService( uno::Sequence< uno::Any > const&, + uno::Reference< uno::XComponentContext > const& xComponentContext ) + : m_xComponentContext( xComponentContext ) +{ +} + +//------------------------------------------------------------------------------ +// XExecutableDialog +//------------------------------------------------------------------------------ +void UpdateRequiredDialogService::setTitle( OUString const & ) throw ( uno::RuntimeException ) +{ +} + +//------------------------------------------------------------------------------ +sal_Int16 UpdateRequiredDialogService::execute() throw ( uno::RuntimeException ) +{ + ::rtl::Reference< ::dp_gui::TheExtensionManager > xManager( TheExtensionManager::get( + m_xComponentContext, + uno::Reference< awt::XWindow >(), + OUString() ) ); + xManager->createDialog( true ); + sal_Int16 nRet = xManager->execute(); + + return nRet; +} + +//------------------------------------------------------------------------------ +SelectedPackage::~SelectedPackage() {} + +} //namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.hxx b/desktop/source/deployment/gui/dp_gui_dialog2.hxx new file mode 100644 index 000000000000..8288d27b5e6f --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dialog2.hxx @@ -0,0 +1,283 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DP_GUI_DIALOG2_HXX +#define INCLUDED_DP_GUI_DIALOG2_HXX + +#include "vcl/dialog.hxx" +#include "vcl/button.hxx" +#include "vcl/fixed.hxx" +#include "vcl/timer.hxx" + +#include "svtools/fixedhyper.hxx" +#include "svtools/prgsbar.hxx" +#include "svtools/svmedit.hxx" + +#include "osl/conditn.hxx" +#include "osl/mutex.hxx" + +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" + +#include "cppuhelper/implbase1.hxx" + +#include "com/sun/star/awt/XWindow.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" +#include "com/sun/star/util/XModifyListener.hpp" + +namespace dp_gui { + +//============================================================================== +class ExtBoxWithBtns_Impl; +class ExtensionBox_Impl; +class TheExtensionManager; + +//============================================================================== +class DialogHelper +{ + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + Dialog* m_pVCLWindow; + sal_uLong m_nEventID; + bool m_bIsBusy; + +public: + DialogHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > &, + Dialog *pWindow ); + virtual ~DialogHelper(); + + void openWebBrowser( const ::rtl::OUString & sURL, const ::rtl::OUString & sTitle ) const; + Dialog* getWindow() const { return m_pVCLWindow; }; + void PostUserEvent( const Link& rLink, void* pCaller ); + void clearEventID() { m_nEventID = 0; } + + virtual void showProgress( bool bStart ) = 0; + virtual void updateProgress( const ::rtl::OUString &rText, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > &xAbortChannel) = 0; + virtual void updateProgress( const long nProgress ) = 0; + + virtual void updatePackageInfo( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) = 0; + virtual long addPackageToList( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, + bool bLicenseMissing = false ) = 0; + + virtual void prepareChecking() = 0; + virtual void checkEntries() = 0; + + static ResId getResId( sal_uInt16 nId ); + static String getResourceString( sal_uInt16 id ); + static bool IsSharedPkgMgr( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &); + static bool continueOnSharedExtension( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &, + Window *pParent, + const sal_uInt16 nResID, + bool &bHadWarning ); + + void setBusy( const bool bBusy ) { m_bIsBusy = bBusy; } + bool isBusy() const { return m_bIsBusy; } + bool installExtensionWarn( const ::rtl::OUString &rExtensionURL ) const; + bool installForAllUsers( bool &bInstallForAll ) const; +}; + +//============================================================================== +class ExtMgrDialog : public ModelessDialog, + public DialogHelper +{ + ExtBoxWithBtns_Impl *m_pExtensionBox; + PushButton m_aAddBtn; + PushButton m_aUpdateBtn; + OKButton m_aCloseBtn; + HelpButton m_aHelpBtn; + FixedLine m_aDivider; + svt::FixedHyperlink m_aGetExtensions; + FixedText m_aProgressText; + ProgressBar m_aProgressBar; + CancelButton m_aCancelBtn; + const String m_sAddPackages; + String m_sProgressText; + String m_sLastFolderURL; + ::osl::Mutex m_aMutex; + bool m_bHasProgress; + bool m_bProgressChanged; + bool m_bStartProgress; + bool m_bStopProgress; + bool m_bUpdateWarning; + bool m_bEnableWarning; + bool m_bDisableWarning; + bool m_bDeleteWarning; + long m_nProgress; + Timer m_aTimeoutTimer; + TheExtensionManager *m_pManager; + + ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > m_xAbortChannel; + + bool removeExtensionWarn( const ::rtl::OUString &rExtensionTitle ) const; + + DECL_DLLPRIVATE_LINK( HandleAddBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleUpdateBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleCancelBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleHyperlink, svt::FixedHyperlink * ); + DECL_DLLPRIVATE_LINK( TimeOutHdl, Timer* ); + DECL_DLLPRIVATE_LINK( startProgress, void * ); + +public: + ExtMgrDialog( Window * pParent, TheExtensionManager *pManager ); + virtual ~ExtMgrDialog(); + + virtual void Resize(); + virtual long Notify( NotifyEvent& rNEvt ); + virtual sal_Bool Close(); + + virtual void showProgress( bool bStart ); + virtual void updateProgress( const ::rtl::OUString &rText, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > &xAbortChannel); + virtual void updateProgress( const long nProgress ); + + virtual void updatePackageInfo( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + + void setGetExtensionsURL( const ::rtl::OUString &rURL ); + virtual long addPackageToList( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &, + bool bLicenseMissing = false ); + bool enablePackage(const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, + bool bEnable ); + bool removePackage(const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + bool updatePackage(const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + bool acceptLicense(const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + + virtual void prepareChecking(); + virtual void checkEntries(); + + ::com::sun::star::uno::Sequence< ::rtl::OUString > raiseAddPicker(); +}; + +//============================================================================== +class UpdateRequiredDialog : public ModalDialog, + public DialogHelper +{ + ExtensionBox_Impl *m_pExtensionBox; + FixedText m_aUpdateNeeded; + PushButton m_aUpdateBtn; + PushButton m_aCloseBtn; + HelpButton m_aHelpBtn; + CancelButton m_aCancelBtn; + FixedLine m_aDivider; + FixedText m_aProgressText; + ProgressBar m_aProgressBar; + const String m_sAddPackages; + const String m_sCloseText; + String m_sProgressText; + ::osl::Mutex m_aMutex; + bool m_bHasProgress; + bool m_bProgressChanged; + bool m_bStartProgress; + bool m_bStopProgress; + bool m_bUpdateWarning; + bool m_bDisableWarning; + bool m_bHasLockedEntries; + long m_nProgress; + Timer m_aTimeoutTimer; + TheExtensionManager *m_pManager; + + ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > m_xAbortChannel; + + DECL_DLLPRIVATE_LINK( HandleUpdateBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleCloseBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleCancelBtn, void * ); + DECL_DLLPRIVATE_LINK( TimeOutHdl, Timer* ); + DECL_DLLPRIVATE_LINK( startProgress, void * ); + DECL_DLLPRIVATE_LINK( HandleHyperlink, svt::FixedHyperlink * ); + + bool isEnabled( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + bool checkDependencies( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + bool hasActiveEntries(); + void disableAllEntries(); + +public: + UpdateRequiredDialog( Window * pParent, TheExtensionManager *pManager ); + virtual ~UpdateRequiredDialog(); + + virtual short Execute(); + virtual void Resize(); + virtual sal_Bool Close(); + + virtual void showProgress( bool bStart ); + virtual void updateProgress( const ::rtl::OUString &rText, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > &xAbortChannel); + virtual void updateProgress( const long nProgress ); + + virtual void updatePackageInfo( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + + void selectEntry( long nPos ); + virtual long addPackageToList( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &, + bool bLicenseMissing = false ); + bool enablePackage( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, bool bEnable ); + bool updatePackage( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + + virtual void prepareChecking(); + virtual void checkEntries(); + + ::com::sun::star::uno::Sequence< ::rtl::OUString > raiseAddPicker(); + + bool installForAllUsers( bool &bInstallForAll ) const; + bool installExtensionWarn( const ::rtl::OUString &rExtensionURL ) const; +}; + +//============================================================================== +class ShowLicenseDialog : public ModalDialog +{ + MultiLineEdit m_aLicenseText; + OKButton m_aCloseBtn; + +public: + ShowLicenseDialog( Window * pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + virtual ~ShowLicenseDialog(); + + virtual void Resize(); +}; + +//============================================================================== +class UpdateRequiredDialogService : public ::cppu::WeakImplHelper1< ::com::sun::star::ui::dialogs::XExecutableDialog > +{ + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const m_xComponentContext; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > m_xParent; + ::rtl::OUString m_sInitialTitle; + +public: + UpdateRequiredDialogService( ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > const & args, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> const & xComponentContext ); + + // XExecutableDialog + virtual void SAL_CALL setTitle( rtl::OUString const & title ) throw ( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int16 SAL_CALL execute() throw ( ::com::sun::star::uno::RuntimeException ); +}; + +} // namespace dp_gui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.src b/desktop/source/deployment/gui/dp_gui_dialog2.src new file mode 100644 index 000000000000..2d11f1175e88 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dialog2.src @@ -0,0 +1,236 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "svtools/controldims.hrc" +#include "dp_gui.hrc" + +ModelessDialog RID_DLG_EXTENSION_MANAGER +{ + HelpId = HID_PACKAGE_MANAGER; + Text [ en-US ] = "Extension Manager"; + + Size = MAP_APPFONT( 300, 200 ); + OutputSize = TRUE; + SVLook = TRUE; + Moveable = TRUE; + Closeable = TRUE; + Sizeable = TRUE; + Hide = TRUE; + + PushButton RID_EM_BTN_ADD + { + HelpID = "desktop:PushButton:RID_DLG_EXTENSION_MANAGER:RID_EM_BTN_ADD"; + TabStop = TRUE; + Text [ en-US ] = "~Add..."; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + PushButton RID_EM_BTN_CHECK_UPDATES + { + HelpID = "desktop:PushButton:RID_DLG_EXTENSION_MANAGER:RID_EM_BTN_CHECK_UPDATES"; + TabStop = TRUE; + Text [ en-US ] = "Check for ~Updates..."; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + FixedText RID_EM_FT_GET_EXTENSIONS + { + NoLabel = TRUE; + TabStop = TRUE; + Text [ en-US ] = "Get more extensions online..."; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT ); + }; + + FixedText RID_EM_FT_PROGRESS + { + Hide = TRUE; + Right = TRUE; + Text [ en-US ] = "Adding %EXTENSION_NAME"; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT ); + }; + + CancelButton RID_EM_BTN_CANCEL + { + TabStop = TRUE; + Hide = TRUE; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + OKButton RID_EM_BTN_CLOSE + { + TabStop = TRUE; + DefButton = TRUE; + Text [ en-US ] = "Close"; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + HelpButton RID_EM_BTN_HELP + { + TabStop = TRUE; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; +}; + +ModalDialog RID_DLG_UPDATE_REQUIRED +{ + HelpId = HID_PACKAGE_MANAGER_UPD_REQ; + Text [ en-US ] = "Extension Update Required"; + + Size = MAP_APPFONT( 300, 200 ); + OutputSize = TRUE; + SVLook = TRUE; + Moveable = TRUE; + Closeable = TRUE; + Sizeable = TRUE; + Hide = TRUE; + + FixedText RID_EM_FT_MSG + { + Text [ en-US ] = "%PRODUCTNAME has been updated to a new version. Some installed %PRODUCTNAME extensions are not compatible with this version and need to be updated before they can be used."; + WordBreak = TRUE; + NoLabel = TRUE; + Size = MAP_APPFONT( 280, 3*RSC_BS_CHARHEIGHT ); + Pos = MAP_APPFONT( 5, 5 ); + }; + + FixedText RID_EM_FT_PROGRESS + { + Hide = TRUE; + Right = TRUE; + Text [ en-US ] = "Adding %EXTENSION_NAME"; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT ); + }; + + HelpButton RID_EM_BTN_HELP + { + TabStop = TRUE; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + PushButton RID_EM_BTN_CHECK_UPDATES + { + HelpID = "desktop:PushButton:RID_DLG_UPDATE_REQUIRED:RID_EM_BTN_CHECK_UPDATES"; + TabStop = TRUE; + Text [ en-US ] = "Check for ~Updates..."; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + PushButton RID_EM_BTN_CLOSE + { + HelpID = "desktop:PushButton:RID_DLG_UPDATE_REQUIRED:RID_EM_BTN_CLOSE"; + TabStop = TRUE; + DefButton = TRUE; + Text [ en-US ] = "Disable all"; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + CancelButton RID_EM_BTN_CANCEL + { + TabStop = TRUE; + Hide = TRUE; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + +}; + +Image RID_IMG_WARNING +{ + ImageBitmap = Bitmap { File = "caution_16.png"; }; +}; + +Image RID_IMG_LOCKED +{ + ImageBitmap = Bitmap { File = "lock_16.png"; }; +}; + +Image RID_IMG_SHARED +{ + ImageBitmap = Bitmap { File = "shared_16.png"; }; +}; + +Image RID_IMG_EXTENSION +{ + ImageBitmap = Bitmap { File = "extension_32.png"; }; +}; + +QueryBox RID_QUERYBOX_INSTALL_FOR_ALL +{ + Buttons = WB_YES_NO_CANCEL; + DefButton = WB_DEF_YES; + Message[en-US] = "Make sure that no further users are working with the same %PRODUCTNAME, when installing an extension for all users in a multi user environment.\n\nFor whom do you want to install the extension?\n"; +}; + + +// Dialog layout +// --------------------------------------------------- +// row 1 | multi line edit +// --------------------------------------------------- +// row 2 | fixed text +// --------------------------------------------------- +// row 3 | img | fixed text | fixed text | button +// ---------------------------------------------------- +// row 4 | img | fixed text | fixed text +// --------------------------------------------------- +// row 5 |fixed line +// --------------------------------------------------- +// row 6 | | |button | button +// --------------------------------------------------- +// | col 1 | col 2 | col3 | col4 | col5 + +//To change the overall size of the multi line edit change +//ROW1_HEIGHT and COL3_WIDTH + +#define ROW1_Y RSC_SP_DLG_INNERBORDER_TOP +#define ROW1_HEIGHT 16*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW2_Y ROW1_Y+ROW1_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW2_HEIGHT 2*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW3_Y ROW2_Y+ROW2_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW3_HEIGHT 3*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW4_Y ROW3_Y+ROW3_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW4_HEIGHT 3*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW5_Y ROW4_Y+ROW4_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW5_HEIGHT RSC_CD_FIXEDTEXT_HEIGHT +#define ROW6_Y ROW5_Y+ROW5_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW6_HEIGHT RSC_CD_PUSHBUTTON_HEIGHT + +#define LIC_DLG_HEIGHT ROW6_Y+ROW6_HEIGHT+RSC_SP_DLG_INNERBORDER_BOTTOM + +#define COL1_X RSC_SP_DLG_INNERBORDER_LEFT +#define IMG_ARROW_WIDTH 16 +#define COL1_WIDTH IMG_ARROW_WIDTH +#define COL2_X COL1_X+COL1_WIDTH +#define COL2_WIDTH 10 +#define COL3_X COL2_X+COL2_WIDTH+RSC_SP_CTRL_GROUP_X +#define COL3_WIDTH 150 +#define COL4_X COL3_X+COL3_WIDTH +#define COL4_WIDTH RSC_CD_PUSHBUTTON_WIDTH+RSC_SP_CTRL_GROUP_X +#define COL5_X COL4_X+COL4_WIDTH + +#define LIC_DLG_WIDTH COL5_X+RSC_CD_PUSHBUTTON_WIDTH+RSC_SP_DLG_INNERBORDER_RIGHT +#define BODYWIDTH LIC_DLG_WIDTH-RSC_SP_DLG_INNERBORDER_LEFT-RSC_SP_DLG_INNERBORDER_RIGHT + + diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx new file mode 100644 index 000000000000..7c75f9dee4c2 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx @@ -0,0 +1,1155 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#define _WIN32_WINNT 0x0500 + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + + + + +#include "sal/config.h" + +#include <cstddef> + +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/beans/NamedValue.hpp" + +#include "com/sun/star/deployment/DependencyException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/deployment/PlatformException.hpp" + +#include "com/sun/star/deployment/ui/LicenseDialog.hpp" +#include "com/sun/star/deployment/DeploymentException.hpp" +#include "com/sun/star/deployment/UpdateInformationProvider.hpp" +#include "com/sun/star/deployment/XPackage.hpp" + +#include "com/sun/star/task/XAbortChannel.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" + +#include "com/sun/star/ucb/CommandAbortedException.hpp" +#include "com/sun/star/ucb/CommandFailedException.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" + +#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uno/TypeClass.hpp" +#include "osl/diagnose.h" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "ucbhelper/content.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase3.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/string.hxx" +#include "vcl/msgbox.hxx" +#include "toolkit/helper/vclunohelper.hxx" +#include "comphelper/processfactory.hxx" + +#include "dp_gui.h" +#include "dp_gui_thread.hxx" +#include "dp_gui_extensioncmdqueue.hxx" +#include "dp_gui_dependencydialog.hxx" +#include "dp_gui_dialog2.hxx" +#include "dp_gui_shared.hxx" +#include "dp_gui_theextmgr.hxx" +#include "dp_gui_updatedialog.hxx" +#include "dp_gui_updateinstalldialog.hxx" +#include "dp_dependencies.hxx" +#include "dp_identifier.hxx" +#include "dp_version.hxx" + +#include <queue> +#include <boost/shared_ptr.hpp> + +#if (defined(_MSC_VER) && (_MSC_VER < 1400)) +#define _WIN32_WINNT 0x0400 +#endif + +#ifdef WNT +#define GradientStyle_RECT BLA_GradientStyle_RECT +#include <windows.h> +#include <objbase.h> +#undef GradientStyle_RECT +#endif + + +using namespace ::com::sun::star; +using ::rtl::OUString; + +namespace { + +OUString getVersion( OUString const & sVersion ) +{ + return ( sVersion.getLength() == 0 ) ? OUString( RTL_CONSTASCII_USTRINGPARAM( "0" ) ) : sVersion; +} + +OUString getVersion( const uno::Reference< deployment::XPackage > &rPackage ) +{ + return getVersion( rPackage->getVersion()); +} +} + + +namespace dp_gui { + +//============================================================================== + +class ProgressCmdEnv + : public ::cppu::WeakImplHelper3< ucb::XCommandEnvironment, + task::XInteractionHandler, + ucb::XProgressHandler > +{ + uno::Reference< task::XInteractionHandler> m_xHandler; + uno::Reference< uno::XComponentContext > m_xContext; + uno::Reference< task::XAbortChannel> m_xAbortChannel; + + DialogHelper *m_pDialogHelper; + OUString m_sTitle; + bool m_bAborted; + bool m_bWarnUser; + sal_Int32 m_nCurrentProgress; + + void updateProgress(); + + void update_( uno::Any const & Status ) throw ( uno::RuntimeException ); + +public: + virtual ~ProgressCmdEnv(); + + /** When param bAskWhenInstalling = true, then the user is asked if he + agrees to install this extension. In case this extension is already installed + then the user is also notified and asked if he wants to replace that existing + extension. In first case an interaction request with an InstallException + will be handled and in the second case a VersionException will be handled. + */ + + ProgressCmdEnv( const uno::Reference< uno::XComponentContext > rContext, + DialogHelper *pDialogHelper, + const OUString &rTitle ) + : m_xContext( rContext ), + m_pDialogHelper( pDialogHelper ), + m_sTitle( rTitle ), + m_bAborted( false ), + m_bWarnUser( false ) + {} + + Dialog * activeDialog() { return m_pDialogHelper ? m_pDialogHelper->getWindow() : NULL; } + + void setTitle( const OUString& rNewTitle ) { m_sTitle = rNewTitle; } + void startProgress(); + void stopProgress(); + void progressSection( const OUString &rText, + const uno::Reference< task::XAbortChannel > &xAbortChannel = 0 ); + inline bool isAborted() const { return m_bAborted; } + inline void setWarnUser( bool bNewVal ) { m_bWarnUser = bNewVal; } + + // XCommandEnvironment + virtual uno::Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler() + throw ( uno::RuntimeException ); + virtual uno::Reference< ucb::XProgressHandler > SAL_CALL getProgressHandler() + throw ( uno::RuntimeException ); + + // XInteractionHandler + virtual void SAL_CALL handle( uno::Reference< task::XInteractionRequest > const & xRequest ) + throw ( uno::RuntimeException ); + + // XProgressHandler + virtual void SAL_CALL push( uno::Any const & Status ) + throw ( uno::RuntimeException ); + virtual void SAL_CALL update( uno::Any const & Status ) + throw ( uno::RuntimeException ); + virtual void SAL_CALL pop() throw ( uno::RuntimeException ); +}; + +//------------------------------------------------------------------------------ +struct ExtensionCmd +{ + enum E_CMD_TYPE { ADD, ENABLE, DISABLE, REMOVE, CHECK_FOR_UPDATES, ACCEPT_LICENSE }; + + E_CMD_TYPE m_eCmdType; + bool m_bWarnUser; + OUString m_sExtensionURL; + OUString m_sRepository; + uno::Reference< deployment::XPackage > m_xPackage; + std::vector< uno::Reference< deployment::XPackage > > m_vExtensionList; + + ExtensionCmd( const E_CMD_TYPE eCommand, + const OUString &rExtensionURL, + const OUString &rRepository, + const bool bWarnUser ) + : m_eCmdType( eCommand ), + m_bWarnUser( bWarnUser ), + m_sExtensionURL( rExtensionURL ), + m_sRepository( rRepository ) {}; + ExtensionCmd( const E_CMD_TYPE eCommand, + const uno::Reference< deployment::XPackage > &rPackage ) + : m_eCmdType( eCommand ), + m_bWarnUser( false ), + m_xPackage( rPackage ) {}; + ExtensionCmd( const E_CMD_TYPE eCommand, + const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) + : m_eCmdType( eCommand ), + m_bWarnUser( false ), + m_vExtensionList( vExtensionList ) {}; +}; + +typedef ::boost::shared_ptr< ExtensionCmd > TExtensionCmd; + +//------------------------------------------------------------------------------ +class ExtensionCmdQueue::Thread: public dp_gui::Thread +{ +public: + Thread( DialogHelper *pDialogHelper, + TheExtensionManager *pManager, + const uno::Reference< uno::XComponentContext > & rContext ); + + void addExtension( const OUString &rExtensionURL, + const OUString &rRepository, + const bool bWarnUser ); + void removeExtension( const uno::Reference< deployment::XPackage > &rPackage ); + void enableExtension( const uno::Reference< deployment::XPackage > &rPackage, + const bool bEnable ); + void checkForUpdates( const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ); + void acceptLicense( const uno::Reference< deployment::XPackage > &rPackage ); + void stop(); + bool isBusy(); + +private: + Thread( Thread & ); // not defined + void operator =( Thread & ); // not defined + + virtual ~Thread(); + + virtual void execute(); + virtual void SAL_CALL onTerminated(); + + void _insert(const TExtensionCmd& rExtCmd); + + void _addExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const OUString &rPackageURL, + const OUString &rRepository, + const bool bWarnUser ); + void _removeExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ); + void _enableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ); + void _disableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ); + void _checkForUpdates( const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ); + void _acceptLicense( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ); + + enum Input { NONE, START, STOP }; + + uno::Reference< uno::XComponentContext > m_xContext; + std::queue< TExtensionCmd > m_queue; + + DialogHelper *m_pDialogHelper; + TheExtensionManager *m_pManager; + + const OUString m_sEnablingPackages; + const OUString m_sDisablingPackages; + const OUString m_sAddingPackages; + const OUString m_sRemovingPackages; + const OUString m_sDefaultCmd; + const OUString m_sAcceptLicense; + osl::Condition m_wakeup; + osl::Mutex m_mutex; + Input m_eInput; + bool m_bTerminated; + bool m_bStopped; + bool m_bWorking; +}; + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::startProgress() +{ + m_nCurrentProgress = 0; + + if ( m_pDialogHelper ) + m_pDialogHelper->showProgress( true ); +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::stopProgress() +{ + if ( m_pDialogHelper ) + m_pDialogHelper->showProgress( false ); +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::progressSection( const OUString &rText, + const uno::Reference< task::XAbortChannel > &xAbortChannel ) +{ + m_xAbortChannel = xAbortChannel; + if (! m_bAborted) + { + m_nCurrentProgress = 0; + if ( m_pDialogHelper ) + { + m_pDialogHelper->updateProgress( rText, xAbortChannel ); + m_pDialogHelper->updateProgress( 5 ); + } + } +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::updateProgress() +{ + if ( ! m_bAborted ) + { + long nProgress = ((m_nCurrentProgress*5) % 100) + 5; + if ( m_pDialogHelper ) + m_pDialogHelper->updateProgress( nProgress ); + } +} + +//------------------------------------------------------------------------------ +ProgressCmdEnv::~ProgressCmdEnv() +{ + // TODO: stop all threads and wait +} + + +//------------------------------------------------------------------------------ +// XCommandEnvironment +//------------------------------------------------------------------------------ +uno::Reference< task::XInteractionHandler > ProgressCmdEnv::getInteractionHandler() + throw ( uno::RuntimeException ) +{ + return this; +} + +//------------------------------------------------------------------------------ +uno::Reference< ucb::XProgressHandler > ProgressCmdEnv::getProgressHandler() + throw ( uno::RuntimeException ) +{ + return this; +} + +//------------------------------------------------------------------------------ +// XInteractionHandler +//------------------------------------------------------------------------------ +void ProgressCmdEnv::handle( uno::Reference< task::XInteractionRequest > const & xRequest ) + throw ( uno::RuntimeException ) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + dp_misc::TRACE( OUSTR("[dp_gui_cmdenv.cxx] incoming request:\n") + + ::comphelper::anyToString(request) + OUSTR("\n")); + + lang::WrappedTargetException wtExc; + deployment::DependencyException depExc; + deployment::LicenseException licExc; + deployment::VersionException verExc; + deployment::InstallException instExc; + deployment::PlatformException platExc; + + // selections: + bool approve = false; + bool abort = false; + + if (request >>= wtExc) { + // handable deployment error signalled, e.g. + // bundle item registration failed, notify cause only: + uno::Any cause; + deployment::DeploymentException dpExc; + if (wtExc.TargetException >>= dpExc) + cause = dpExc.Cause; + else { + ucb::CommandFailedException cfExc; + if (wtExc.TargetException >>= cfExc) + cause = cfExc.Reason; + else + cause = wtExc.TargetException; + } + update_( cause ); + + // ignore intermediate errors of legacy packages, i.e. + // former pkgchk behaviour: + const uno::Reference< deployment::XPackage > xPackage( wtExc.Context, uno::UNO_QUERY ); + OSL_ASSERT( xPackage.is() ); + if ( xPackage.is() ) + { + const uno::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; + } + else if (request >>= depExc) + { + std::vector< rtl::OUString > deps; + for (sal_Int32 i = 0; i < depExc.UnsatisfiedDependencies.getLength(); + ++i) + { + deps.push_back( + dp_misc::Dependencies::getErrorText( depExc.UnsatisfiedDependencies[i]) ); + } + { + SolarMutexGuard guard; + short n = DependencyDialog( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, deps ).Execute(); + // Distinguish between closing the dialog and programatically + // canceling the dialog (headless VCL): + approve = n == RET_OK + || (n == RET_CANCEL && !Application::IsDialogCancelEnabled()); + } + } + else if (request >>= licExc) + { + uno::Reference< ui::dialogs::XExecutableDialog > xDialog( + deployment::ui::LicenseDialog::create( + m_xContext, VCLUnoHelper::GetInterface( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL ), + licExc.ExtensionName, licExc.Text ) ); + sal_Int16 res = xDialog->execute(); + if ( res == ui::dialogs::ExecutableDialogResults::CANCEL ) + abort = true; + else if ( res == ui::dialogs::ExecutableDialogResults::OK ) + approve = true; + else + { + OSL_ASSERT(0); + } + } + else if (request >>= verExc) + { + sal_uInt32 id; + switch (dp_misc::compareVersions( + verExc.NewVersion, verExc.Deployed->getVersion() )) + { + case dp_misc::LESS: + id = RID_WARNINGBOX_VERSION_LESS; + break; + case dp_misc::EQUAL: + id = RID_WARNINGBOX_VERSION_EQUAL; + break; + default: // dp_misc::GREATER + id = RID_WARNINGBOX_VERSION_GREATER; + break; + } + OSL_ASSERT( verExc.Deployed.is() ); + bool bEqualNames = verExc.NewDisplayName.equals( + verExc.Deployed->getDisplayName()); + { + SolarMutexGuard guard; + WarningBox box( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, ResId(id, *DeploymentGuiResMgr::get())); + String s; + if (bEqualNames) + { + s = box.GetMessText(); + } + else if (id == RID_WARNINGBOX_VERSION_EQUAL) + { + //hypothetical: requires two instances of an extension with the same + //version to have different display names. Probably the developer forgot + //to change the version. + s = String(ResId(RID_STR_WARNINGBOX_VERSION_EQUAL_DIFFERENT_NAMES, *DeploymentGuiResMgr::get())); + } + else if (id == RID_WARNINGBOX_VERSION_LESS) + { + s = String(ResId(RID_STR_WARNINGBOX_VERSION_LESS_DIFFERENT_NAMES, *DeploymentGuiResMgr::get())); + } + else if (id == RID_WARNINGBOX_VERSION_GREATER) + { + s = String(ResId(RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES, *DeploymentGuiResMgr::get())); + } + s.SearchAndReplaceAllAscii( "$NAME", verExc.NewDisplayName); + s.SearchAndReplaceAllAscii( "$OLDNAME", verExc.Deployed->getDisplayName()); + s.SearchAndReplaceAllAscii( "$NEW", getVersion(verExc.NewVersion) ); + s.SearchAndReplaceAllAscii( "$DEPLOYED", getVersion(verExc.Deployed) ); + box.SetMessText(s); + approve = box.Execute() == RET_OK; + abort = !approve; + } + } + else if (request >>= instExc) + { + if ( ! m_bWarnUser ) + { + approve = true; + } + else + { + if ( m_pDialogHelper ) + { + SolarMutexGuard guard; + + approve = m_pDialogHelper->installExtensionWarn( instExc.displayName ); + } + else + approve = false; + abort = !approve; + } + } + else if (request >>= platExc) + { + SolarMutexGuard guard; + String sMsg( ResId( RID_STR_UNSUPPORTED_PLATFORM, *DeploymentGuiResMgr::get() ) ); + sMsg.SearchAndReplaceAllAscii( "%Name", platExc.package->getDisplayName() ); + ErrorBox box( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, WB_OK, sMsg ); + box.Execute(); + approve = true; + } + + if (approve == false && abort == false) + { + // forward to UUI handler: + if (! m_xHandler.is()) { + // late init: + uno::Sequence< uno::Any > handlerArgs( 1 ); + handlerArgs[ 0 ] <<= beans::PropertyValue( + OUSTR("Context"), -1, uno::Any( m_sTitle ), + beans::PropertyState_DIRECT_VALUE ); + m_xHandler.set( m_xContext->getServiceManager() + ->createInstanceWithArgumentsAndContext( + OUSTR("com.sun.star.uui.InteractionHandler"), + handlerArgs, m_xContext ), uno::UNO_QUERY_THROW ); + } + m_xHandler->handle( xRequest ); + } + else + { + // select: + uno::Sequence< uno::Reference< task::XInteractionContinuation > > conts( + xRequest->getContinuations() ); + uno::Reference< task::XInteractionContinuation > const * pConts = conts.getConstArray(); + sal_Int32 len = conts.getLength(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + if (approve) { + uno::Reference< task::XInteractionApprove > xInteractionApprove( pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + // don't query again for ongoing continuations: + approve = false; + } + } + else if (abort) { + uno::Reference< task::XInteractionAbort > xInteractionAbort( pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionAbort.is()) { + xInteractionAbort->select(); + // don't query again for ongoing continuations: + abort = false; + } + } + } + } +} + +//------------------------------------------------------------------------------ +// XProgressHandler +//------------------------------------------------------------------------------ +void ProgressCmdEnv::push( uno::Any const & rStatus ) + throw( uno::RuntimeException ) +{ + update_( rStatus ); +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::update_( uno::Any const & rStatus ) + throw( uno::RuntimeException ) +{ + OUString text; + if ( rStatus.hasValue() && !( rStatus >>= text) ) + { + if ( rStatus.getValueTypeClass() == uno::TypeClass_EXCEPTION ) + text = static_cast< uno::Exception const *>( rStatus.getValue() )->Message; + if ( text.getLength() == 0 ) + text = ::comphelper::anyToString( rStatus ); // fallback + + const SolarMutexGuard aGuard; + const ::std::auto_ptr< ErrorBox > aBox( new ErrorBox( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, WB_OK, text ) ); + aBox->Execute(); + } + ++m_nCurrentProgress; + updateProgress(); +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::update( uno::Any const & rStatus ) + throw( uno::RuntimeException ) +{ + update_( rStatus ); +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::pop() + throw( uno::RuntimeException ) +{ + update_( uno::Any() ); // no message +} + +//------------------------------------------------------------------------------ +ExtensionCmdQueue::Thread::Thread( DialogHelper *pDialogHelper, + TheExtensionManager *pManager, + const uno::Reference< uno::XComponentContext > & rContext ) : + m_xContext( rContext ), + m_pDialogHelper( pDialogHelper ), + m_pManager( pManager ), + m_sEnablingPackages( DialogHelper::getResourceString( RID_STR_ENABLING_PACKAGES ) ), + m_sDisablingPackages( DialogHelper::getResourceString( RID_STR_DISABLING_PACKAGES ) ), + m_sAddingPackages( DialogHelper::getResourceString( RID_STR_ADDING_PACKAGES ) ), + m_sRemovingPackages( DialogHelper::getResourceString( RID_STR_REMOVING_PACKAGES ) ), + m_sDefaultCmd( DialogHelper::getResourceString( RID_STR_ADD_PACKAGES ) ), + m_sAcceptLicense( DialogHelper::getResourceString( RID_STR_ACCEPT_LICENSE ) ), + m_eInput( NONE ), + m_bTerminated( false ), + m_bStopped( false ), + m_bWorking( false ) +{ + OSL_ASSERT( pDialogHelper ); +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::addExtension( const ::rtl::OUString &rExtensionURL, + const ::rtl::OUString &rRepository, + const bool bWarnUser ) +{ + if ( rExtensionURL.getLength() ) + { + TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::ADD, rExtensionURL, rRepository, bWarnUser ) ); + _insert( pEntry ); + } +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::removeExtension( const uno::Reference< deployment::XPackage > &rPackage ) +{ + if ( rPackage.is() ) + { + TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::REMOVE, rPackage ) ); + _insert( pEntry ); + } +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::acceptLicense( const uno::Reference< deployment::XPackage > &rPackage ) +{ + if ( rPackage.is() ) + { + TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::ACCEPT_LICENSE, rPackage ) ); + _insert( pEntry ); + } +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::enableExtension( const uno::Reference< deployment::XPackage > &rPackage, + const bool bEnable ) +{ + if ( rPackage.is() ) + { + TExtensionCmd pEntry( new ExtensionCmd( bEnable ? ExtensionCmd::ENABLE : + ExtensionCmd::DISABLE, + rPackage ) ); + _insert( pEntry ); + } +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::checkForUpdates( + const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) +{ + TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::CHECK_FOR_UPDATES, vExtensionList ) ); + _insert( pEntry ); +} + +//------------------------------------------------------------------------------ +//Stopping this thread will not abort the installation of extensions. +void ExtensionCmdQueue::Thread::stop() +{ + osl::MutexGuard aGuard( m_mutex ); + m_bStopped = true; + m_eInput = STOP; + m_wakeup.set(); +} + +//------------------------------------------------------------------------------ +bool ExtensionCmdQueue::Thread::isBusy() +{ + osl::MutexGuard aGuard( m_mutex ); + return m_bWorking; +} + +//------------------------------------------------------------------------------ +ExtensionCmdQueue::Thread::~Thread() {} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::execute() +{ +#ifdef WNT + //Needed for use of the service "com.sun.star.system.SystemShellExecute" in + //DialogHelper::openWebBrowser + CoUninitialize(); + HRESULT r = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); +#endif + for (;;) + { + if ( m_wakeup.wait() != osl::Condition::result_ok ) + { + dp_misc::TRACE( "dp_gui::ExtensionCmdQueue::Thread::run: ignored " + "osl::Condition::wait failure\n" ); + } + m_wakeup.reset(); + + int nSize; + Input eInput; + { + osl::MutexGuard aGuard( m_mutex ); + eInput = m_eInput; + m_eInput = NONE; + nSize = m_queue.size(); + m_bWorking = false; + } + + // If this thread has been woken up by anything else except start, stop + // then input is NONE and we wait again. + // We only install the extension which are currently in the queue. + // The progressbar will be set to show the progress of the current number + // of extensions. If we allowed to add extensions now then the progressbar may + // have reached the end while we still install newly added extensions. + if ( ( eInput == NONE ) || ( nSize == 0 ) ) + continue; + if ( eInput == STOP ) + break; + + ::rtl::Reference< ProgressCmdEnv > currentCmdEnv( new ProgressCmdEnv( m_xContext, m_pDialogHelper, m_sDefaultCmd ) ); + + // Do not lock the following part with addExtension. addExtension may be called in the main thread. + // If the message box "Do you want to install the extension (or similar)" is shown and then + // addExtension is called, which then blocks the main thread, then we deadlock. + bool bStartProgress = true; + + while ( !currentCmdEnv->isAborted() && --nSize >= 0 ) + { + { + osl::MutexGuard aGuard( m_mutex ); + m_bWorking = true; + } + + try + { + TExtensionCmd pEntry; + { + ::osl::MutexGuard queueGuard( m_mutex ); + pEntry = m_queue.front(); + m_queue.pop(); + } + + if ( bStartProgress && ( pEntry->m_eCmdType != ExtensionCmd::CHECK_FOR_UPDATES ) ) + { + currentCmdEnv->startProgress(); + bStartProgress = false; + } + + switch ( pEntry->m_eCmdType ) { + case ExtensionCmd::ADD : + _addExtension( currentCmdEnv, pEntry->m_sExtensionURL, pEntry->m_sRepository, pEntry->m_bWarnUser ); + break; + case ExtensionCmd::REMOVE : + _removeExtension( currentCmdEnv, pEntry->m_xPackage ); + break; + case ExtensionCmd::ENABLE : + _enableExtension( currentCmdEnv, pEntry->m_xPackage ); + break; + case ExtensionCmd::DISABLE : + _disableExtension( currentCmdEnv, pEntry->m_xPackage ); + break; + case ExtensionCmd::CHECK_FOR_UPDATES : + _checkForUpdates( pEntry->m_vExtensionList ); + break; + case ExtensionCmd::ACCEPT_LICENSE : + _acceptLicense( currentCmdEnv, pEntry->m_xPackage ); + break; + } + } + catch ( ucb::CommandAbortedException & ) + { + //This exception is thrown when the user clicks cancel on the progressbar. + //Then we cancel the installation of all extensions and remove them from + //the queue. + { + ::osl::MutexGuard queueGuard2(m_mutex); + while ( --nSize >= 0 ) + m_queue.pop(); + } + break; + } + catch ( ucb::CommandFailedException & ) + { + //This exception is thrown when a user clicked cancel in the messagebox which was + //startet by the interaction handler. For example the user will be asked if he/she + //really wants to install the extension. + //These interaction are run for exectly one extension at a time. Therefore we continue + //with installing the remaining extensions. + continue; + } + catch ( uno::Exception & ) + { + //Todo display the user an error + //see also DialogImpl::SyncPushButton::Click() + uno::Any exc( ::cppu::getCaughtException() ); + OUString msg; + deployment::DeploymentException dpExc; + if ((exc >>= dpExc) && + dpExc.Cause.getValueTypeClass() == uno::TypeClass_EXCEPTION) + { + // notify error cause only: + msg = reinterpret_cast< uno::Exception const * >( dpExc.Cause.getValue() )->Message; + } + if (msg.getLength() == 0) // fallback for debugging purposes + msg = ::comphelper::anyToString(exc); + + const SolarMutexGuard guard; + ::std::auto_ptr<ErrorBox> box( + new ErrorBox( currentCmdEnv->activeDialog(), WB_OK, msg ) ); + if ( m_pDialogHelper ) + box->SetText( m_pDialogHelper->getWindow()->GetText() ); + box->Execute(); + //Continue with installation of the remaining extensions + } + { + osl::MutexGuard aGuard( m_mutex ); + m_bWorking = false; + } + } + + { + // when leaving the while loop with break, we should set working to false, too + osl::MutexGuard aGuard( m_mutex ); + m_bWorking = false; + } + + if ( !bStartProgress ) + currentCmdEnv->stopProgress(); + } + //end for +#ifdef WNT + CoUninitialize(); +#endif +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_addExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const OUString &rPackageURL, + const OUString &rRepository, + const bool bWarnUser ) +{ + //check if we have a string in anyTitle. For example "unopkg gui \" caused anyTitle to be void + //and anyTitle.get<OUString> throws as RuntimeException. + uno::Any anyTitle; + try + { + anyTitle = ::ucbhelper::Content( rPackageURL, rCmdEnv.get() ).getPropertyValue( OUSTR("Title") ); + } + catch ( uno::Exception & ) + { + return; + } + + OUString sName; + if ( ! (anyTitle >>= sName) ) + { + OSL_FAIL("Could not get file name for extension."); + return; + } + + rCmdEnv->setWarnUser( bWarnUser ); + uno::Reference< deployment::XExtensionManager > xExtMgr = m_pManager->getExtensionManager(); + uno::Reference< task::XAbortChannel > xAbortChannel( xExtMgr->createAbortChannel() ); + OUString sTitle = comphelper::string::replace(m_sAddingPackages, OUSTR("%EXTENSION_NAME"), sName); + rCmdEnv->progressSection( sTitle, xAbortChannel ); + + try + { + xExtMgr->addExtension(rPackageURL, uno::Sequence<beans::NamedValue>(), + rRepository, xAbortChannel, rCmdEnv.get() ); + } + catch ( ucb::CommandFailedException & ) + { + // When the extension is already installed we'll get a dialog asking if we want to overwrite. If we then press + // cancel this exception is thrown. + } + catch ( ucb::CommandAbortedException & ) + { + // User clicked the cancel button + // TODO: handle cancel + } + rCmdEnv->setWarnUser( false ); +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_removeExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ) +{ + uno::Reference< deployment::XExtensionManager > xExtMgr = m_pManager->getExtensionManager(); + uno::Reference< task::XAbortChannel > xAbortChannel( xExtMgr->createAbortChannel() ); + OUString sTitle = comphelper::string::replace(m_sRemovingPackages, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName()); + rCmdEnv->progressSection( sTitle, xAbortChannel ); + + OUString id( dp_misc::getIdentifier( xPackage ) ); + try + { + xExtMgr->removeExtension( id, xPackage->getName(), xPackage->getRepositoryName(), xAbortChannel, rCmdEnv.get() ); + } + catch ( deployment::DeploymentException & ) + {} + catch ( ucb::CommandFailedException & ) + {} + catch ( ucb::CommandAbortedException & ) + {} + + // Check, if there are still updates to be notified via menu bar icon + uno::Sequence< uno::Sequence< rtl::OUString > > aItemList; + UpdateDialog::createNotifyJob( false, aItemList ); +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_checkForUpdates( + const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) +{ + UpdateDialog* pUpdateDialog; + std::vector< UpdateData > vData; + + const SolarMutexGuard guard; + + pUpdateDialog = new UpdateDialog( m_xContext, m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, vExtensionList, &vData ); + + pUpdateDialog->notifyMenubar( true, false ); // prepare the checking, if there updates to be notified via menu bar icon + + if ( ( pUpdateDialog->Execute() == RET_OK ) && !vData.empty() ) + { + // If there is at least one directly downloadable extension then we + // open the install dialog. + ::std::vector< UpdateData > dataDownload; + int countWebsiteDownload = 0; + typedef std::vector< dp_gui::UpdateData >::const_iterator cit; + + for ( cit i = vData.begin(); i < vData.end(); ++i ) + { + if ( i->sWebsiteURL.getLength() > 0 ) + countWebsiteDownload ++; + else + dataDownload.push_back( *i ); + } + + short nDialogResult = RET_OK; + if ( !dataDownload.empty() ) + { + nDialogResult = UpdateInstallDialog( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, dataDownload, m_xContext ).Execute(); + pUpdateDialog->notifyMenubar( false, true ); // Check, if there are still pending updates to be notified via menu bar icon + } + else + pUpdateDialog->notifyMenubar( false, false ); // Check, if there are pending updates to be notified via menu bar icon + + //Now start the webbrowser and navigate to the websites where we get the updates + if ( RET_OK == nDialogResult ) + { + for ( cit i = vData.begin(); i < vData.end(); ++i ) + { + if ( m_pDialogHelper && ( i->sWebsiteURL.getLength() > 0 ) ) + m_pDialogHelper->openWebBrowser( i->sWebsiteURL, m_pDialogHelper->getWindow()->GetText() ); + } + } + } + else + pUpdateDialog->notifyMenubar( false, false ); // check if there updates to be notified via menu bar icon + + delete pUpdateDialog; +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_enableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return; + + uno::Reference< deployment::XExtensionManager > xExtMgr = m_pManager->getExtensionManager(); + uno::Reference< task::XAbortChannel > xAbortChannel( xExtMgr->createAbortChannel() ); + OUString sTitle = comphelper::string::replace(m_sEnablingPackages, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName()); + rCmdEnv->progressSection( sTitle, xAbortChannel ); + + try + { + xExtMgr->enableExtension( xPackage, xAbortChannel, rCmdEnv.get() ); + if ( m_pDialogHelper ) + m_pDialogHelper->updatePackageInfo( xPackage ); + } + catch ( ::ucb::CommandAbortedException & ) + {} +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_disableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return; + + uno::Reference< deployment::XExtensionManager > xExtMgr = m_pManager->getExtensionManager(); + uno::Reference< task::XAbortChannel > xAbortChannel( xExtMgr->createAbortChannel() ); + OUString sTitle = comphelper::string::replace(m_sDisablingPackages, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName()); + rCmdEnv->progressSection( sTitle, xAbortChannel ); + + try + { + xExtMgr->disableExtension( xPackage, xAbortChannel, rCmdEnv.get() ); + if ( m_pDialogHelper ) + m_pDialogHelper->updatePackageInfo( xPackage ); + } + catch ( ::ucb::CommandAbortedException & ) + {} +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_acceptLicense( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return; + + uno::Reference< deployment::XExtensionManager > xExtMgr = m_pManager->getExtensionManager(); + uno::Reference< task::XAbortChannel > xAbortChannel( xExtMgr->createAbortChannel() ); + OUString sTitle = comphelper::string::replace(m_sAcceptLicense, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName()); + rCmdEnv->progressSection( sTitle, xAbortChannel ); + + try + { + xExtMgr->checkPrerequisitesAndEnable( xPackage, xAbortChannel, rCmdEnv.get() ); + if ( m_pDialogHelper ) + m_pDialogHelper->updatePackageInfo( xPackage ); + } + catch ( ::ucb::CommandAbortedException & ) + {} +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::onTerminated() +{ + ::osl::MutexGuard g(m_mutex); + m_bTerminated = true; +} + +void ExtensionCmdQueue::Thread::_insert(const TExtensionCmd& rExtCmd) +{ + ::osl::MutexGuard aGuard( m_mutex ); + + // If someone called stop then we do not process the command -> game over! + if ( m_bStopped ) + return; + + m_queue.push( rExtCmd ); + m_eInput = START; + m_wakeup.set(); +} + +//------------------------------------------------------------------------------ +ExtensionCmdQueue::ExtensionCmdQueue( DialogHelper * pDialogHelper, + TheExtensionManager *pManager, + const uno::Reference< uno::XComponentContext > &rContext ) + : m_thread( new Thread( pDialogHelper, pManager, rContext ) ) +{ + m_thread->launch(); +} + +ExtensionCmdQueue::~ExtensionCmdQueue() { + stop(); +} + +void ExtensionCmdQueue::addExtension( const ::rtl::OUString & extensionURL, + const ::rtl::OUString & repository, + const bool bWarnUser ) +{ + m_thread->addExtension( extensionURL, repository, bWarnUser ); +} + +void ExtensionCmdQueue::removeExtension( const uno::Reference< deployment::XPackage > &rPackage ) +{ + m_thread->removeExtension( rPackage ); +} + +void ExtensionCmdQueue::enableExtension( const uno::Reference< deployment::XPackage > &rPackage, + const bool bEnable ) +{ + m_thread->enableExtension( rPackage, bEnable ); +} + +void ExtensionCmdQueue::checkForUpdates( const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) +{ + m_thread->checkForUpdates( vExtensionList ); +} + +void ExtensionCmdQueue::acceptLicense( const uno::Reference< deployment::XPackage > &rPackage ) +{ + m_thread->acceptLicense( rPackage ); +} + +void ExtensionCmdQueue::syncRepositories( const uno::Reference< uno::XComponentContext > &xContext ) +{ + dp_misc::syncRepositories( new ProgressCmdEnv( xContext, NULL, OUSTR("Extension Manager") ) ); +} + +void ExtensionCmdQueue::stop() +{ + m_thread->stop(); +} + +bool ExtensionCmdQueue::isBusy() +{ + return m_thread->isBusy(); +} + +void handleInteractionRequest( const uno::Reference< uno::XComponentContext > & xContext, + const uno::Reference< task::XInteractionRequest > & xRequest ) +{ + ::rtl::Reference< ProgressCmdEnv > xCmdEnv( new ProgressCmdEnv( xContext, NULL, OUSTR("Extension Manager") ) ); + xCmdEnv->handle( xRequest ); +} + +} //namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.hxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.hxx new file mode 100644 index 000000000000..f8fd1f1b2e05 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.hxx @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DP_GUI_EXTENSIONCMDQUEUE_HXX +#define INCLUDED_DP_GUI_EXTENSIONCMDQUEUE_HXX + +#include "sal/config.h" + +#include "com/sun/star/uno/Reference.hxx" +#include "rtl/ref.hxx" + +#include <vector> + +#include "dp_gui_updatedata.hxx" + +/// @HTML + +namespace com { namespace sun { namespace star { + namespace task { class XInteractionRequest; } + namespace uno { class XComponentContext; } +} } } + +namespace dp_gui { + +class DialogHelper; +class TheExtensionManager; + +/** + Manages installing of extensions in the GUI mode. Requests for installing + Extensions can be asynchronous. For example, the Extension Manager is running + in an office process and someone uses the system integration to install an Extension. + That is, the user double clicks an extension symbol in a file browser, which then + causes an invocation of "unopkg gui ext". When at that time the Extension Manager + already performs a task, triggered by the user (for example, add, update, disable, + enable) then adding of the extension will be postponed until the user has finished + the task. + + This class also ensures that the extensions are not installed in the main thread. + Doing so would cause a deadlock because of the progress bar which needs to be constantly + updated. +*/ +class ExtensionCmdQueue { + +public: + /** + Create an instance. + */ + ExtensionCmdQueue( DialogHelper * pDialogHelper, + TheExtensionManager *pManager, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & rContext); + + ~ExtensionCmdQueue(); + + /** + */ + void addExtension( const ::rtl::OUString &rExtensionURL, + const ::rtl::OUString &rRepository, + const bool bWarnUser ); + void removeExtension( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &rPackage ); + void enableExtension( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &rPackage, + const bool bEnable ); + void checkForUpdates(const std::vector< ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage > > &vList ); + void acceptLicense( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &rPackage ); + static void syncRepositories( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & xContext ); + /** + This call does not block. It signals the internal thread + that it should install the remaining extensions and then terminate. + */ + void stop(); + + bool isBusy(); +private: + ExtensionCmdQueue(ExtensionCmdQueue &); // not defined + void operator =(ExtensionCmdQueue &); // not defined + + class Thread; + + rtl::Reference< Thread > m_thread; +}; + +void handleInteractionRequest( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & xContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest > & xRequest ); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_extlistbox.cxx b/desktop/source/deployment/gui/dp_gui_extlistbox.cxx new file mode 100644 index 000000000000..96e4e596ca71 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_extlistbox.cxx @@ -0,0 +1,1224 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "svtools/controldims.hrc" + +#include "dp_gui.h" +#include "dp_gui_extlistbox.hxx" +#include "dp_gui_theextmgr.hxx" +#include "dp_gui_dialog2.hxx" +#include "dp_dependencies.hxx" + +#include "comphelper/processfactory.hxx" +#include "com/sun/star/i18n/CollatorOptions.hpp" +#include "com/sun/star/deployment/DependencyException.hpp" +#include "com/sun/star/deployment/DeploymentException.hpp" + + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +#define USER_PACKAGE_MANAGER OUSTR("user") +#define SHARED_PACKAGE_MANAGER OUSTR("shared") +#define BUNDLED_PACKAGE_MANAGER OUSTR("bundled") + +using namespace ::com::sun::star; + +namespace dp_gui { + +//------------------------------------------------------------------------------ +// struct Entry_Impl +//------------------------------------------------------------------------------ +Entry_Impl::Entry_Impl( const uno::Reference< deployment::XPackage > &xPackage, + const PackageState eState, const bool bReadOnly ) : + m_bActive( false ), + m_bLocked( bReadOnly ), + m_bHasOptions( false ), + m_bUser( false ), + m_bShared( false ), + m_bNew( false ), + m_bChecked( false ), + m_bMissingDeps( false ), + m_bHasButtons( false ), + m_bMissingLic( false ), + m_eState( eState ), + m_pPublisher( NULL ), + m_xPackage( xPackage ) +{ + try + { + m_sTitle = xPackage->getDisplayName(); + m_sVersion = xPackage->getVersion(); + m_sDescription = xPackage->getDescription(); + m_sLicenseText = xPackage->getLicenseText(); + + beans::StringPair aInfo( m_xPackage->getPublisherInfo() ); + m_sPublisher = aInfo.First; + m_sPublisherURL = aInfo.Second; + + // get the icons for the package if there are any + uno::Reference< graphic::XGraphic > xGraphic = xPackage->getIcon( false ); + if ( xGraphic.is() ) + m_aIcon = Image( xGraphic ); + + xGraphic = xPackage->getIcon( true ); + if ( xGraphic.is() ) + m_aIconHC = Image( xGraphic ); + else + m_aIconHC = m_aIcon; + + if ( eState == AMBIGUOUS ) + m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_UNKNOWN_STATUS ); + else if ( eState == NOT_REGISTERED ) + checkDependencies(); + } + catch (deployment::ExtensionRemovedException &) {} + catch (uno::RuntimeException &) {} +} + +//------------------------------------------------------------------------------ +Entry_Impl::~Entry_Impl() +{} + +//------------------------------------------------------------------------------ +StringCompare Entry_Impl::CompareTo( const CollatorWrapper *pCollator, const TEntry_Impl pEntry ) const +{ + StringCompare eCompare = (StringCompare) pCollator->compareString( m_sTitle, pEntry->m_sTitle ); + if ( eCompare == COMPARE_EQUAL ) + { + eCompare = m_sVersion.CompareTo( pEntry->m_sVersion ); + if ( eCompare == COMPARE_EQUAL ) + { + sal_Int32 nCompare = m_xPackage->getRepositoryName().compareTo( pEntry->m_xPackage->getRepositoryName() ); + if ( nCompare < 0 ) + eCompare = COMPARE_LESS; + else if ( nCompare > 0 ) + eCompare = COMPARE_GREATER; + } + } + return eCompare; +} + +//------------------------------------------------------------------------------ +void Entry_Impl::checkDependencies() +{ + try { + m_xPackage->checkDependencies( uno::Reference< ucb::XCommandEnvironment >() ); + } + catch ( deployment::DeploymentException &e ) + { + deployment::DependencyException depExc; + if ( e.Cause >>= depExc ) + { + rtl::OUString aMissingDep( DialogHelper::getResourceString( RID_STR_ERROR_MISSING_DEPENDENCIES ) ); + for ( sal_Int32 i = 0; i < depExc.UnsatisfiedDependencies.getLength(); ++i ) + { + aMissingDep += OUSTR("\n"); + aMissingDep += dp_misc::Dependencies::getErrorText( depExc.UnsatisfiedDependencies[i]); + } + aMissingDep += OUSTR("\n"); + m_sErrorText = aMissingDep; + m_bMissingDeps = true; + } + } +} +//------------------------------------------------------------------------------ +// ExtensionRemovedListener +//------------------------------------------------------------------------------ +void ExtensionRemovedListener::disposing( lang::EventObject const & rEvt ) + throw ( uno::RuntimeException ) +{ + uno::Reference< deployment::XPackage > xPackage( rEvt.Source, uno::UNO_QUERY ); + + if ( xPackage.is() ) + { + m_pParent->removeEntry( xPackage ); + } +} + +//------------------------------------------------------------------------------ +ExtensionRemovedListener::~ExtensionRemovedListener() +{ +} + +//------------------------------------------------------------------------------ +// ExtensionBox_Impl +//------------------------------------------------------------------------------ +ExtensionBox_Impl::ExtensionBox_Impl( Dialog* pParent, TheExtensionManager *pManager ) : + IExtensionListBox( pParent, WB_BORDER | WB_TABSTOP | WB_CHILDDLGCTRL ), + m_bHasScrollBar( false ), + m_bHasActive( false ), + m_bNeedsRecalc( true ), + m_bHasNew( false ), + m_bInCheckMode( false ), + m_bAdjustActive( false ), + m_bInDelete( false ), + m_nActive( 0 ), + m_nTopIndex( 0 ), + m_nActiveHeight( 0 ), + m_nExtraHeight( 2 ), + m_aSharedImage( DialogHelper::getResId( RID_IMG_SHARED ) ), + m_aLockedImage( DialogHelper::getResId( RID_IMG_LOCKED ) ), + m_aWarningImage( DialogHelper::getResId( RID_IMG_WARNING ) ), + m_aDefaultImage( DialogHelper::getResId( RID_IMG_EXTENSION ) ), + m_pScrollBar( NULL ), + m_pManager( pManager ) +{ + SetHelpId( HID_EXTENSION_MANAGER_LISTBOX ); + + m_pScrollBar = new ScrollBar( this, WB_VERT ); + m_pScrollBar->SetScrollHdl( LINK( this, ExtensionBox_Impl, ScrollHdl ) ); + m_pScrollBar->EnableDrag(); + + SetPaintTransparent( true ); + SetPosPixel( Point( RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP ) ); + long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE; + long nTitleHeight = 2*TOP_OFFSET + GetTextHeight(); + if ( nIconHeight < nTitleHeight ) + m_nStdHeight = nTitleHeight; + else + m_nStdHeight = nIconHeight; + m_nStdHeight += GetTextHeight() + TOP_OFFSET; + + nIconHeight = ICON_HEIGHT + 2*TOP_OFFSET + 1; + if ( m_nStdHeight < nIconHeight ) + m_nStdHeight = nIconHeight; + + m_nActiveHeight = m_nStdHeight; + + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + if( IsControlBackground() ) + SetBackground( GetControlBackground() ); + else + SetBackground( rStyleSettings.GetFieldColor() ); + + m_xRemoveListener = new ExtensionRemovedListener( this ); + + m_pLocale = new lang::Locale( Application::GetSettings().GetLocale() ); + m_pCollator = new CollatorWrapper( ::comphelper::getProcessServiceFactory() ); + m_pCollator->loadDefaultCollator( *m_pLocale, i18n::CollatorOptions::CollatorOptions_IGNORE_CASE ); + + Show(); +} + +//------------------------------------------------------------------------------ +ExtensionBox_Impl::~ExtensionBox_Impl() +{ + if ( ! m_bInDelete ) + DeleteRemoved(); + + m_bInDelete = true; + + typedef std::vector< TEntry_Impl >::iterator ITER; + + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + if ( (*iIndex)->m_pPublisher ) + { + delete (*iIndex)->m_pPublisher; + (*iIndex)->m_pPublisher = NULL; + } + (*iIndex)->m_xPackage->removeEventListener( uno::Reference< lang::XEventListener > ( m_xRemoveListener, uno::UNO_QUERY ) ); + } + + m_vEntries.clear(); + + delete m_pScrollBar; + + m_xRemoveListener.clear(); + + delete m_pLocale; + delete m_pCollator; +} + +//------------------------------------------------------------------------------ +sal_Int32 ExtensionBox_Impl::getItemCount() const +{ + return static_cast< sal_Int32 >( m_vEntries.size() ); +} + +//------------------------------------------------------------------------------ +sal_Int32 ExtensionBox_Impl::getSelIndex() const +{ + if ( m_bHasActive ) + { + OSL_ASSERT( m_nActive >= -1); + return static_cast< sal_Int32 >( m_nActive ); + } + else + return static_cast< sal_Int32 >( EXTENSION_LISTBOX_ENTRY_NOTFOUND ); +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::checkIndex( sal_Int32 nIndex ) const +{ + if ( nIndex < 0 ) + throw lang::IllegalArgumentException( OUSTR("The list index starts with 0"),0, 0 ); + if ( static_cast< sal_uInt32 >( nIndex ) >= m_vEntries.size()) + throw lang::IllegalArgumentException( OUSTR("There is no element at the provided position." + "The position exceeds the number of available list entries"),0, 0 ); +} + +//------------------------------------------------------------------------------ +rtl::OUString ExtensionBox_Impl::getItemName( sal_Int32 nIndex ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + return m_vEntries[ nIndex ]->m_sTitle; +} + +//------------------------------------------------------------------------------ +rtl::OUString ExtensionBox_Impl::getItemVersion( sal_Int32 nIndex ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + return m_vEntries[ nIndex ]->m_sVersion; +} + +//------------------------------------------------------------------------------ +rtl::OUString ExtensionBox_Impl::getItemDescription( sal_Int32 nIndex ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + return m_vEntries[ nIndex ]->m_sDescription; +} + +//------------------------------------------------------------------------------ +rtl::OUString ExtensionBox_Impl::getItemPublisher( sal_Int32 nIndex ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + return m_vEntries[ nIndex ]->m_sPublisher; +} + +//------------------------------------------------------------------------------ +rtl::OUString ExtensionBox_Impl::getItemPublisherLink( sal_Int32 nIndex ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + return m_vEntries[ nIndex ]->m_sPublisherURL; +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::select( sal_Int32 nIndex ) +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + selectEntry( nIndex ); +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::select( const rtl::OUString & sName ) +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + typedef ::std::vector< TEntry_Impl >::const_iterator It; + + for ( It iIter = m_vEntries.begin(); iIter < m_vEntries.end(); iIter++ ) + { + if ( sName.equals( (*iIter)->m_sTitle ) ) + { + long nPos = iIter - m_vEntries.begin(); + selectEntry( nPos ); + break; + } + } +} + +//------------------------------------------------------------------------------ +// Title + description +void ExtensionBox_Impl::CalcActiveHeight( const long nPos ) +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + + // get title height + long aTextHeight; + long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE; + long nTitleHeight = 2*TOP_OFFSET + GetTextHeight(); + if ( nIconHeight < nTitleHeight ) + aTextHeight = nTitleHeight; + else + aTextHeight = nIconHeight; + + // calc description height + Size aSize = GetOutputSizePixel(); + if ( m_bHasScrollBar ) + aSize.Width() -= m_pScrollBar->GetSizePixel().Width(); + + aSize.Width() -= ICON_OFFSET; + aSize.Height() = 10000; + + rtl::OUString aText( m_vEntries[ nPos ]->m_sErrorText ); + if ( aText.getLength() ) + aText += OUSTR("\n"); + aText += m_vEntries[ nPos ]->m_sDescription; + + Rectangle aRect = GetTextRect( Rectangle( Point(), aSize ), aText, + TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK ); + aTextHeight += aRect.GetHeight(); + + if ( aTextHeight < m_nStdHeight ) + aTextHeight = m_nStdHeight; + + if ( m_vEntries[ nPos ]->m_bHasButtons ) + m_nActiveHeight = aTextHeight + m_nExtraHeight; + else + m_nActiveHeight = aTextHeight + 2; +} + +//------------------------------------------------------------------------------ +const Size ExtensionBox_Impl::GetMinOutputSizePixel() const +{ + return Size( 200, 80 ); +} + +//------------------------------------------------------------------------------ +Rectangle ExtensionBox_Impl::GetEntryRect( const long nPos ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + + Size aSize( GetOutputSizePixel() ); + + if ( m_bHasScrollBar ) + aSize.Width() -= m_pScrollBar->GetSizePixel().Width(); + + if ( m_vEntries[ nPos ]->m_bActive ) + aSize.Height() = m_nActiveHeight; + else + aSize.Height() = m_nStdHeight; + + Point aPos( 0, -m_nTopIndex + nPos * m_nStdHeight ); + if ( m_bHasActive && ( nPos < m_nActive ) ) + aPos.Y() += m_nActiveHeight - m_nStdHeight; + + return Rectangle( aPos, aSize ); +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::DeleteRemoved() +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + + m_bInDelete = true; + + if ( ! m_vRemovedEntries.empty() ) + { + typedef std::vector< TEntry_Impl >::iterator ITER; + + for ( ITER iIndex = m_vRemovedEntries.begin(); iIndex < m_vRemovedEntries.end(); ++iIndex ) + { + if ( (*iIndex)->m_pPublisher ) + { + delete (*iIndex)->m_pPublisher; + (*iIndex)->m_pPublisher = NULL; + } + } + + m_vRemovedEntries.clear(); + } + + m_bInDelete = false; +} + +//------------------------------------------------------------------------------ +//This function may be called with nPos < 0 +void ExtensionBox_Impl::selectEntry( const long nPos ) +{ + //ToDo whe should not use the guard at such a big scope here. + //Currently it is used to gard m_vEntries and m_nActive. m_nActive will be + //modified in this function. + //It would be probably best to always use a copy of m_vEntries + //and some other state variables from ExtensionBox_Impl for + //the whole painting operation. See issue i86993 + ::osl::ClearableMutexGuard guard(m_entriesMutex); + + if ( m_bInCheckMode ) + return; + + if ( m_bHasActive ) + { + if ( nPos == m_nActive ) + return; + + m_bHasActive = false; + m_vEntries[ m_nActive ]->m_bActive = false; + } + + if ( ( nPos >= 0 ) && ( nPos < (long) m_vEntries.size() ) ) + { + m_bHasActive = true; + m_nActive = nPos; + m_vEntries[ nPos ]->m_bActive = true; + + if ( IsReallyVisible() ) + { + m_bAdjustActive = true; + } + } + + if ( IsReallyVisible() ) + { + m_bNeedsRecalc = true; + Invalidate(); + } + + guard.clear(); +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::DrawRow( const Rectangle& rRect, const TEntry_Impl pEntry ) +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + if ( pEntry->m_bActive ) + SetTextColor( rStyleSettings.GetHighlightTextColor() ); + else if ( ( pEntry->m_eState != REGISTERED ) && ( pEntry->m_eState != NOT_AVAILABLE ) ) + SetTextColor( rStyleSettings.GetDisableColor() ); + else if ( IsControlForeground() ) + SetTextColor( GetControlForeground() ); + else + SetTextColor( rStyleSettings.GetFieldTextColor() ); + + if ( pEntry->m_bActive ) + { + SetLineColor(); + SetFillColor( rStyleSettings.GetHighlightColor() ); + DrawRect( rRect ); + } + else + { + if( IsControlBackground() ) + SetBackground( GetControlBackground() ); + else + SetBackground( rStyleSettings.GetFieldColor() ); + + SetTextFillColor(); + Erase( rRect ); + } + + // Draw extension icon + Point aPos( rRect.TopLeft() ); + aPos += Point( TOP_OFFSET, TOP_OFFSET ); + Image aImage; + if ( ! pEntry->m_aIcon ) + aImage = m_aDefaultImage; + else + aImage = pEntry->m_aIcon; + Size aImageSize = aImage.GetSizePixel(); + if ( ( aImageSize.Width() <= ICON_WIDTH ) && ( aImageSize.Height() <= ICON_HEIGHT ) ) + DrawImage( Point( aPos.X()+((ICON_WIDTH-aImageSize.Width())/2), aPos.Y()+((ICON_HEIGHT-aImageSize.Height())/2) ), aImage ); + else + DrawImage( aPos, Size( ICON_WIDTH, ICON_HEIGHT ), aImage ); + + // Setup fonts + Font aStdFont( GetFont() ); + Font aBoldFont( aStdFont ); + aBoldFont.SetWeight( WEIGHT_BOLD ); + SetFont( aBoldFont ); + long aTextHeight = GetTextHeight(); + + // Init publisher link here + if ( !pEntry->m_pPublisher && pEntry->m_sPublisher.Len() ) + { + pEntry->m_pPublisher = new svt::FixedHyperlink( this ); + pEntry->m_pPublisher->SetBackground(); + pEntry->m_pPublisher->SetPaintTransparent( true ); + pEntry->m_pPublisher->SetURL( pEntry->m_sPublisherURL ); + pEntry->m_pPublisher->SetDescription( pEntry->m_sPublisher ); + Size aSize = FixedText::CalcMinimumTextSize( pEntry->m_pPublisher ); + pEntry->m_pPublisher->SetSizePixel( aSize ); + + if ( m_aClickHdl.IsSet() ) + pEntry->m_pPublisher->SetClickHdl( m_aClickHdl ); + } + + // Get max title width + long nMaxTitleWidth = rRect.GetWidth() - ICON_OFFSET; + nMaxTitleWidth -= ( 2 * SMALL_ICON_SIZE ) + ( 4 * SPACE_BETWEEN ); + if ( pEntry->m_pPublisher ) + { + nMaxTitleWidth -= pEntry->m_pPublisher->GetSizePixel().Width() + (2*SPACE_BETWEEN); + } + + long aVersionWidth = GetTextWidth( pEntry->m_sVersion ); + long aTitleWidth = GetTextWidth( pEntry->m_sTitle ) + (aTextHeight / 3); + + aPos = rRect.TopLeft() + Point( ICON_OFFSET, TOP_OFFSET ); + + if ( aTitleWidth > nMaxTitleWidth - aVersionWidth ) + { + aTitleWidth = nMaxTitleWidth - aVersionWidth - (aTextHeight / 3); + String aShortTitle = GetEllipsisString( pEntry->m_sTitle, aTitleWidth ); + DrawText( aPos, aShortTitle ); + aTitleWidth += (aTextHeight / 3); + } + else + DrawText( aPos, pEntry->m_sTitle ); + + SetFont( aStdFont ); + DrawText( Point( aPos.X() + aTitleWidth, aPos.Y() ), pEntry->m_sVersion ); + + long nIconHeight = TOP_OFFSET + SMALL_ICON_SIZE; + long nTitleHeight = TOP_OFFSET + GetTextHeight(); + if ( nIconHeight < nTitleHeight ) + aTextHeight = nTitleHeight; + else + aTextHeight = nIconHeight; + + // draw description + String sDescription; + if ( pEntry->m_sErrorText.Len() ) + { + if ( pEntry->m_bActive ) + sDescription = pEntry->m_sErrorText + OUSTR("\n") + pEntry->m_sDescription; + else + sDescription = pEntry->m_sErrorText; + } + else + sDescription = pEntry->m_sDescription; + + aPos.Y() += aTextHeight; + if ( pEntry->m_bActive ) + { + long nExtraHeight = 0; + + if ( pEntry->m_bHasButtons ) + nExtraHeight = m_nExtraHeight; + + DrawText( Rectangle( aPos.X(), aPos.Y(), rRect.Right(), rRect.Bottom() - nExtraHeight ), + sDescription, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK ); + } + else + { + const long nWidth = GetTextWidth( sDescription ); + if ( nWidth > rRect.GetWidth() - aPos.X() ) + sDescription = GetEllipsisString( sDescription, rRect.GetWidth() - aPos.X() ); + DrawText( aPos, sDescription ); + } + + // Draw publisher link + if ( pEntry->m_pPublisher ) + { + pEntry->m_pPublisher->Show(); + aPos = rRect.TopLeft() + Point( ICON_OFFSET + nMaxTitleWidth + (2*SPACE_BETWEEN), TOP_OFFSET ); + pEntry->m_pPublisher->SetPosPixel( aPos ); + } + + // Draw status icons + if ( !pEntry->m_bUser ) + { + aPos = rRect.TopRight() + Point( -(RIGHT_ICON_OFFSET + SMALL_ICON_SIZE), TOP_OFFSET ); + if ( pEntry->m_bLocked ) + DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), m_aLockedImage ); + else + DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), m_aSharedImage ); + } + if ( ( pEntry->m_eState == AMBIGUOUS ) || pEntry->m_bMissingDeps || pEntry->m_bMissingLic ) + { + aPos = rRect.TopRight() + Point( -(RIGHT_ICON_OFFSET + SPACE_BETWEEN + 2*SMALL_ICON_SIZE), TOP_OFFSET ); + DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), m_aWarningImage ); + } + + SetLineColor( Color( COL_LIGHTGRAY ) ); + DrawLine( rRect.BottomLeft(), rRect.BottomRight() ); +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::RecalcAll() +{ + if ( m_bHasActive ) + CalcActiveHeight( m_nActive ); + + SetupScrollBar(); + + if ( m_bHasActive ) + { + Rectangle aEntryRect = GetEntryRect( m_nActive ); + + if ( m_bAdjustActive ) + { + m_bAdjustActive = false; + + // If the top of the selected entry isn't visible, make it visible + if ( aEntryRect.Top() < 0 ) + { + m_nTopIndex += aEntryRect.Top(); + aEntryRect.Move( 0, -aEntryRect.Top() ); + } + + // If the bottom of the selected entry isn't visible, make it visible even if now the top + // isn't visible any longer ( the buttons are more important ) + Size aOutputSize = GetOutputSizePixel(); + if ( aEntryRect.Bottom() > aOutputSize.Height() ) + { + m_nTopIndex += ( aEntryRect.Bottom() - aOutputSize.Height() ); + aEntryRect.Move( 0, -( aEntryRect.Bottom() - aOutputSize.Height() ) ); + } + + // If there is unused space below the last entry but all entries don't fit into the box, + // move the content down to use the whole space + const long nTotalHeight = GetTotalHeight(); + if ( m_bHasScrollBar && ( aOutputSize.Height() + m_nTopIndex > nTotalHeight ) ) + { + long nOffset = m_nTopIndex; + m_nTopIndex = nTotalHeight - aOutputSize.Height(); + nOffset -= m_nTopIndex; + aEntryRect.Move( 0, nOffset ); + } + + if ( m_bHasScrollBar ) + m_pScrollBar->SetThumbPos( m_nTopIndex ); + } + } + + m_bNeedsRecalc = false; +} + +// ----------------------------------------------------------------------- +bool ExtensionBox_Impl::HandleTabKey( bool ) +{ + return false; +} + +// ----------------------------------------------------------------------- +bool ExtensionBox_Impl::HandleCursorKey( sal_uInt16 nKeyCode ) +{ + if ( m_vEntries.empty() ) + return true; + + long nSelect = 0; + + if ( m_bHasActive ) + { + long nPageSize = GetOutputSizePixel().Height() / m_nStdHeight; + if ( nPageSize < 2 ) + nPageSize = 2; + + if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_RIGHT ) ) + nSelect = m_nActive + 1; + else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_LEFT ) ) + nSelect = m_nActive - 1; + else if ( nKeyCode == KEY_HOME ) + nSelect = 0; + else if ( nKeyCode == KEY_END ) + nSelect = m_vEntries.size() - 1; + else if ( nKeyCode == KEY_PAGEUP ) + nSelect = m_nActive - nPageSize + 1; + else if ( nKeyCode == KEY_PAGEDOWN ) + nSelect = m_nActive + nPageSize - 1; + } + else // when there is no selected entry, we will select the first or the last. + { + if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_PAGEDOWN ) || ( nKeyCode == KEY_HOME ) ) + nSelect = 0; + else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_PAGEUP ) || ( nKeyCode == KEY_END ) ) + nSelect = m_vEntries.size() - 1; + } + + if ( nSelect < 0 ) + nSelect = 0; + if ( nSelect >= (long) m_vEntries.size() ) + nSelect = m_vEntries.size() - 1; + + selectEntry( nSelect ); + + return true; +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::Paint( const Rectangle &/*rPaintRect*/ ) +{ + if ( !m_bInDelete ) + DeleteRemoved(); + + if ( m_bNeedsRecalc ) + RecalcAll(); + + Point aStart( 0, -m_nTopIndex ); + Size aSize( GetOutputSizePixel() ); + + if ( m_bHasScrollBar ) + aSize.Width() -= m_pScrollBar->GetSizePixel().Width(); + + const ::osl::MutexGuard aGuard( m_entriesMutex ); + + typedef std::vector< TEntry_Impl >::iterator ITER; + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + aSize.Height() = (*iIndex)->m_bActive ? m_nActiveHeight : m_nStdHeight; + Rectangle aEntryRect( aStart, aSize ); + DrawRow( aEntryRect, *iIndex ); + aStart.Y() += aSize.Height(); + } +} + +// ----------------------------------------------------------------------- +long ExtensionBox_Impl::GetTotalHeight() const +{ + long nHeight = m_vEntries.size() * m_nStdHeight; + + if ( m_bHasActive ) + { + nHeight += m_nActiveHeight - m_nStdHeight; + } + + return nHeight; +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::SetupScrollBar() +{ + const Size aSize = GetOutputSizePixel(); + const long nScrBarSize = GetSettings().GetStyleSettings().GetScrollBarSize(); + const long nTotalHeight = GetTotalHeight(); + const bool bNeedsScrollBar = ( nTotalHeight > aSize.Height() ); + + if ( bNeedsScrollBar ) + { + if ( m_nTopIndex + aSize.Height() > nTotalHeight ) + m_nTopIndex = nTotalHeight - aSize.Height(); + + m_pScrollBar->SetPosSizePixel( Point( aSize.Width() - nScrBarSize, 0 ), + Size( nScrBarSize, aSize.Height() ) ); + m_pScrollBar->SetRangeMax( nTotalHeight ); + m_pScrollBar->SetVisibleSize( aSize.Height() ); + m_pScrollBar->SetPageSize( ( aSize.Height() * 4 ) / 5 ); + m_pScrollBar->SetLineSize( m_nStdHeight ); + m_pScrollBar->SetThumbPos( m_nTopIndex ); + + if ( !m_bHasScrollBar ) + m_pScrollBar->Show(); + } + else if ( m_bHasScrollBar ) + { + m_pScrollBar->Hide(); + m_nTopIndex = 0; + } + + m_bHasScrollBar = bNeedsScrollBar; +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::Resize() +{ + RecalcAll(); +} + +//------------------------------------------------------------------------------ +long ExtensionBox_Impl::PointToPos( const Point& rPos ) +{ + long nPos = ( rPos.Y() + m_nTopIndex ) / m_nStdHeight; + + if ( m_bHasActive && ( nPos > m_nActive ) ) + { + if ( rPos.Y() + m_nTopIndex <= m_nActive*m_nStdHeight + m_nActiveHeight ) + nPos = m_nActive; + else + nPos = ( rPos.Y() + m_nTopIndex - (m_nActiveHeight - m_nStdHeight) ) / m_nStdHeight; + } + + return nPos; +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::MouseButtonDown( const MouseEvent& rMEvt ) +{ + long nPos = PointToPos( rMEvt.GetPosPixel() ); + + if ( rMEvt.IsLeft() ) + { + if ( rMEvt.IsMod1() && m_bHasActive ) + selectEntry( m_vEntries.size() ); // Selecting an not existing entry will deselect the current one + else + selectEntry( nPos ); + } +} + +//------------------------------------------------------------------------------ +long ExtensionBox_Impl::Notify( NotifyEvent& rNEvt ) +{ + if ( !m_bInDelete ) + DeleteRemoved(); + + bool bHandled = false; + + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); + KeyCode aKeyCode = pKEvt->GetKeyCode(); + sal_uInt16 nKeyCode = aKeyCode.GetCode(); + + if ( nKeyCode == KEY_TAB ) + bHandled = HandleTabKey( aKeyCode.IsShift() ); + else if ( aKeyCode.GetGroup() == KEYGROUP_CURSOR ) + bHandled = HandleCursorKey( nKeyCode ); + } + + if ( rNEvt.GetType() == EVENT_COMMAND ) + { + if ( m_bHasScrollBar && + ( rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL ) ) + { + const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData(); + if ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) + { + long nThumbPos = m_pScrollBar->GetThumbPos(); + if ( pData->GetDelta() < 0 ) + m_pScrollBar->DoScroll( nThumbPos + m_nStdHeight ); + else + m_pScrollBar->DoScroll( nThumbPos - m_nStdHeight ); + bHandled = true; + } + } + } + + if ( !bHandled ) + return Control::Notify( rNEvt ); + else + return true; +} + +//------------------------------------------------------------------------------ +bool ExtensionBox_Impl::FindEntryPos( const TEntry_Impl pEntry, const long nStart, + const long nEnd, long &nPos ) +{ + nPos = nStart; + if ( nStart > nEnd ) + return false; + + StringCompare eCompare; + + if ( nStart == nEnd ) + { + eCompare = pEntry->CompareTo( m_pCollator, m_vEntries[ nStart ] ); + if ( eCompare == COMPARE_LESS ) + return false; + else if ( eCompare == COMPARE_EQUAL ) + { + //Workaround. See i86963. + if (pEntry->m_xPackage != m_vEntries[nStart]->m_xPackage) + return false; + + if ( m_bInCheckMode ) + m_vEntries[ nStart ]->m_bChecked = true; + return true; + } + else + { + nPos = nStart + 1; + return false; + } + } + + const long nMid = nStart + ( ( nEnd - nStart ) / 2 ); + eCompare = pEntry->CompareTo( m_pCollator, m_vEntries[ nMid ] ); + + if ( eCompare == COMPARE_LESS ) + return FindEntryPos( pEntry, nStart, nMid-1, nPos ); + else if ( eCompare == COMPARE_GREATER ) + return FindEntryPos( pEntry, nMid+1, nEnd, nPos ); + else + { + //Workaround.See i86963. + if (pEntry->m_xPackage != m_vEntries[nMid]->m_xPackage) + return false; + + if ( m_bInCheckMode ) + m_vEntries[ nMid ]->m_bChecked = true; + nPos = nMid; + return true; + } +} + +//------------------------------------------------------------------------------ +long ExtensionBox_Impl::addEntry( const uno::Reference< deployment::XPackage > &xPackage, + bool bLicenseMissing ) +{ + long nPos = 0; + PackageState eState = m_pManager->getPackageState( xPackage ); + bool bLocked = m_pManager->isReadOnly( xPackage ); + + TEntry_Impl pEntry( new Entry_Impl( xPackage, eState, bLocked ) ); + + // Don't add empty entries + if ( ! pEntry->m_sTitle.Len() ) + return 0; + + bool bNewEntryInserted = false; + + ::osl::ClearableMutexGuard guard(m_entriesMutex); + if ( m_vEntries.empty() ) + { + m_vEntries.push_back( pEntry ); + bNewEntryInserted = true; + } + else + { + if ( !FindEntryPos( pEntry, 0, m_vEntries.size()-1, nPos ) ) + { + m_vEntries.insert( m_vEntries.begin()+nPos, pEntry ); + bNewEntryInserted = true; + } + else if ( !m_bInCheckMode ) + { + OSL_FAIL( "ExtensionBox_Impl::addEntry(): Will not add duplicate entries" ); + } + } + + //Related: rhbz#702833 Only add a Listener if we're adding a new entry, to + //keep in sync with removeEventListener logic + if (bNewEntryInserted) + { + pEntry->m_xPackage->addEventListener(uno::Reference< lang::XEventListener > ( m_xRemoveListener, uno::UNO_QUERY ) ); + } + + + pEntry->m_bHasOptions = m_pManager->supportsOptions( xPackage ); + pEntry->m_bUser = xPackage->getRepositoryName().equals( USER_PACKAGE_MANAGER ); + pEntry->m_bShared = xPackage->getRepositoryName().equals( SHARED_PACKAGE_MANAGER ); + pEntry->m_bNew = m_bInCheckMode; + pEntry->m_bMissingLic = bLicenseMissing; + + if ( bLicenseMissing ) + pEntry->m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_MISSING_LICENSE ); + + //access to m_nActive must be guarded + if ( !m_bInCheckMode && m_bHasActive && ( m_nActive >= nPos ) ) + m_nActive += 1; + + guard.clear(); + + if ( IsReallyVisible() ) + Invalidate(); + + m_bNeedsRecalc = true; + + return nPos; +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::updateEntry( const uno::Reference< deployment::XPackage > &xPackage ) +{ + typedef std::vector< TEntry_Impl >::iterator ITER; + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + if ( (*iIndex)->m_xPackage == xPackage ) + { + PackageState eState = m_pManager->getPackageState( xPackage ); + (*iIndex)->m_bHasOptions = m_pManager->supportsOptions( xPackage ); + (*iIndex)->m_eState = eState; + (*iIndex)->m_sTitle = xPackage->getDisplayName(); + (*iIndex)->m_sVersion = xPackage->getVersion(); + (*iIndex)->m_sDescription = xPackage->getDescription(); + + if ( eState == REGISTERED ) + (*iIndex)->m_bMissingLic = false; + + if ( eState == AMBIGUOUS ) + (*iIndex)->m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_UNKNOWN_STATUS ); + else if ( ! (*iIndex)->m_bMissingLic ) + (*iIndex)->m_sErrorText = String(); + + if ( IsReallyVisible() ) + Invalidate(); + break; + } + } +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::removeEntry( const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( ! m_bInDelete ) + { + ::osl::ClearableMutexGuard aGuard( m_entriesMutex ); + + typedef std::vector< TEntry_Impl >::iterator ITER; + + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + if ( (*iIndex)->m_xPackage == xPackage ) + { + long nPos = iIndex - m_vEntries.begin(); + + // Entries mustn't removed here, because they contain a hyperlink control + // which can only be deleted when the thread has the solar mutex. Therefor + // the entry will be moved into the m_vRemovedEntries list which will be + // cleared on the next paint event + m_vRemovedEntries.push_back( *iIndex ); + m_vEntries.erase( iIndex ); + + m_bNeedsRecalc = true; + + if ( IsReallyVisible() ) + Invalidate(); + + if ( m_bHasActive ) + { + if ( nPos < m_nActive ) + m_nActive -= 1; + else if ( ( nPos == m_nActive ) && + ( nPos == (long) m_vEntries.size() ) ) + m_nActive -= 1; + + m_bHasActive = false; + //clear before calling out of this method + aGuard.clear(); + selectEntry( m_nActive ); + } + break; + } + } + } +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::RemoveUnlocked() +{ + bool bAllRemoved = false; + + while ( ! bAllRemoved ) + { + bAllRemoved = true; + + ::osl::ClearableMutexGuard aGuard( m_entriesMutex ); + + typedef std::vector< TEntry_Impl >::iterator ITER; + + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + if ( !(*iIndex)->m_bLocked ) + { + bAllRemoved = false; + uno::Reference< deployment::XPackage> xPackage = (*iIndex)->m_xPackage; + aGuard.clear(); + removeEntry( xPackage ); + break; + } + } + } +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::prepareChecking() +{ + m_bInCheckMode = true; + typedef std::vector< TEntry_Impl >::iterator ITER; + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + (*iIndex)->m_bChecked = false; + (*iIndex)->m_bNew = false; + } +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::checkEntries() +{ + long nNewPos = -1; + long nPos = 0; + bool bNeedsUpdate = false; + + ::osl::ClearableMutexGuard guard(m_entriesMutex); + typedef std::vector< TEntry_Impl >::iterator ITER; + ITER iIndex = m_vEntries.begin(); + while ( iIndex < m_vEntries.end() ) + { + if ( (*iIndex)->m_bChecked == false ) + { + (*iIndex)->m_bChecked = true; + bNeedsUpdate = true; + nPos = iIndex-m_vEntries.begin(); + if ( (*iIndex)->m_bNew ) + { // add entry to list and correct active pos + if ( nNewPos == - 1) + nNewPos = nPos; + if ( nPos <= m_nActive ) + m_nActive += 1; + ++iIndex; + } + else + { // remove entry from list + if ( nPos < m_nActive ) + m_nActive -= 1; + else if ( ( nPos == m_nActive ) && ( nPos == (long) m_vEntries.size() - 1 ) ) + m_nActive -= 1; + m_vRemovedEntries.push_back( *iIndex ); + m_vEntries.erase( iIndex ); + iIndex = m_vEntries.begin() + nPos; + } + } + else + ++iIndex; + } + guard.clear(); + + m_bInCheckMode = false; + + if ( nNewPos != - 1) + selectEntry( nNewPos ); + + if ( bNeedsUpdate ) + { + m_bNeedsRecalc = true; + if ( IsReallyVisible() ) + Invalidate(); + } +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::SetScrollHdl( const Link& rLink ) +{ + if ( m_pScrollBar ) + m_pScrollBar->SetScrollHdl( rLink ); +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::DoScroll( long nDelta ) +{ + m_nTopIndex += nDelta; + Point aNewSBPt( m_pScrollBar->GetPosPixel() ); + + Rectangle aScrRect( Point(), GetOutputSizePixel() ); + aScrRect.Right() -= m_pScrollBar->GetSizePixel().Width(); + Scroll( 0, -nDelta, aScrRect ); + + m_pScrollBar->SetPosPixel( aNewSBPt ); +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtensionBox_Impl, ScrollHdl, ScrollBar*, pScrBar ) +{ + DoScroll( pScrBar->GetDelta() ); + + return 1; +} + +} //namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_extlistbox.hxx b/desktop/source/deployment/gui/dp_gui_extlistbox.hxx new file mode 100644 index 000000000000..9dbbb7d33789 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_extlistbox.hxx @@ -0,0 +1,269 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "rtl/ustring.hxx" +#include "vcl/scrbar.hxx" +#include "vcl/fixed.hxx" +#include "vcl/dialog.hxx" + +#include "svtools/extensionlistbox.hxx" +#include "svtools/fixedhyper.hxx" +#include "cppuhelper/implbase1.hxx" +#include "unotools/collatorwrapper.hxx" + +#include "com/sun/star/lang/Locale.hpp" +#include "com/sun/star/lang/XEventListener.hpp" +#include "com/sun/star/deployment/XPackage.hpp" + +#include <boost/shared_ptr.hpp> + +namespace dp_gui { + +#define SMALL_ICON_SIZE 16 +#define TOP_OFFSET 5 +#define ICON_HEIGHT 42 +#define ICON_WIDTH 47 +#define ICON_OFFSET 72 +#define RIGHT_ICON_OFFSET 5 +#define SPACE_BETWEEN 3 + +class TheExtensionManager; + +typedef ::boost::shared_ptr< svt::FixedHyperlink > TFixedHyperlink; + +//------------------------------------------------------------------------------ +// struct Entry_Impl +//------------------------------------------------------------------------------ +struct Entry_Impl; + +typedef ::boost::shared_ptr< Entry_Impl > TEntry_Impl; + +struct Entry_Impl +{ + bool m_bActive :1; + bool m_bLocked :1; + bool m_bHasOptions :1; + bool m_bUser :1; + bool m_bShared :1; + bool m_bNew :1; + bool m_bChecked :1; + bool m_bMissingDeps :1; + bool m_bHasButtons :1; + bool m_bMissingLic :1; + PackageState m_eState; + String m_sTitle; + String m_sVersion; + String m_sDescription; + String m_sPublisher; + String m_sPublisherURL; + String m_sErrorText; + String m_sLicenseText; + Image m_aIcon; + Image m_aIconHC; + svt::FixedHyperlink *m_pPublisher; + + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> m_xPackage; + + Entry_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, + const PackageState eState, const bool bReadOnly ); + ~Entry_Impl(); + + StringCompare CompareTo( const CollatorWrapper *pCollator, const TEntry_Impl pEntry ) const; + void checkDependencies(); +}; + +//------------------------------------------------------------------------------ +// class ExtensionBox_Impl +//------------------------------------------------------------------------------ + +class ExtensionBox_Impl; + +//------------------------------------------------------------------------------ +class ExtensionRemovedListener : public ::cppu::WeakImplHelper1< ::com::sun::star::lang::XEventListener > +{ + ExtensionBox_Impl *m_pParent; + +public: + + ExtensionRemovedListener( ExtensionBox_Impl *pParent ) { m_pParent = pParent; } + ~ExtensionRemovedListener(); + + //=================================================================================== + // XEventListener + virtual void SAL_CALL disposing( ::com::sun::star::lang::EventObject const & evt ) + throw (::com::sun::star::uno::RuntimeException); +}; + +//------------------------------------------------------------------------------ +class ExtensionBox_Impl : public ::svt::IExtensionListBox +{ + bool m_bHasScrollBar; + bool m_bHasActive; + bool m_bNeedsRecalc; + bool m_bHasNew; + bool m_bInCheckMode; + bool m_bAdjustActive; + bool m_bInDelete; + //Must be guarded together with m_vEntries to ensure a valid index at all times. + //Use m_entriesMutex as guard. + long m_nActive; + long m_nTopIndex; + long m_nStdHeight; + long m_nActiveHeight; + long m_nExtraHeight; + Size m_aOutputSize; + Image m_aSharedImage; + Image m_aLockedImage; + Image m_aWarningImage; + Image m_aDefaultImage; + Link m_aClickHdl; + + ScrollBar *m_pScrollBar; + + com::sun::star::uno::Reference< ExtensionRemovedListener > m_xRemoveListener; + + TheExtensionManager *m_pManager; + //This mutex is used for synchronizing access to m_vEntries. + //Currently it is used to synchronize adding, removing entries and + //functions like getItemName, getItemDescription, etc. to prevent + //that m_vEntries is accessed at an invalid index. + //ToDo: There are many more places where m_vEntries is read and which may + //fail. For example the Paint method is probable called from the main thread + //while new entries are added / removed in a separate thread. + mutable ::osl::Mutex m_entriesMutex; + std::vector< TEntry_Impl > m_vEntries; + std::vector< TEntry_Impl > m_vRemovedEntries; + + ::com::sun::star::lang::Locale *m_pLocale; + CollatorWrapper *m_pCollator; + + void CalcActiveHeight( const long nPos ); + long GetTotalHeight() const; + void SetupScrollBar(); + void DrawRow( const Rectangle& rRect, const TEntry_Impl pEntry ); + bool HandleTabKey( bool bReverse ); + bool HandleCursorKey( sal_uInt16 nKeyCode ); + bool FindEntryPos( const TEntry_Impl pEntry, long nStart, long nEnd, long &nFound ); + void DeleteRemoved(); + + //----------------- + DECL_DLLPRIVATE_LINK( ScrollHdl, ScrollBar * ); + + //Index starts with 1. + //Throws an com::sun::star::lang::IllegalArgumentException, when the index is invalid. + void checkIndex(sal_Int32 pos) const; + + +public: + ExtensionBox_Impl( Dialog* pParent, TheExtensionManager *pManager ); + ~ExtensionBox_Impl(); + + virtual void MouseButtonDown( const MouseEvent& rMEvt ); + virtual void Paint( const Rectangle &rPaintRect ); + virtual void Resize(); + virtual long Notify( NotifyEvent& rNEvt ); + + const Size GetMinOutputSizePixel() const; + void SetExtraSize( long nSize ) { m_nExtraHeight = nSize; } + TEntry_Impl GetEntryData( long nPos ) { return m_vEntries[ nPos ]; } + long GetEntryCount() { return (long) m_vEntries.size(); } + Rectangle GetEntryRect( const long nPos ) const; + bool HasActive() { return m_bHasActive; } + long PointToPos( const Point& rPos ); + void SetScrollHdl( const Link& rLink ); + void DoScroll( long nDelta ); + void SetHyperlinkHdl( const Link& rLink ){ m_aClickHdl = rLink; } + virtual void RecalcAll(); + void RemoveUnlocked(); + + //----------------- + virtual void selectEntry( const long nPos ); + long addEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, + bool bLicenseMissing = false ); + void updateEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + void removeEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + + void prepareChecking(); + void checkEntries(); + + TheExtensionManager* getExtensionManager() const { return m_pManager; } + + //=================================================================================== + //These functions are used for automatic testing + + /** @return The count of the entries in the list box. */ + virtual sal_Int32 getItemCount() const; + + /** @return The index of the first selected entry in the list box. + When nothing is selected, which is the case when getItemCount returns '0', + then this function returns EXTENSION_LISTBOX_ENTRY_NOTFOUND */ + virtual sal_Int32 getSelIndex() const; + + /** @return The item name of the entry with the given index + The index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual ::rtl::OUString getItemName( sal_Int32 index ) const; + + /** @return The version string of the entry with the given index + The index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual ::rtl::OUString getItemVersion( sal_Int32 index ) const; + + /** @return The description string of the entry with the given index + The index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual ::rtl::OUString getItemDescription( sal_Int32 index ) const; + + /** @return The publisher string of the entry with the given index + The index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual ::rtl::OUString getItemPublisher( sal_Int32 index ) const; + + /** @return The link behind the publisher text of the entry with the given index + The index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual ::rtl::OUString getItemPublisherLink( sal_Int32 index ) const; + + /** The entry at the given position will be selected + Index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual void select( sal_Int32 pos ); + + /** The first found entry with the given name will be selected + When there was no entry found with the name, the selection doesn't change. + Please note that there might be more than one entry with the same + name, because: + 1. the name is not unique + 2. one extension can be installed as user and shared extension. + */ + virtual void select( const ::rtl::OUString & sName ); +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_service.cxx b/desktop/source/deployment/gui/dp_gui_service.cxx new file mode 100644 index 000000000000..efd055dc4d87 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_service.cxx @@ -0,0 +1,365 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_gui_shared.hxx" +#include "dp_gui.h" +#include "dp_gui_theextmgr.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "unotools/configmgr.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/unwrapargs.hxx" +#include <i18npool/mslangid.hxx> +#include "vcl/svapp.hxx" +#include "vcl/msgbox.hxx" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/task/XJobExecutor.hpp" +#include "com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp" + +#include "boost/bind.hpp" +#include "license_dialog.hxx" +#include "dp_gui_dialog2.hxx" +#include "dp_gui_extensioncmdqueue.hxx" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +namespace css = ::com::sun::star; +namespace dp_gui { + +//============================================================================== +class MyApp : public Application, private boost::noncopyable +{ +public: + MyApp(); + virtual ~MyApp(); + + // Application + virtual int Main(); +}; + +//______________________________________________________________________________ +MyApp::~MyApp() +{ +} + +//______________________________________________________________________________ +MyApp::MyApp() +{ +} + +//______________________________________________________________________________ +int MyApp::Main() +{ + return EXIT_SUCCESS; +} + + +namespace +{ + struct ProductName + : public rtl::Static< String, ProductName > {}; + struct Version + : public rtl::Static< String, Version > {}; + struct AboutBoxVersion + : public rtl::Static< String, AboutBoxVersion > {}; + struct OOOVendor + : public rtl::Static< String, OOOVendor > {}; + struct Extension + : public rtl::Static< String, Extension > {}; +} + +void ReplaceProductNameHookProc( String& rStr ) +{ + static int nAll = 0, nPro = 0; + + nAll++; + if ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND ) + { + String &rProductName = ProductName::get(); + String &rVersion = Version::get(); + String &rAboutBoxVersion = AboutBoxVersion::get(); + String &rExtension = Extension::get(); + String &rOOOVendor = OOOVendor::get(); + + if ( !rProductName.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ); + aRet >>= aTmp; + rProductName = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTVERSION ); + aRet >>= aTmp; + rVersion = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::ABOUTBOXPRODUCTVERSION ); + aRet >>= aTmp; + rAboutBoxVersion = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::OOOVENDOR ); + aRet >>= aTmp; + rOOOVendor = aTmp; + + if ( !rExtension.Len() ) + { + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTEXTENSION ); + aRet >>= aTmp; + rExtension = aTmp; + } + } + + nPro++; + rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", rProductName ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTVERSION", rVersion ); + rStr.SearchAndReplaceAllAscii( "%ABOUTBOXPRODUCTVERSION", rAboutBoxVersion ); + rStr.SearchAndReplaceAllAscii( "%OOOVENDOR", rOOOVendor ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTEXTENSION", rExtension ); + } +} + +//============================================================================== +class ServiceImpl + : public ::cppu::WeakImplHelper2<ui::dialogs::XAsynchronousExecutableDialog, + task::XJobExecutor> +{ + Reference<XComponentContext> const m_xComponentContext; + boost::optional< Reference<awt::XWindow> > /* const */ m_parent; + boost::optional<OUString> /* const */ m_view; + /* if true then this service is running in an unopkg process and not in an office process */ + boost::optional<sal_Bool> /* const */ m_unopkg; + boost::optional<OUString> m_extensionURL; + OUString m_initialTitle; + bool m_bShowUpdateOnly; + +public: + ServiceImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XAsynchronousExecutableDialog + virtual void SAL_CALL setDialogTitle( OUString const & aTitle ) + throw (RuntimeException); + virtual void SAL_CALL startExecuteModal( + Reference< ui::dialogs::XDialogClosedListener > const & xListener ) + throw (RuntimeException); + + // XJobExecutor + virtual void SAL_CALL trigger( OUString const & event ) + throw (RuntimeException); +}; + +//______________________________________________________________________________ +ServiceImpl::ServiceImpl( Sequence<Any> const& args, + Reference<XComponentContext> const& xComponentContext) + : m_xComponentContext(xComponentContext), + m_bShowUpdateOnly( false ) +{ + try { + comphelper::unwrapArgs( args, m_parent, m_view, m_unopkg ); + return; + } catch (css::lang::IllegalArgumentException & ) { + } + try { + comphelper::unwrapArgs( args, m_extensionURL); + } catch (css::lang::IllegalArgumentException & ) { + } + + ResHookProc pProc = ResMgr::GetReadStringHook(); + if ( !pProc ) + ResMgr::SetReadStringHook( ReplaceProductNameHookProc ); +} + +// XAsynchronousExecutableDialog +//______________________________________________________________________________ +void ServiceImpl::setDialogTitle( OUString const & title ) + throw (RuntimeException) +{ + if ( dp_gui::TheExtensionManager::s_ExtMgr.is() ) + { + const SolarMutexGuard guard; + ::rtl::Reference< ::dp_gui::TheExtensionManager > dialog( + ::dp_gui::TheExtensionManager::get( m_xComponentContext, + m_parent ? *m_parent : Reference<awt::XWindow>(), + m_extensionURL ? *m_extensionURL : OUString() ) ); + dialog->SetText( title ); + } + else + m_initialTitle = title; +} + +//______________________________________________________________________________ +void ServiceImpl::startExecuteModal( + Reference< ui::dialogs::XDialogClosedListener > const & xListener ) + throw (RuntimeException) +{ + bool bCloseDialog = true; // only used if m_bShowUpdateOnly is true + ::std::auto_ptr<Application> app; + //ToDo: synchronize access to s_dialog !!! + if (! dp_gui::TheExtensionManager::s_ExtMgr.is()) + { + const bool bAppUp = (GetpApp() != 0); + bool bOfficePipePresent; + try { + bOfficePipePresent = dp_misc::office_is_running(); + } + catch (Exception & exc) { + if (bAppUp) { + const SolarMutexGuard guard; + std::auto_ptr<ErrorBox> box( + new ErrorBox( Application::GetActiveTopWindow(), + WB_OK, exc.Message ) ); + box->Execute(); + } + throw; + } + + if (! bOfficePipePresent) { + OSL_ASSERT( ! bAppUp ); + app.reset( new MyApp ); + if (! InitVCL( Reference<lang::XMultiServiceFactory>( + m_xComponentContext->getServiceManager(), + UNO_QUERY_THROW ) )) + throw RuntimeException( OUSTR("Cannot initialize VCL!"), + static_cast<OWeakObject *>(this) ); + AllSettings as = app->GetSettings(); + OUString slang; + if (! (::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::LOCALE ) >>= slang)) + throw RuntimeException( OUSTR("Cannot determine language!"), + static_cast<OWeakObject *>(this) ); + as.SetUILanguage( MsLangId::convertIsoStringToLanguage( slang ) ); + app->SetSettings( as ); + String sTitle = ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTNAME).get<OUString>() + + String(static_cast<sal_Unicode>(' ')) + + ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTVERSION).get<OUString>(); + app->SetDisplayName(sTitle); + ExtensionCmdQueue::syncRepositories( m_xComponentContext ); + } + } + else + { + // When m_bShowUpdateOnly is set, we are inside the office and the user clicked + // the update notification icon in the menu bar. We must not close the extensions + // dialog after displaying the update dialog when it has been visible before + if ( m_bShowUpdateOnly ) + bCloseDialog = ! dp_gui::TheExtensionManager::s_ExtMgr->isVisible(); + } + + { + const SolarMutexGuard guard; + ::rtl::Reference< ::dp_gui::TheExtensionManager > myExtMgr( + ::dp_gui::TheExtensionManager::get( + m_xComponentContext, + m_parent ? *m_parent : Reference<awt::XWindow>(), + m_extensionURL ? *m_extensionURL : OUString() ) ); + myExtMgr->createDialog( false ); + if (m_initialTitle.getLength() > 0) { + myExtMgr->SetText( m_initialTitle ); + m_initialTitle = OUString(); + } + if ( m_bShowUpdateOnly ) + { + myExtMgr->checkUpdates( true, !bCloseDialog ); + if ( bCloseDialog ) + myExtMgr->Close(); + else + myExtMgr->ToTop( TOTOP_RESTOREWHENMIN ); + } + else + { + myExtMgr->Show(); + myExtMgr->ToTop( TOTOP_RESTOREWHENMIN ); + } + } + + if (app.get() != 0) { + Application::Execute(); + DeInitVCL(); + } + + if (xListener.is()) + xListener->dialogClosed( + ui::dialogs::DialogClosedEvent( + static_cast< ::cppu::OWeakObject * >(this), + sal_Int16(0)) ); +} + +// XJobExecutor +//______________________________________________________________________________ +void ServiceImpl::trigger( OUString const &rEvent ) throw (RuntimeException) +{ + if ( rEvent == OUSTR("SHOW_UPDATE_DIALOG") ) + m_bShowUpdateOnly = true; + else + m_bShowUpdateOnly = false; + + startExecuteModal( Reference< ui::dialogs::XDialogClosedListener >() ); +} + +namespace sdecl = comphelper::service_decl; +sdecl::class_<ServiceImpl, sdecl::with_args<true> > serviceSI; +sdecl::ServiceDecl const serviceDecl( + serviceSI, + "com.sun.star.comp.deployment.ui.PackageManagerDialog", + "com.sun.star.deployment.ui.PackageManagerDialog" ); + +sdecl::class_<LicenseDialog, sdecl::with_args<true> > licenseSI; +sdecl::ServiceDecl const licenseDecl( + licenseSI, + "com.sun.star.comp.deployment.ui.LicenseDialog", + "com.sun.star.deployment.ui.LicenseDialog" ); + +sdecl::class_<UpdateRequiredDialogService, sdecl::with_args<true> > updateSI; +sdecl::ServiceDecl const updateDecl( + updateSI, + "com.sun.star.comp.deployment.ui.UpdateRequiredDialog", + "com.sun.star.deployment.ui.UpdateRequiredDialog" ); +} // namespace dp_gui + +extern "C" { + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + sal_Char const * pImplName, + lang::XMultiServiceFactory * pServiceManager, + registry::XRegistryKey * pRegistryKey ) +{ + return component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, dp_gui::serviceDecl, dp_gui::licenseDecl, dp_gui::updateDecl ); +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_shared.hxx b/desktop/source/deployment/gui/dp_gui_shared.hxx new file mode 100644 index 000000000000..3e2db45bfdd7 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_shared.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if !defined INCLUDED_DP_GUI_SHARED_HXX +#define INCLUDED_DP_GUI_SHARED_HXX + +#include "unotools/configmgr.hxx" +#include "rtl/instance.hxx" +#include "tools/resmgr.hxx" + + +namespace css = ::com::sun::star; + +namespace dp_gui { + +struct DeploymentGuiResMgr : + public ::rtl::StaticWithInit< ResMgr *, DeploymentGuiResMgr > { + ResMgr * operator () () { + return ResMgr::CreateResMgr( "deploymentgui" ); + } +}; + +struct BrandName : public ::rtl::StaticWithInit< ::rtl::OUString, BrandName > { + const ::rtl::OUString operator () () { + return ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTNAME ).get< ::rtl::OUString >(); + } +}; + +class DpGuiResId : public ResId +{ +public: + DpGuiResId( sal_uInt16 nId ):ResId( nId, *DeploymentGuiResMgr::get() ) {} +}; + +} // namespace dp_gui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_theextmgr.cxx b/desktop/source/deployment/gui/dp_gui_theextmgr.cxx new file mode 100644 index 000000000000..c86d3e2ba90b --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_theextmgr.cxx @@ -0,0 +1,533 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "vcl/svapp.hxx" +#include "vcl/msgbox.hxx" + +#include "osl/mutex.hxx" + +#include "toolkit/helper/vclunohelper.hxx" + +#include "com/sun/star/beans/XPropertySet.hpp" + +#include "dp_gui_dialog2.hxx" +#include "dp_gui_extensioncmdqueue.hxx" +#include "dp_gui_theextmgr.hxx" +#include "dp_gui_theextmgr.hxx" +#include "dp_identifier.hxx" +#include "dp_update.hxx" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +#define USER_PACKAGE_MANAGER OUSTR("user") +#define SHARED_PACKAGE_MANAGER OUSTR("shared") +#define BUNDLED_PACKAGE_MANAGER OUSTR("bundled") + +using namespace ::com::sun::star; +using ::rtl::OUString; + +namespace dp_gui { + +//------------------------------------------------------------------------------ + +::rtl::Reference< TheExtensionManager > TheExtensionManager::s_ExtMgr; + +//------------------------------------------------------------------------------ +// TheExtensionManager +//------------------------------------------------------------------------------ + +TheExtensionManager::TheExtensionManager( Window *pParent, + const uno::Reference< uno::XComponentContext > &xContext ) : + m_xContext( xContext ), + m_pParent( pParent ), + m_pExtMgrDialog( NULL ), + m_pUpdReqDialog( NULL ), + m_pExecuteCmdQueue( NULL ) +{ + m_xExtensionManager = deployment::ExtensionManager::get( xContext ); + m_xExtensionManager->addModifyListener( this ); + + uno::Reference< lang::XMultiServiceFactory > xConfig( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.configuration.ConfigurationProvider"), xContext ), uno::UNO_QUERY_THROW); + uno::Any args[1]; + beans::PropertyValue aValue( OUSTR("nodepath"), 0, uno::Any( OUSTR("/org.openoffice.Office.OptionsDialog/Nodes") ), + beans::PropertyState_DIRECT_VALUE ); + args[0] <<= aValue; + m_xNameAccessNodes = uno::Reference< container::XNameAccess >( + xConfig->createInstanceWithArguments( OUSTR("com.sun.star.configuration.ConfigurationAccess"), + uno::Sequence< uno::Any >( args, 1 )), uno::UNO_QUERY_THROW); + + // get the 'get more extensions here' url + uno::Reference< container::XNameAccess > xNameAccessRepositories; + beans::PropertyValue aValue2( OUSTR("nodepath"), 0, uno::Any( OUSTR("/org.openoffice.Office.ExtensionManager/ExtensionRepositories") ), + beans::PropertyState_DIRECT_VALUE ); + args[0] <<= aValue2; + xNameAccessRepositories = uno::Reference< container::XNameAccess > ( + xConfig->createInstanceWithArguments( OUSTR("com.sun.star.configuration.ConfigurationAccess"), + uno::Sequence< uno::Any >( args, 1 )), uno::UNO_QUERY_THROW); + try + { //throws css::container::NoSuchElementException, css::lang::WrappedTargetException + uno::Any value = xNameAccessRepositories->getByName( OUSTR( "WebsiteLink" ) ); + m_sGetExtensionsURL = value.get< OUString > (); + } + catch ( uno::Exception& ) + {} + + if ( dp_misc::office_is_running() ) + { + // the registration should be done after the construction has been ended + // otherwise an exception prevents object creation, but it is registered as a listener + m_xDesktop.set( xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.frame.Desktop"), xContext ), uno::UNO_QUERY ); + if ( m_xDesktop.is() ) + m_xDesktop->addTerminateListener( this ); + } +} + +//------------------------------------------------------------------------------ +TheExtensionManager::~TheExtensionManager() +{ + if ( m_pUpdReqDialog ) + delete m_pUpdReqDialog; + if ( m_pExtMgrDialog ) + delete m_pExtMgrDialog; + if ( m_pExecuteCmdQueue ) + delete m_pExecuteCmdQueue; +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::createDialog( const bool bCreateUpdDlg ) +{ + const SolarMutexGuard guard; + + if ( bCreateUpdDlg ) + { + if ( !m_pUpdReqDialog ) + { + m_pUpdReqDialog = new UpdateRequiredDialog( NULL, this ); + delete m_pExecuteCmdQueue; + m_pExecuteCmdQueue = new ExtensionCmdQueue( (DialogHelper*) m_pUpdReqDialog, this, m_xContext ); + createPackageList(); + } + } + else if ( !m_pExtMgrDialog ) + { + m_pExtMgrDialog = new ExtMgrDialog( m_pParent, this ); + delete m_pExecuteCmdQueue; + m_pExecuteCmdQueue = new ExtensionCmdQueue( (DialogHelper*) m_pExtMgrDialog, this, m_xContext ); + m_pExtMgrDialog->setGetExtensionsURL( m_sGetExtensionsURL ); + createPackageList(); + } +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::Show() +{ + const SolarMutexGuard guard; + + getDialog()->Show(); +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::SetText( const ::rtl::OUString &rTitle ) +{ + const SolarMutexGuard guard; + + getDialog()->SetText( rTitle ); +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::ToTop( sal_uInt16 nFlags ) +{ + const SolarMutexGuard guard; + + getDialog()->ToTop( nFlags ); +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::Close() +{ + if ( m_pExtMgrDialog ) + return m_pExtMgrDialog->Close(); + else if ( m_pUpdReqDialog ) + return m_pUpdReqDialog->Close(); + else + return true; +} + +//------------------------------------------------------------------------------ +sal_Int16 TheExtensionManager::execute() +{ + sal_Int16 nRet = 0; + + if ( m_pUpdReqDialog ) + { + nRet = m_pUpdReqDialog->Execute(); + delete m_pUpdReqDialog; + m_pUpdReqDialog = NULL; + } + + return nRet; +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::isVisible() +{ + return getDialog()->IsVisible(); +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::checkUpdates( bool /* bShowUpdateOnly */, bool /*bParentVisible*/ ) +{ + std::vector< uno::Reference< deployment::XPackage > > vEntries; + uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages; + + try { + xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(), + uno::Reference< ucb::XCommandEnvironment >() ); + } catch ( deployment::DeploymentException & ) { + return false; + } catch ( ucb::CommandFailedException & ) { + return false; + } catch ( ucb::CommandAbortedException & ) { + return false; + } catch ( lang::IllegalArgumentException & e ) { + throw uno::RuntimeException( e.Message, e.Context ); + } + + for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i ) + { + uno::Reference< deployment::XPackage > xPackage = dp_misc::getExtensionWithHighestVersion(xAllPackages[i]); + OSL_ASSERT(xPackage.is()); + if ( xPackage.is() ) + { + vEntries.push_back( xPackage ); + } + } + + m_pExecuteCmdQueue->checkForUpdates( vEntries ); + return true; +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::installPackage( const OUString &rPackageURL, bool bWarnUser ) +{ + if ( rPackageURL.getLength() == 0 ) + return false; + + createDialog( false ); + + bool bInstall = true; + bool bInstallForAll = false; + + // DV! missing function is read only repository from extension manager + if ( !bWarnUser && ! m_xExtensionManager->isReadOnlyRepository( SHARED_PACKAGE_MANAGER ) ) + bInstall = getDialogHelper()->installForAllUsers( bInstallForAll ); + + if ( !bInstall ) + return false; + + if ( bInstallForAll ) + m_pExecuteCmdQueue->addExtension( rPackageURL, SHARED_PACKAGE_MANAGER, false ); + else + m_pExecuteCmdQueue->addExtension( rPackageURL, USER_PACKAGE_MANAGER, bWarnUser ); + + return true; +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::queryTermination() +{ + if ( dp_misc::office_is_running() ) + return true; + // the standalone application unopkg must not close ( and quit ) the dialog + // when there are still actions in the queue + return true; +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::terminateDialog() +{ + if ( ! dp_misc::office_is_running() ) + { + const SolarMutexGuard guard; + delete m_pExtMgrDialog; + m_pExtMgrDialog = NULL; + delete m_pUpdReqDialog; + m_pUpdReqDialog = NULL; + Application::Quit(); + } +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::createPackageList() +{ + uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages; + + try { + xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(), + uno::Reference< ucb::XCommandEnvironment >() ); + } catch ( deployment::DeploymentException & ) { + return; + } catch ( ucb::CommandFailedException & ) { + return; + } catch ( ucb::CommandAbortedException & ) { + return; + } catch ( lang::IllegalArgumentException & e ) { + throw uno::RuntimeException( e.Message, e.Context ); + } + + for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i ) + { + uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i]; + + for ( sal_Int32 j = 0; j < xPackageList.getLength(); ++j ) + { + uno::Reference< deployment::XPackage > xPackage = xPackageList[j]; + if ( xPackage.is() ) + { + PackageState eState = getPackageState( xPackage ); + getDialogHelper()->addPackageToList( xPackage ); + // When the package is enabled, we can stop here, otherwise we have to look for + // another version of this package + if ( ( eState == REGISTERED ) || ( eState == NOT_AVAILABLE ) ) + break; + } + } + } + + uno::Sequence< uno::Reference< deployment::XPackage > > xNoLicPackages; + xNoLicPackages = m_xExtensionManager->getExtensionsWithUnacceptedLicenses( SHARED_PACKAGE_MANAGER, + uno::Reference< ucb::XCommandEnvironment >() ); + for ( sal_Int32 i = 0; i < xNoLicPackages.getLength(); ++i ) + { + uno::Reference< deployment::XPackage > xPackage = xNoLicPackages[i]; + if ( xPackage.is() ) + { + getDialogHelper()->addPackageToList( xPackage, true ); + } + } +} + +//------------------------------------------------------------------------------ +PackageState TheExtensionManager::getPackageState( const uno::Reference< deployment::XPackage > &xPackage ) const +{ + try { + beans::Optional< beans::Ambiguous< sal_Bool > > option( + xPackage->isRegistered( uno::Reference< task::XAbortChannel >(), + uno::Reference< ucb::XCommandEnvironment >() ) ); + if ( option.IsPresent ) + { + ::beans::Ambiguous< sal_Bool > const & reg = option.Value; + if ( reg.IsAmbiguous ) + return AMBIGUOUS; + else + return reg.Value ? REGISTERED : NOT_REGISTERED; + } + else + return NOT_AVAILABLE; + } + catch ( uno::RuntimeException & ) { + throw; + } + catch ( uno::Exception & exc) { + (void) exc; + OSL_FAIL( ::rtl::OUStringToOString( exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + return NOT_AVAILABLE; + } +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::isReadOnly( const uno::Reference< deployment::XPackage > &xPackage ) const +{ + if ( m_xExtensionManager.is() && xPackage.is() ) + { + return m_xExtensionManager->isReadOnlyRepository( xPackage->getRepositoryName() ); + } + else + return true; +} + +//------------------------------------------------------------------------------ +// The function investigates if the extension supports options. +bool TheExtensionManager::supportsOptions( const uno::Reference< deployment::XPackage > &xPackage ) const +{ + bool bOptions = false; + + if ( ! xPackage->isBundle() ) + return false; + + beans::Optional< OUString > aId = xPackage->getIdentifier(); + + //a bundle must always have an id + OSL_ASSERT( aId.IsPresent ); + + //iterate over all available nodes + uno::Sequence< OUString > seqNames = m_xNameAccessNodes->getElementNames(); + + for ( int i = 0; i < seqNames.getLength(); i++ ) + { + uno::Any anyNode = m_xNameAccessNodes->getByName( seqNames[i] ); + //If we have a node then then it must contain the set of leaves. This is part of OptionsDialog.xcs + uno::Reference< XInterface> xIntNode = anyNode.get< uno::Reference< XInterface > >(); + uno::Reference< container::XNameAccess > xNode( xIntNode, uno::UNO_QUERY_THROW ); + + uno::Any anyLeaves = xNode->getByName( OUSTR("Leaves") ); + uno::Reference< XInterface > xIntLeaves = anyLeaves.get< uno::Reference< XInterface > >(); + uno::Reference< container::XNameAccess > xLeaves( xIntLeaves, uno::UNO_QUERY_THROW ); + + //iterate over all available leaves + uno::Sequence< OUString > seqLeafNames = xLeaves->getElementNames(); + for ( int j = 0; j < seqLeafNames.getLength(); j++ ) + { + uno::Any anyLeaf = xLeaves->getByName( seqLeafNames[j] ); + uno::Reference< XInterface > xIntLeaf = anyLeaf.get< uno::Reference< XInterface > >(); + uno::Reference< beans::XPropertySet > xLeaf( xIntLeaf, uno::UNO_QUERY_THROW ); + //investigate the Id property if it matches the extension identifier which + //has been passed in. + uno::Any anyValue = xLeaf->getPropertyValue( OUSTR("Id") ); + + OUString sId = anyValue.get< OUString >(); + if ( sId == aId.Value ) + { + bOptions = true; + break; + } + } + if ( bOptions ) + break; + } + return bOptions; +} + +//------------------------------------------------------------------------------ +// XEventListener +void TheExtensionManager::disposing( lang::EventObject const & rEvt ) + throw ( uno::RuntimeException ) +{ + bool shutDown = (rEvt.Source == m_xDesktop); + + if ( shutDown && m_xDesktop.is() ) + { + m_xDesktop->removeTerminateListener( this ); + m_xDesktop.clear(); + } + + if ( shutDown ) + { + if ( dp_misc::office_is_running() ) + { + const SolarMutexGuard guard; + delete m_pExtMgrDialog; + m_pExtMgrDialog = NULL; + delete m_pUpdReqDialog; + m_pUpdReqDialog = NULL; + } + s_ExtMgr.clear(); + } +} + +//------------------------------------------------------------------------------ +// XTerminateListener +void TheExtensionManager::queryTermination( ::lang::EventObject const & ) + throw ( frame::TerminationVetoException, uno::RuntimeException ) +{ + DialogHelper *pDialogHelper = getDialogHelper(); + + if ( m_pExecuteCmdQueue->isBusy() || ( pDialogHelper && pDialogHelper->isBusy() ) ) + { + ToTop( TOTOP_RESTOREWHENMIN ); + throw frame::TerminationVetoException( + OUSTR("The office cannot be closed while the Extension Manager is running"), + uno::Reference<XInterface>(static_cast<frame::XTerminateListener*>(this), uno::UNO_QUERY)); + } + else + { + if ( m_pExtMgrDialog ) + m_pExtMgrDialog->Close(); + if ( m_pUpdReqDialog ) + m_pUpdReqDialog->Close(); + } +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::notifyTermination( ::lang::EventObject const & rEvt ) + throw ( uno::RuntimeException ) +{ + disposing( rEvt ); +} + +//------------------------------------------------------------------------------ +// XModifyListener +void TheExtensionManager::modified( ::lang::EventObject const & /*rEvt*/ ) + throw ( uno::RuntimeException ) +{ + getDialogHelper()->prepareChecking(); + createPackageList(); + getDialogHelper()->checkEntries(); +} + +//------------------------------------------------------------------------------ +::rtl::Reference< TheExtensionManager > TheExtensionManager::get( const uno::Reference< uno::XComponentContext > &xContext, + const uno::Reference< awt::XWindow > &xParent, + const OUString & extensionURL ) +{ + if ( s_ExtMgr.is() ) + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + if ( extensionURL.getLength() ) + s_ExtMgr->installPackage( extensionURL, true ); + return s_ExtMgr; + } + + Window * pParent = DIALOG_NO_PARENT; + if ( xParent.is() ) + pParent = VCLUnoHelper::GetWindow(xParent); + + ::rtl::Reference<TheExtensionManager> that( new TheExtensionManager( pParent, xContext ) ); + + const SolarMutexGuard guard; + if ( ! s_ExtMgr.is() ) + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + s_ExtMgr = that; + } + + if ( extensionURL.getLength() ) + s_ExtMgr->installPackage( extensionURL, true ); + + return s_ExtMgr; +} + +} //namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_theextmgr.hxx b/desktop/source/deployment/gui/dp_gui_theextmgr.hxx new file mode 100644 index 000000000000..39bad610bb9a --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_theextmgr.hxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DP_GUI_THEEXTMGR_HXX +#define INCLUDED_DP_GUI_THEEXTMGR_HXX + +#include "comphelper/sequence.hxx" + +#include "cppuhelper/implbase2.hxx" + +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/frame/XDesktop.hpp" +#include "com/sun/star/frame/XTerminateListener.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/util/XModifyListener.hpp" + +#include "dp_gui.h" +#include "dp_gui_dialog2.hxx" +#include "dp_gui_updatedata.hxx" + +//============================================================================== +namespace dp_gui { + +//------------------------------------------------------------------------------ +class ExtensionCmdQueue; + +//------------------------------------------------------------------------------ +class TheExtensionManager : + public ::cppu::WeakImplHelper2< ::com::sun::star::frame::XTerminateListener, + ::com::sun::star::util::XModifyListener > +{ +private: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDesktop > m_xDesktop; + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > m_xExtensionManager; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xNameAccessNodes; + + Window *m_pParent; + ExtMgrDialog *m_pExtMgrDialog; + UpdateRequiredDialog *m_pUpdReqDialog; + ExtensionCmdQueue *m_pExecuteCmdQueue; + + ::rtl::OUString m_sGetExtensionsURL; + + void createPackageList(); + +public: + static ::rtl::Reference<TheExtensionManager> s_ExtMgr; + + TheExtensionManager( Window * pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > &xContext ); + ~TheExtensionManager(); + + void createDialog( const bool bCreateUpdDlg ); + sal_Int16 execute(); + + Dialog* getDialog() { return m_pExtMgrDialog ? (Dialog*) m_pExtMgrDialog : (Dialog*) m_pUpdReqDialog; } + DialogHelper* getDialogHelper() { return m_pExtMgrDialog ? (DialogHelper*) m_pExtMgrDialog : (DialogHelper*) m_pUpdReqDialog; } + ExtensionCmdQueue* getCmdQueue() const { return m_pExecuteCmdQueue; } + + void SetText( const ::rtl::OUString &rTitle ); + void Show(); + void ToTop( sal_uInt16 nFlags ); + bool Close(); + bool isVisible(); + + //----------------- + bool checkUpdates( bool showUpdateOnly, bool parentVisible ); + bool installPackage( const ::rtl::OUString &rPackageURL, bool bWarnUser = false ); + + bool queryTermination(); + void terminateDialog(); + + // Tools + bool supportsOptions( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + PackageState getPackageState( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > getContext() const { return m_xContext; } + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > getExtensionManager() const { return m_xExtensionManager; } + bool isReadOnly( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + + //----------------- + static ::rtl::Reference<TheExtensionManager> get( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> const & xContext, + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow> const & xParent = 0, + ::rtl::OUString const & view = ::rtl::OUString() ); + + // XEventListener + virtual void SAL_CALL disposing( ::com::sun::star::lang::EventObject const & evt ) + throw (::com::sun::star::uno::RuntimeException); + + // XTerminateListener + virtual void SAL_CALL queryTermination( ::com::sun::star::lang::EventObject const & evt ) + throw (::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL notifyTermination( ::com::sun::star::lang::EventObject const & evt ) + throw (::com::sun::star::uno::RuntimeException); + + // XModifyListener + virtual void SAL_CALL modified( ::com::sun::star::lang::EventObject const & evt ) + throw (::com::sun::star::uno::RuntimeException); +}; + +} // namespace dp_gui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_thread.cxx b/desktop/source/deployment/gui/dp_gui_thread.cxx new file mode 100644 index 000000000000..1ad857ad7b86 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_thread.cxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "sal/config.h" + +#include <cstddef> +#include <new> + +#include "osl/thread.hxx" +#include "salhelper/simplereferenceobject.hxx" + +#include "dp_gui_thread.hxx" + +using dp_gui::Thread; + +Thread::Thread() {} + +void Thread::launch() { + // Assumption is that osl::Thread::create returns normally iff it causes + // osl::Thread::run to start executing: + acquire(); + try { + create(); + } catch (...) { + release(); + throw; + } +} + +void * Thread::operator new(std::size_t size) + throw (std::bad_alloc) +{ + return SimpleReferenceObject::operator new(size); +} + +void Thread::operator delete(void * p) throw () { + SimpleReferenceObject::operator delete(p); +} + +Thread::~Thread() {} + +void Thread::run() { + try { + execute(); + } catch (...) { + // Work around the problem that onTerminated is not called if run throws + // an exception: + onTerminated(); + throw; + } +} + +void Thread::onTerminated() { + release(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_thread.hxx b/desktop/source/deployment/gui/dp_gui_thread.hxx new file mode 100644 index 000000000000..624624b0cb3f --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_thread.hxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_GUI_DP_GUI_THREAD_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_THREAD_HXX + +#include "sal/config.h" + +#include <cstddef> +#include <new> +#include "osl/thread.hxx" +#include "sal/types.h" +#include "salhelper/simplereferenceobject.hxx" + +/// @HTML + +namespace dp_gui { + +/** + A safe encapsulation of <code>osl::Thread</code>. +*/ +class Thread: public salhelper::SimpleReferenceObject, private osl::Thread { +public: + Thread(); + + /** + Launch the thread. + + <p>This function must be called at most once.</p> + */ + void launch(); + + using osl::Thread::join; + + static void * operator new(std::size_t size) throw (std::bad_alloc); + + static void operator delete(void * p) throw (); + +protected: + virtual ~Thread(); + + /** + The main function executed by the thread. + + <p>Any exceptions terminate the thread and are effectively ignored.</p> + */ + virtual void execute() = 0; + +private: + Thread(Thread &); // not defined + void operator =(Thread &); // not defined + + virtual void SAL_CALL run(); + + virtual void SAL_CALL onTerminated(); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updatedata.hxx b/desktop/source/deployment/gui/dp_gui_updatedata.hxx new file mode 100644 index 000000000000..9fb4b9f79816 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updatedata.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ +#if ! defined INCLUDED_DP_GUI_UPDATEDATA_HXX +#define INCLUDED_DP_GUI_UPDATEDATA_HXX + +#include "sal/config.h" +#include "tools/solar.h" +#include "rtl/ustring.hxx" +#include "com/sun/star/uno/Reference.hxx" + +#include <boost/shared_ptr.hpp> + + +namespace com { namespace sun { namespace star { namespace deployment { + class XPackage; +}}}} +namespace com { namespace sun { namespace star { namespace xml { namespace dom { + class XNode; +}}}}} + + +namespace dp_gui { + +struct UpdateData +{ + UpdateData( ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > const & aExt): + bIsShared(false), aInstalledPackage(aExt){}; + + //When entries added to the listbox then there can be one for the user update and one + //for the shared update. However, both list entries will contain the same UpdateData. + //isShared is used to indicate which one is used for the shared entry. + bool bIsShared; + + //The currently installed extension which is going to be updated. If the extension exist in + //multiple repositories then it is the one with the highest version. + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > aInstalledPackage; + + //The version of the update + ::rtl::OUString updateVersion; + + //For online update + // ====================== + // The content of the update information. + //Only if aUpdateInfo is set then there is an online update available with a better version + //than any of the currently installed extensions with the same identifier. + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > aUpdateInfo; + //The URL of the locally downloaded extension. It will only be set if there were no errors + //during the download + ::rtl::OUString sLocalURL; + //The URL of the website wher the download can be obtained. + ::rtl::OUString sWebsiteURL; + + //For local update + //===================== + //The locale extension which is used as update for the user or shared repository. + //If set then the data for the online update (aUpdateInfo, sLocalURL, sWebsiteURL) + //are to be ignored. + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > + aUpdateSource; + + // ID to find this entry in the update listbox + sal_uInt16 m_nID; + bool m_bIgnored; +}; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.cxx b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx new file mode 100644 index 000000000000..33306839a72f --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx @@ -0,0 +1,1440 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "sal/config.h" + +#include <cstddef> +#include <limits> +#include <map> +#include <memory> +#include <utility> +#include <vector> + + +#include "boost/optional.hpp" +#include "com/sun/star/awt/Rectangle.hpp" +#include "com/sun/star/awt/WindowAttribute.hpp" +#include "com/sun/star/awt/WindowClass.hpp" +#include "com/sun/star/awt/WindowDescriptor.hpp" +#include "com/sun/star/awt/XToolkit.hpp" +#include "com/sun/star/awt/XWindow.hpp" +#include "com/sun/star/awt/XWindowPeer.hpp" +#include "com/sun/star/beans/NamedValue.hpp" +#include "com/sun/star/beans/Optional.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/container/XNameContainer.hpp" +#include "com/sun/star/deployment/DeploymentException.hpp" +#include "com/sun/star/deployment/UpdateInformationProvider.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/XUpdateInformationProvider.hpp" +#include "com/sun/star/frame/XDesktop.hpp" +#include "com/sun/star/frame/XDispatch.hpp" +#include "com/sun/star/frame/XDispatchProvider.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/system/SystemShellExecuteFlags.hpp" +#include "com/sun/star/system/XSystemShellExecute.hpp" +#include "com/sun/star/task/XAbortChannel.hpp" +#include "com/sun/star/task/XJob.hpp" +#include "com/sun/star/ucb/CommandAbortedException.hpp" +#include "com/sun/star/ucb/CommandFailedException.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/URL.hpp" +#include "com/sun/star/util/XChangesBatch.hpp" +#include "com/sun/star/util/XURLTransformer.hpp" +#include "com/sun/star/xml/dom/XElement.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" +#include "osl/diagnose.h" +#include "rtl/bootstrap.hxx" +#include "rtl/ref.hxx" +#include "rtl/string.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "svtools/svlbitm.hxx" +#include "svtools/svlbox.hxx" +#include <svtools/controldims.hrc> +#include "svx/checklbx.hxx" +#include "tools/gen.hxx" +#include "tools/link.hxx" +#include "tools/resid.hxx" +#include "tools/resmgr.hxx" +#include "tools/solar.h" +#include "tools/string.hxx" +#include "vcl/button.hxx" +#include "vcl/dialog.hxx" +#include "vcl/fixed.hxx" +#include "vcl/image.hxx" +#include "vcl/msgbox.hxx" +#include "vcl/svapp.hxx" +#include "osl/mutex.hxx" + +#include "comphelper/processfactory.hxx" + +#include "dp_dependencies.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_identifier.hxx" +#include "dp_version.hxx" +#include "dp_misc.h" +#include "dp_update.hxx" + +#include "dp_gui.h" +#include "dp_gui.hrc" +#include "dp_gui_thread.hxx" +#include "dp_gui_updatedata.hxx" +#include "dp_gui_updatedialog.hxx" +#include "dp_gui_shared.hxx" + +class KeyEvent; +class MouseEvent; +class Window; +namespace com { namespace sun { namespace star { namespace uno { + class XComponentContext; +} } } } + +using namespace ::com::sun::star; +using dp_gui::UpdateDialog; + +namespace { + +static sal_Unicode const LF = 0x000A; +static sal_Unicode const CR = 0x000D; +static const sal_uInt16 CMD_ENABLE_UPDATE = 1; +static const sal_uInt16 CMD_IGNORE_UPDATE = 2; +static const sal_uInt16 CMD_IGNORE_ALL_UPDATES = 3; + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +#define IGNORED_UPDATES OUSTR("/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/IgnoredUpdates") +#define PROPERTY_VERSION OUSTR("Version") + +enum Kind { ENABLED_UPDATE, DISABLED_UPDATE, SPECIFIC_ERROR }; + +rtl::OUString confineToParagraph(rtl::OUString const & text) { + // Confine arbitrary text to a single paragraph in a dp_gui::AutoScrollEdit. + // This assumes that U+000A and U+000D are the only paragraph separators in + // a dp_gui::AutoScrollEdit, and that replacing them with a single space + // each is acceptable: + return text.replace(LF, ' ').replace(CR, ' '); +} +} + +struct UpdateDialog::DisabledUpdate { + rtl::OUString name; + uno::Sequence< rtl::OUString > unsatisfiedDependencies; + // We also want to show release notes and publisher for disabled updates + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > aUpdateInfo; + sal_uInt16 m_nID; +}; + +struct UpdateDialog::SpecificError { + rtl::OUString name; + rtl::OUString message; + sal_uInt16 m_nID; +}; + +//------------------------------------------------------------------------------ +struct UpdateDialog::IgnoredUpdate { + rtl::OUString sExtensionID; + rtl::OUString sVersion; + bool bRemoved; + + IgnoredUpdate( const rtl::OUString &rExtensionID, const rtl::OUString &rVersion ); +}; + +//------------------------------------------------------------------------------ +UpdateDialog::IgnoredUpdate::IgnoredUpdate( const rtl::OUString &rExtensionID, const rtl::OUString &rVersion ): + sExtensionID( rExtensionID ), + sVersion( rVersion ), + bRemoved( false ) +{} + +//------------------------------------------------------------------------------ +struct UpdateDialog::Index +{ + Kind m_eKind; + bool m_bIgnored; + sal_uInt16 m_nID; + sal_uInt16 m_nIndex; + rtl::OUString m_aName; + + Index( Kind theKind, sal_uInt16 nID, sal_uInt16 nIndex, const rtl::OUString &rName ); +}; + +//------------------------------------------------------------------------------ +UpdateDialog::Index::Index( Kind theKind, sal_uInt16 nID, sal_uInt16 nIndex, const rtl::OUString &rName ): + m_eKind( theKind ), + m_bIgnored( false ), + m_nID( nID ), + m_nIndex( nIndex ), + m_aName( rName ) +{} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +class UpdateDialog::Thread: public dp_gui::Thread { +public: + Thread( + uno::Reference< uno::XComponentContext > const & context, + UpdateDialog & dialog, + const std::vector< uno::Reference< deployment::XPackage > > & vExtensionList); + + void stop(); + +private: + Thread(UpdateDialog::Thread &); // not defined + void operator =(UpdateDialog::Thread &); // not defined + + virtual ~Thread(); + + virtual void execute(); + + void handleSpecificError( + uno::Reference< deployment::XPackage > const & package, + uno::Any const & exception) const; + + uno::Sequence< uno::Reference< xml::dom::XElement > > + getUpdateInformation( + uno::Reference< deployment::XPackage > const & package, + uno::Sequence< rtl::OUString > const & urls, + rtl::OUString const & identifier) const; + + ::rtl::OUString getUpdateDisplayString( + dp_gui::UpdateData const & data, ::rtl::OUString const & version = ::rtl::OUString()) const; + + void prepareUpdateData( + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > const & updateInfo, + UpdateDialog::DisabledUpdate & out_du, + dp_gui::UpdateData & out_data) const; + + bool update( + UpdateDialog::DisabledUpdate & du, + dp_gui::UpdateData & data) const; + + uno::Reference< uno::XComponentContext > m_context; + UpdateDialog & m_dialog; + std::vector< uno::Reference< deployment::XPackage > > m_vExtensionList; + uno::Reference< deployment::XUpdateInformationProvider > m_updateInformation; + uno::Reference< task::XInteractionHandler > m_xInteractionHdl; + + // guarded by Application::GetSolarMutex(): + uno::Reference< task::XAbortChannel > m_abort; + bool m_stop; +}; + +UpdateDialog::Thread::Thread( + uno::Reference< uno::XComponentContext > const & context, + UpdateDialog & dialog, + const std::vector< uno::Reference< deployment::XPackage > > &vExtensionList): + m_context(context), + m_dialog(dialog), + m_vExtensionList(vExtensionList), + m_updateInformation( + deployment::UpdateInformationProvider::create(context)), + m_stop(false) +{ + if( m_context.is() ) + { + uno::Reference< lang::XMultiComponentFactory > xServiceManager( m_context->getServiceManager() ); + + if( xServiceManager.is() ) + { + m_xInteractionHdl = uno::Reference< task::XInteractionHandler > ( + xServiceManager->createInstanceWithContext( OUSTR( "com.sun.star.task.InteractionHandler" ), m_context), + uno::UNO_QUERY ); + if ( m_xInteractionHdl.is() ) + m_updateInformation->setInteractionHandler( m_xInteractionHdl ); + } + } +} + +void UpdateDialog::Thread::stop() { + uno::Reference< task::XAbortChannel > abort; + { + SolarMutexGuard g; + abort = m_abort; + m_stop = true; + } + if (abort.is()) { + abort->sendAbort(); + } + m_updateInformation->cancel(); +} + +UpdateDialog::Thread::~Thread() +{ + if ( m_xInteractionHdl.is() ) + m_updateInformation->setInteractionHandler( uno::Reference< task::XInteractionHandler > () ); +} + +void UpdateDialog::Thread::execute() +{ + { + SolarMutexGuard g; + if ( m_stop ) { + return; + } + } + uno::Reference<deployment::XExtensionManager> extMgr = + deployment::ExtensionManager::get(m_context); + + std::vector<std::pair<uno::Reference<deployment::XPackage>, uno::Any > > errors; + + dp_misc::UpdateInfoMap updateInfoMap = dp_misc::getOnlineUpdateInfos( + m_context, extMgr, m_updateInformation, &m_vExtensionList, errors); + + typedef std::vector<std::pair<uno::Reference<deployment::XPackage>, + uno::Any> >::const_iterator ITERROR; + for (ITERROR ite = errors.begin(); ite != errors.end(); ++ite ) + handleSpecificError(ite->first, ite->second); + + for (dp_misc::UpdateInfoMap::iterator i(updateInfoMap.begin()); i != updateInfoMap.end(); ++i) + { + dp_misc::UpdateInfo const & info = i->second; + UpdateData updateData(info.extension); + DisabledUpdate disableUpdate; + //determine if online updates meet the requirements + prepareUpdateData(info.info, disableUpdate, updateData); + + //determine if the update is installed in the user or shared repository + rtl::OUString sOnlineVersion; + if (info.info.is()) + sOnlineVersion = info.version; + rtl::OUString sVersionUser; + rtl::OUString sVersionShared; + rtl::OUString sVersionBundled; + uno::Sequence< uno::Reference< deployment::XPackage> > extensions; + try { + extensions = extMgr->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(info.extension), info.extension->getName(), + uno::Reference<ucb::XCommandEnvironment>()); + } catch (lang::IllegalArgumentException& ) { + OSL_ASSERT(0); + continue; + } catch (css::ucb::CommandFailedException& ) { + OSL_ASSERT(0); + continue; + } + OSL_ASSERT(extensions.getLength() == 3); + if (extensions[0].is() ) + sVersionUser = extensions[0]->getVersion(); + if (extensions[1].is() ) + sVersionShared = extensions[1]->getVersion(); + if (extensions[2].is() ) + sVersionBundled = extensions[2]->getVersion(); + + bool bSharedReadOnly = extMgr->isReadOnlyRepository(OUSTR("shared")); + + dp_misc::UPDATE_SOURCE sourceUser = dp_misc::isUpdateUserExtension( + bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion); + dp_misc::UPDATE_SOURCE sourceShared = dp_misc::isUpdateSharedExtension( + bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion); + + uno::Reference<deployment::XPackage> updateSource; + if (sourceUser != dp_misc::UPDATE_SOURCE_NONE) + { + if (sourceUser == dp_misc::UPDATE_SOURCE_SHARED) + { + updateData.aUpdateSource = extensions[1]; + updateData.updateVersion = extensions[1]->getVersion(); + } + else if (sourceUser == dp_misc::UPDATE_SOURCE_BUNDLED) + { + updateData.aUpdateSource = extensions[2]; + updateData.updateVersion = extensions[2]->getVersion(); + } + if (!update(disableUpdate, updateData)) + return; + } + + if (sourceShared != dp_misc::UPDATE_SOURCE_NONE) + { + if (sourceShared == dp_misc::UPDATE_SOURCE_BUNDLED) + { + updateData.aUpdateSource = extensions[2]; + updateData.updateVersion = extensions[2]->getVersion(); + } + updateData.bIsShared = true; + if (!update(disableUpdate, updateData)) + return; + } + } + + + SolarMutexGuard g; + if (!m_stop) { + m_dialog.checkingDone(); + } +} + +//Parameter package can be null +void UpdateDialog::Thread::handleSpecificError( + uno::Reference< deployment::XPackage > const & package, + uno::Any const & exception) const +{ + UpdateDialog::SpecificError data; + if (package.is()) + data.name = package->getDisplayName(); + uno::Exception e; + if (exception >>= e) { + data.message = e.Message; + } + SolarMutexGuard g; + if (!m_stop) { + m_dialog.addSpecificError(data); + } +} + +::rtl::OUString UpdateDialog::Thread::getUpdateDisplayString( + dp_gui::UpdateData const & data, ::rtl::OUString const & version) const +{ + OSL_ASSERT(data.aInstalledPackage.is()); + rtl::OUStringBuffer b(data.aInstalledPackage->getDisplayName()); + b.append(static_cast< sal_Unicode >(' ')); + { + SolarMutexGuard g; + if(!m_stop) + b.append(m_dialog.m_version); + } + b.append(static_cast< sal_Unicode >(' ')); + if (version.getLength()) + b.append(version); + else + b.append(data.updateVersion); + + if (data.sWebsiteURL.getLength()) + { + b.append(static_cast< sal_Unicode >(' ')); + { + SolarMutexGuard g; + if(!m_stop) + b.append(m_dialog.m_browserbased); + } + } + return b.makeStringAndClear(); +} + +/** out_data will only be filled if all dependencies are ok. + */ +void UpdateDialog::Thread::prepareUpdateData( + uno::Reference< xml::dom::XNode > const & updateInfo, + UpdateDialog::DisabledUpdate & out_du, + dp_gui::UpdateData & out_data) const +{ + if (!updateInfo.is()) + return; + dp_misc::DescriptionInfoset infoset(m_context, updateInfo); + OSL_ASSERT(infoset.getVersion().getLength() != 0); + uno::Sequence< uno::Reference< xml::dom::XElement > > ds( + dp_misc::Dependencies::check(infoset)); + + out_du.aUpdateInfo = updateInfo; + out_du.unsatisfiedDependencies.realloc(ds.getLength()); + for (sal_Int32 i = 0; i < ds.getLength(); ++i) { + out_du.unsatisfiedDependencies[i] = dp_misc::Dependencies::getErrorText(ds[i]); + } + + const ::boost::optional< ::rtl::OUString> updateWebsiteURL(infoset.getLocalizedUpdateWebsiteURL()); + + out_du.name = getUpdateDisplayString(out_data, infoset.getVersion()); + + if (out_du.unsatisfiedDependencies.getLength() == 0) + { + out_data.aUpdateInfo = updateInfo; + out_data.updateVersion = infoset.getVersion(); + if (updateWebsiteURL) + out_data.sWebsiteURL = *updateWebsiteURL; + } +} + +bool UpdateDialog::Thread::update( + UpdateDialog::DisabledUpdate & du, + dp_gui::UpdateData & data) const +{ + bool ret = false; + if (du.unsatisfiedDependencies.getLength() == 0) + { + SolarMutexGuard g; + if (!m_stop) { + m_dialog.addEnabledUpdate(getUpdateDisplayString(data), data); + } + ret = !m_stop; + } else { + SolarMutexGuard g; + if (!m_stop) { + m_dialog.addDisabledUpdate(du); + } + ret = !m_stop; + } + return ret; +} + +// UpdateDialog ---------------------------------------------------------- +UpdateDialog::UpdateDialog( + uno::Reference< uno::XComponentContext > const & context, + Window * parent, + const std::vector<uno::Reference< deployment::XPackage > > &vExtensionList, + std::vector< dp_gui::UpdateData > * updateData): + ModalDialog(parent,DpGuiResId(RID_DLG_UPDATE)), + m_context(context), + m_checking(this, DpGuiResId(RID_DLG_UPDATE_CHECKING)), + m_throbber(this, DpGuiResId(RID_DLG_UPDATE_THROBBER)), + m_update(this, DpGuiResId(RID_DLG_UPDATE_UPDATE)), + m_updates( + *this, DpGuiResId(RID_DLG_UPDATE_UPDATES), + Image(DpGuiResId(RID_DLG_UPDATE_NORMALALERT))), + m_all(this, DpGuiResId(RID_DLG_UPDATE_ALL)), + m_description(this, DpGuiResId(RID_DLG_UPDATE_DESCRIPTION)), + m_PublisherLabel(this, DpGuiResId(RID_DLG_UPDATE_PUBLISHER_LABEL)), + m_PublisherLink(this, DpGuiResId(RID_DLG_UPDATE_PUBLISHER_LINK)), + m_ReleaseNotesLabel(this, DpGuiResId(RID_DLG_UPDATE_RELEASENOTES_LABEL)), + m_ReleaseNotesLink(this, DpGuiResId(RID_DLG_UPDATE_RELEASENOTES_LINK)), + m_descriptions(this, DpGuiResId(RID_DLG_UPDATE_DESCRIPTIONS)), + m_line(this, DpGuiResId(RID_DLG_UPDATE_LINE)), + m_help(this, DpGuiResId(RID_DLG_UPDATE_HELP)), + m_ok(this, DpGuiResId(RID_DLG_UPDATE_OK)), + m_close(this, DpGuiResId(RID_DLG_UPDATE_CLOSE)), + m_error(String(DpGuiResId(RID_DLG_UPDATE_ERROR))), + m_none(String(DpGuiResId(RID_DLG_UPDATE_NONE))), + m_noInstallable(String(DpGuiResId(RID_DLG_UPDATE_NOINSTALLABLE))), + m_failure(String(DpGuiResId(RID_DLG_UPDATE_FAILURE))), + m_unknownError(String(DpGuiResId(RID_DLG_UPDATE_UNKNOWNERROR))), + m_noDescription(String(DpGuiResId(RID_DLG_UPDATE_NODESCRIPTION))), + m_noInstall(String(DpGuiResId(RID_DLG_UPDATE_NOINSTALL))), + m_noDependency(String(DpGuiResId(RID_DLG_UPDATE_NODEPENDENCY))), + m_noDependencyCurVer(String(DpGuiResId(RID_DLG_UPDATE_NODEPENDENCY_CUR_VER))), + m_browserbased(String(DpGuiResId(RID_DLG_UPDATE_BROWSERBASED))), + m_version(String(DpGuiResId(RID_DLG_UPDATE_VERSION))), + m_ignoredUpdate(String(DpGuiResId(RID_DLG_UPDATE_IGNORED_UPDATE))), + m_updateData(*updateData), + m_thread( + new UpdateDialog::Thread( + context, *this, vExtensionList)), + m_nFirstLineDelta(0), + m_nOneLineMissing(0), + m_nLastID(1), + m_bModified( false ) + // TODO: check! +// , +// m_extensionManagerDialog(extensionManagerDialog) +{ + OSL_ASSERT(updateData != NULL); + + m_xExtensionManager = deployment::ExtensionManager::get( context ); + + uno::Reference< awt::XToolkit > toolkit; + try { + toolkit = uno::Reference< awt::XToolkit >( + (uno::Reference< lang::XMultiComponentFactory >( + m_context->getServiceManager(), + uno::UNO_QUERY_THROW)-> + createInstanceWithContext( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit")), + m_context)), + uno::UNO_QUERY_THROW); + } catch (uno::RuntimeException &) { + throw; + } catch (uno::Exception & e) { + throw uno::RuntimeException(e.Message, e.Context); + } + m_updates.SetSelectHdl(LINK(this, UpdateDialog, selectionHandler)); + m_all.SetToggleHdl(LINK(this, UpdateDialog, allHandler)); + m_ok.SetClickHdl(LINK(this, UpdateDialog, okHandler)); + m_close.SetClickHdl(LINK(this, UpdateDialog, closeHandler)); + if ( ! dp_misc::office_is_running()) + m_help.Disable(); + FreeResource(); + + initDescription(); + getIgnoredUpdates(); +} + +//------------------------------------------------------------------------------ +UpdateDialog::~UpdateDialog() +{ + storeIgnoredUpdates(); + + for ( std::vector< UpdateDialog::Index* >::iterator i( m_ListboxEntries.begin() ); i != m_ListboxEntries.end(); ++i ) + { + delete (*i); + } + for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i ) + { + delete (*i); + } +} + +//------------------------------------------------------------------------------ +sal_Bool UpdateDialog::Close() { + m_thread->stop(); + return ModalDialog::Close(); +} + +short UpdateDialog::Execute() { + m_throbber.start(); + m_thread->launch(); + return ModalDialog::Execute(); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +UpdateDialog::CheckListBox::CheckListBox( UpdateDialog & dialog, ResId const & resource, + Image const & normalStaticImage ): + SvxCheckListBox( &dialog, resource, normalStaticImage ), + m_ignoreUpdate( String( DpGuiResId( RID_DLG_UPDATE_IGNORE ) ) ), + m_ignoreAllUpdates( String( DpGuiResId( RID_DLG_UPDATE_IGNORE_ALL ) ) ), + m_enableUpdate( String( DpGuiResId( RID_DLG_UPDATE_ENABLE ) ) ), + m_dialog(dialog) +{} + +//------------------------------------------------------------------------------ +UpdateDialog::CheckListBox::~CheckListBox() {} + +//------------------------------------------------------------------------------ +sal_uInt16 UpdateDialog::CheckListBox::getItemCount() const { + sal_uLong i = GetEntryCount(); + OSL_ASSERT(i <= std::numeric_limits< sal_uInt16 >::max()); + return sal::static_int_cast< sal_uInt16 >(i); +} + +//------------------------------------------------------------------------------ +void UpdateDialog::CheckListBox::MouseButtonDown( MouseEvent const & event ) +{ + // When clicking on a selected entry in an SvxCheckListBox, the entry's + // checkbox is toggled on mouse button down: + SvxCheckListBox::MouseButtonDown( event ); + + if ( event.IsRight() ) + { + handlePopupMenu( event.GetPosPixel() ); + } + + m_dialog.enableOk(); +} + +//------------------------------------------------------------------------------ +void UpdateDialog::CheckListBox::MouseButtonUp(MouseEvent const & event) { + // When clicking on an entry's checkbox in an SvxCheckListBox, the entry's + // checkbox is toggled on mouse button up: + SvxCheckListBox::MouseButtonUp(event); + m_dialog.enableOk(); +} + +void UpdateDialog::CheckListBox::KeyInput(KeyEvent const & event) { + SvxCheckListBox::KeyInput(event); + m_dialog.enableOk(); +} + +//------------------------------------------------------------------------------ +void UpdateDialog::CheckListBox::handlePopupMenu( const Point &rPos ) +{ + SvListEntry *pData = GetEntry( rPos ); + + if ( pData ) + { + sal_uInt16 nEntryPos = GetSelectEntryPos(); + UpdateDialog::Index * p = static_cast< UpdateDialog::Index * >( GetEntryData( nEntryPos ) ); + + if ( ( p->m_eKind == ENABLED_UPDATE ) || ( p->m_eKind == DISABLED_UPDATE ) ) + { + PopupMenu aPopup; + + if ( p->m_bIgnored ) + aPopup.InsertItem( CMD_ENABLE_UPDATE, m_enableUpdate ); + else + { + aPopup.InsertItem( CMD_IGNORE_UPDATE, m_ignoreUpdate ); + aPopup.InsertItem( CMD_IGNORE_ALL_UPDATES, m_ignoreAllUpdates ); + } + + sal_uInt16 aCmd = aPopup.Execute( this, rPos ); + if ( ( aCmd == CMD_IGNORE_UPDATE ) || ( aCmd == CMD_IGNORE_ALL_UPDATES ) ) + { + p->m_bIgnored = true; + if ( p->m_eKind == ENABLED_UPDATE ) + { + RemoveEntry( nEntryPos ); + m_dialog.addAdditional( p, SvLBoxButtonKind_disabledCheckbox ); + } + if ( aCmd == CMD_IGNORE_UPDATE ) + m_dialog.setIgnoredUpdate( p, true, false ); + else + m_dialog.setIgnoredUpdate( p, true, true ); + // TODO: reselect entry to display new description! + } + else if ( aCmd == CMD_ENABLE_UPDATE ) + { + p->m_bIgnored = false; + if ( p->m_eKind == ENABLED_UPDATE ) + { + RemoveEntry( nEntryPos ); + m_dialog.insertItem( p, SvLBoxButtonKind_enabledCheckbox ); + } + m_dialog.setIgnoredUpdate( p, false, false ); + } + } + } +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +sal_uInt16 UpdateDialog::insertItem( UpdateDialog::Index *pEntry, SvLBoxButtonKind kind ) +{ + m_updates.InsertEntry( pEntry->m_aName, LISTBOX_APPEND, static_cast< void * >( pEntry ), kind ); + + for ( sal_uInt16 i = m_updates.getItemCount(); i != 0 ; ) + { + i -= 1; + UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( m_updates.GetEntryData( i ) ); + if ( p == pEntry ) + return i; + } + OSL_ASSERT(0); + return 0; +} + +//------------------------------------------------------------------------------ +void UpdateDialog::addAdditional( UpdateDialog::Index * index, SvLBoxButtonKind kind ) +{ + m_all.Enable(); + if (m_all.IsChecked()) + { + insertItem( index, kind ); + m_update.Enable(); + m_updates.Enable(); + m_description.Enable(); + m_descriptions.Enable(); + } +} + +//------------------------------------------------------------------------------ +void UpdateDialog::addEnabledUpdate( rtl::OUString const & name, + dp_gui::UpdateData & data ) +{ + sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_enabledUpdates.size() ); + UpdateDialog::Index *pEntry = new UpdateDialog::Index( ENABLED_UPDATE, m_nLastID, nIndex, name ); + + data.m_nID = m_nLastID; + m_nLastID += 1; + + m_enabledUpdates.push_back( data ); + m_ListboxEntries.push_back( pEntry ); + + if ( ! isIgnoredUpdate( pEntry ) ) + { + sal_uInt16 nPos = insertItem( pEntry, SvLBoxButtonKind_enabledCheckbox ); + m_updates.CheckEntryPos( nPos ); + } + else + addAdditional( pEntry, SvLBoxButtonKind_disabledCheckbox ); + + m_update.Enable(); + m_updates.Enable(); + m_description.Enable(); + m_descriptions.Enable(); +} + +//------------------------------------------------------------------------------ +void UpdateDialog::addDisabledUpdate( UpdateDialog::DisabledUpdate & data ) +{ + sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_disabledUpdates.size() ); + UpdateDialog::Index *pEntry = new UpdateDialog::Index( DISABLED_UPDATE, m_nLastID, nIndex, data.name ); + + data.m_nID = m_nLastID; + m_nLastID += 1; + + m_disabledUpdates.push_back( data ); + m_ListboxEntries.push_back( pEntry ); + + isIgnoredUpdate( pEntry ); + addAdditional( pEntry, SvLBoxButtonKind_disabledCheckbox ); +} + +//------------------------------------------------------------------------------ +void UpdateDialog::addSpecificError( UpdateDialog::SpecificError & data ) +{ + sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_specificErrors.size() ); + UpdateDialog::Index *pEntry = new UpdateDialog::Index( DISABLED_UPDATE, m_nLastID, nIndex, data.name ); + + data.m_nID = m_nLastID; + m_nLastID += 1; + + m_specificErrors.push_back( data ); + m_ListboxEntries.push_back( pEntry ); + + addAdditional( pEntry, SvLBoxButtonKind_staticImage); +} + +void UpdateDialog::checkingDone() { + m_checking.Hide(); + m_throbber.stop(); + m_throbber.Hide(); + if (m_updates.getItemCount() == 0) + { + clearDescription(); + m_description.Enable(); + m_descriptions.Enable(); + + if ( m_disabledUpdates.empty() && m_specificErrors.empty() && m_ignoredUpdates.empty() ) + showDescription( m_none, false ); + else + showDescription( m_noInstallable, false ); + } + + enableOk(); +} + +void UpdateDialog::enableOk() { + if (!m_checking.IsVisible()) { + m_ok.Enable(m_updates.GetCheckedEntryCount() != 0); + } +} + +// ********************************************************************************* +void UpdateDialog::createNotifyJob( bool bPrepareOnly, + uno::Sequence< uno::Sequence< rtl::OUString > > &rItemList ) +{ + if ( !dp_misc::office_is_running() ) + return; + + // notify update check job + try + { + uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + uno::Reference< lang::XMultiServiceFactory > xConfigProvider( + xFactory->createInstance( OUSTR( "com.sun.star.configuration.ConfigurationProvider" )), + uno::UNO_QUERY_THROW); + + beans::PropertyValue aProperty; + aProperty.Name = OUSTR( "nodepath" ); + aProperty.Value = uno::makeAny( OUSTR("org.openoffice.Office.Addons/AddonUI/OfficeHelp/UpdateCheckJob") ); + + uno::Sequence< uno::Any > aArgumentList( 1 ); + aArgumentList[0] = uno::makeAny( aProperty ); + + uno::Reference< container::XNameAccess > xNameAccess( + xConfigProvider->createInstanceWithArguments( + OUSTR("com.sun.star.configuration.ConfigurationAccess"), aArgumentList ), + uno::UNO_QUERY_THROW ); + + util::URL aURL; + xNameAccess->getByName(OUSTR("URL")) >>= aURL.Complete; + + uno::Reference < util::XURLTransformer > xTransformer( xFactory->createInstance( OUSTR( "com.sun.star.util.URLTransformer" ) ), + uno::UNO_QUERY_THROW ); + + xTransformer->parseStrict(aURL); + + uno::Reference < frame::XDesktop > xDesktop( xFactory->createInstance( OUSTR( "com.sun.star.frame.Desktop" ) ), + uno::UNO_QUERY_THROW ); + uno::Reference< frame::XDispatchProvider > xDispatchProvider( xDesktop->getCurrentFrame(), + uno::UNO_QUERY_THROW ); + uno::Reference< frame::XDispatch > xDispatch = xDispatchProvider->queryDispatch(aURL, rtl::OUString(), 0); + + if( xDispatch.is() ) + { + uno::Sequence< beans::PropertyValue > aPropList(2); + aProperty.Name = OUSTR( "updateList" ); + aProperty.Value = uno::makeAny( rItemList ); + aPropList[0] = aProperty; + aProperty.Name = OUSTR( "prepareOnly" ); + aProperty.Value = uno::makeAny( bPrepareOnly ); + aPropList[1] = aProperty; + + xDispatch->dispatch(aURL, aPropList ); + } + } + catch( const uno::Exception& e ) + { + dp_misc::TRACE( OUSTR("Caught exception: ") + + e.Message + OUSTR("\n thread terminated.\n\n")); + } +} + +// ********************************************************************************* +void UpdateDialog::notifyMenubar( bool bPrepareOnly, bool bRecheckOnly ) +{ + if ( !dp_misc::office_is_running() ) + return; + + uno::Sequence< uno::Sequence< rtl::OUString > > aItemList; + + if ( ! bRecheckOnly ) + { + sal_Int32 nCount = 0; + for ( sal_Int16 i = 0; i < m_updates.getItemCount(); ++i ) + { + uno::Sequence< rtl::OUString > aItem(2); + + UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >(m_updates.GetEntryData(i)); + + if ( p->m_eKind == ENABLED_UPDATE ) + { + dp_gui::UpdateData aUpdData = m_enabledUpdates[ p->m_nIndex ]; + aItem[0] = dp_misc::getIdentifier( aUpdData.aInstalledPackage ); + + dp_misc::DescriptionInfoset aInfoset( m_context, aUpdData.aUpdateInfo ); + aItem[1] = aInfoset.getVersion(); + } + else if ( p->m_eKind == DISABLED_UPDATE ) + continue; + else + continue; + + aItemList.realloc( nCount + 1 ); + aItemList[ nCount ] = aItem; + nCount += 1; + } + } + + storeIgnoredUpdates(); + createNotifyJob( bPrepareOnly, aItemList ); +} + +// ********************************************************************************* + +void UpdateDialog::initDescription() +{ + m_PublisherLabel.Hide(); + m_PublisherLink.Hide(); + m_ReleaseNotesLabel.Hide(); + m_ReleaseNotesLink.Hide(); + m_descriptions.Hide(); + + Link aLink = LINK( this, UpdateDialog, hyperlink_clicked ); + m_PublisherLink.SetClickHdl( aLink ); + m_ReleaseNotesLink.SetClickHdl( aLink ); + + long nTextWidth = m_PublisherLabel.GetCtrlTextWidth( m_PublisherLabel.GetText() ); + long nTemp = m_ReleaseNotesLabel.GetTextWidth( m_ReleaseNotesLabel.GetText() ); + if ( nTemp > nTextWidth ) + nTextWidth = nTemp; + nTextWidth = nTextWidth * 110 / 100; + + Size aNewSize = m_PublisherLabel.GetSizePixel(); + if ( nTextWidth > aNewSize.Width() ) + { + long nDelta = nTextWidth - aNewSize.Width(); + aNewSize.Width() = nTextWidth; + m_PublisherLabel.SetSizePixel( aNewSize ); + m_ReleaseNotesLabel.SetSizePixel( aNewSize ); + + aNewSize = m_PublisherLink.GetSizePixel(); + aNewSize.Width() = aNewSize.Width() - nDelta; + Point aNewPos = m_PublisherLink.GetPosPixel(); + aNewPos.X() = aNewPos.X() + nDelta; + m_PublisherLink.SetPosSizePixel( aNewPos, aNewSize ); + aNewPos.Y() = m_ReleaseNotesLink.GetPosPixel().Y(); + m_ReleaseNotesLink.SetPosSizePixel( aNewPos, aNewSize ); + } + + m_aFirstLinePos = m_descriptions.GetPosPixel(); + m_aFirstLineSize = m_descriptions.GetSizePixel(); + Size aMarginSize = LogicToPixel( Size( RSC_SP_CTRL_GROUP_X, RSC_SP_CTRL_GROUP_Y ), MAP_APPFONT ); + Point aThirdLinePos = m_ReleaseNotesLabel.GetPosPixel(); + aThirdLinePos.Y() = aThirdLinePos.Y() + m_ReleaseNotesLabel.GetSizePixel().Height() + aMarginSize.Height(); + m_nFirstLineDelta = aThirdLinePos.Y() - m_aFirstLinePos.Y(); + m_nOneLineMissing = m_ReleaseNotesLabel.GetPosPixel().Y() - m_PublisherLabel.GetPosPixel().Y(); +} + +void UpdateDialog::clearDescription() +{ + String sEmpty; + m_PublisherLabel.Hide(); + m_PublisherLink.Hide(); + m_PublisherLink.SetDescription( sEmpty ); + m_PublisherLink.SetURL( sEmpty ); + m_ReleaseNotesLabel.Hide(); + m_ReleaseNotesLink.Hide(); + m_ReleaseNotesLink.SetURL( sEmpty ); + if ( m_PublisherLabel.GetPosPixel().Y() == m_ReleaseNotesLabel.GetPosPixel().Y() ) + { + Point aNewPos = m_ReleaseNotesLabel.GetPosPixel(); + aNewPos.Y() += m_nOneLineMissing; + m_ReleaseNotesLabel.SetPosPixel( aNewPos ); + aNewPos = m_ReleaseNotesLink.GetPosPixel(); + aNewPos.Y() += m_nOneLineMissing; + m_ReleaseNotesLink.SetPosPixel( aNewPos ); + } + m_descriptions.Hide(); + m_descriptions.Clear(); + m_descriptions.SetPosSizePixel( m_aFirstLinePos, m_aFirstLineSize ); +} + +bool UpdateDialog::showDescription(uno::Reference< xml::dom::XNode > const & aUpdateInfo) +{ + dp_misc::DescriptionInfoset infoset(m_context, aUpdateInfo); + return showDescription(infoset.getLocalizedPublisherNameAndURL(), + infoset.getLocalizedReleaseNotesURL()); +} + +bool UpdateDialog::showDescription(uno::Reference< deployment::XPackage > const & aExtension) +{ + OSL_ASSERT(aExtension.is()); + beans::StringPair pubInfo = aExtension->getPublisherInfo(); + return showDescription(std::make_pair(pubInfo.First, pubInfo.Second), + OUSTR("")); +} + +bool UpdateDialog::showDescription(std::pair< rtl::OUString, rtl::OUString > const & pairPublisher, + rtl::OUString const & sReleaseNotes) +{ + rtl::OUString sPub = pairPublisher.first; + rtl::OUString sURL = pairPublisher.second; + + if ( sPub.getLength() == 0 && sURL.getLength() == 0 && sReleaseNotes.getLength() == 0 ) + // nothing to show + return false; + + bool bPublisher = false; + if ( sPub.getLength() > 0 ) + { + m_PublisherLabel.Show(); + m_PublisherLink.Show(); + m_PublisherLink.SetDescription( sPub ); + m_PublisherLink.SetURL( sURL ); + bPublisher = true; + } + + if ( sReleaseNotes.getLength() > 0 ) + { + if ( !bPublisher ) + { + m_ReleaseNotesLabel.SetPosPixel( m_PublisherLabel.GetPosPixel() ); + m_ReleaseNotesLink.SetPosPixel( m_PublisherLink.GetPosPixel() ); + } + m_ReleaseNotesLabel.Show(); + m_ReleaseNotesLink.Show(); + m_ReleaseNotesLink.SetURL( sReleaseNotes ); + } + return true; +} + +bool UpdateDialog::showDescription( const String& rDescription, bool bWithPublisher ) +{ + if ( rDescription.Len() == 0 ) + // nothing to show + return false; + + if ( bWithPublisher ) + { + bool bOneLineMissing = !m_ReleaseNotesLabel.IsVisible() || !m_PublisherLabel.IsVisible(); + Point aNewPos = m_aFirstLinePos; + aNewPos.Y() += m_nFirstLineDelta; + if ( bOneLineMissing ) + aNewPos.Y() -= m_nOneLineMissing; + Size aNewSize = m_aFirstLineSize; + aNewSize.Height() -= m_nFirstLineDelta; + if ( bOneLineMissing ) + aNewSize.Height() += m_nOneLineMissing; + m_descriptions.SetPosSizePixel( aNewPos, aNewSize ); + } + m_descriptions.Show(); + m_descriptions.SetDescription( rDescription ); + return true; +} + +//------------------------------------------------------------------------------ +void UpdateDialog::getIgnoredUpdates() +{ + uno::Reference< lang::XMultiServiceFactory > xConfig( m_context->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.configuration.ConfigurationProvider"), m_context ), uno::UNO_QUERY_THROW); + beans::NamedValue aValue( OUSTR("nodepath"), uno::Any( IGNORED_UPDATES ) ); + uno::Sequence< uno::Any > args(1); + args[0] <<= aValue; + + uno::Reference< container::XNameAccess > xNameAccess( xConfig->createInstanceWithArguments( OUSTR("com.sun.star.configuration.ConfigurationAccess"), args), uno::UNO_QUERY_THROW ); + uno::Sequence< rtl::OUString > aElementNames = xNameAccess->getElementNames(); + + for ( sal_Int32 i = 0; i < aElementNames.getLength(); i++ ) + { + ::rtl::OUString aIdentifier = aElementNames[i]; + ::rtl::OUString aVersion; + + uno::Any aPropValue( uno::Reference< beans::XPropertySet >( xNameAccess->getByName( aIdentifier ), uno::UNO_QUERY_THROW )->getPropertyValue( PROPERTY_VERSION ) ); + aPropValue >>= aVersion; + IgnoredUpdate *pData = new IgnoredUpdate( aIdentifier, aVersion ); + m_ignoredUpdates.push_back( pData ); + } +} + +//------------------------------------------------------------------------------ +void UpdateDialog::storeIgnoredUpdates() +{ + if ( m_bModified && ( !m_ignoredUpdates.empty() ) ) + { + uno::Reference< lang::XMultiServiceFactory > xConfig( m_context->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.configuration.ConfigurationProvider"), m_context ), uno::UNO_QUERY_THROW ); + beans::NamedValue aValue( OUSTR("nodepath"), uno::Any( IGNORED_UPDATES ) ); + uno::Sequence< uno::Any > args(1); + args[0] <<= aValue; + + uno::Reference< container::XNameContainer > xNameContainer( xConfig->createInstanceWithArguments( + OUSTR("com.sun.star.configuration.ConfigurationUpdateAccess"), args ), uno::UNO_QUERY_THROW ); + + for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i ) + { + if ( xNameContainer->hasByName( (*i)->sExtensionID ) ) + { + if ( (*i)->bRemoved ) + xNameContainer->removeByName( (*i)->sExtensionID ); + else + uno::Reference< beans::XPropertySet >( xNameContainer->getByName( (*i)->sExtensionID ), uno::UNO_QUERY_THROW )->setPropertyValue( PROPERTY_VERSION, uno::Any( (*i)->sVersion ) ); + } + else if ( ! (*i)->bRemoved ) + { + uno::Reference< beans::XPropertySet > elem( uno::Reference< lang::XSingleServiceFactory >( xNameContainer, uno::UNO_QUERY_THROW )->createInstance(), uno::UNO_QUERY_THROW ); + elem->setPropertyValue( PROPERTY_VERSION, uno::Any( (*i)->sVersion ) ); + xNameContainer->insertByName( (*i)->sExtensionID, uno::Any( elem ) ); + } + } + + uno::Reference< util::XChangesBatch > xChangesBatch( xNameContainer, uno::UNO_QUERY ); + if ( xChangesBatch.is() && xChangesBatch->hasPendingChanges() ) + xChangesBatch->commitChanges(); + } + + m_bModified = false; +} + +//------------------------------------------------------------------------------ +bool UpdateDialog::isIgnoredUpdate( UpdateDialog::Index * index ) +{ + bool bIsIgnored = false; + + if (! m_ignoredUpdates.empty() ) + { + rtl::OUString aExtensionID; + rtl::OUString aVersion; + + if ( index->m_eKind == ENABLED_UPDATE ) + { + dp_gui::UpdateData aUpdData = m_enabledUpdates[ index->m_nIndex ]; + aExtensionID = dp_misc::getIdentifier( aUpdData.aInstalledPackage ); + aVersion = aUpdData.updateVersion; + } + else if ( index->m_eKind == DISABLED_UPDATE ) + { + DisabledUpdate &rData = m_disabledUpdates[ index->m_nIndex ]; + dp_misc::DescriptionInfoset aInfoset( m_context, rData.aUpdateInfo ); + ::boost::optional< ::rtl::OUString > aID( aInfoset.getIdentifier() ); + if ( aID ) + aExtensionID = *aID; + aVersion = aInfoset.getVersion(); + } + + for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i ) + { + if ( (*i)->sExtensionID == aExtensionID ) + { + if ( ( (*i)->sVersion.getLength() == 0 ) || ( (*i)->sVersion == aVersion ) ) + { + bIsIgnored = true; + index->m_bIgnored = true; + } + else // when we find another update of an ignored version, we will remove the old one to keep the ignored list small + (*i)->bRemoved = true; + break; + } + } + } + + return bIsIgnored; +} + +//------------------------------------------------------------------------------ +void UpdateDialog::setIgnoredUpdate( UpdateDialog::Index *pIndex, bool bIgnore, bool bIgnoreAll ) +{ + rtl::OUString aExtensionID; + rtl::OUString aVersion; + + m_bModified = true; + + if ( pIndex->m_eKind == ENABLED_UPDATE ) + { + dp_gui::UpdateData aUpdData = m_enabledUpdates[ pIndex->m_nIndex ]; + aExtensionID = dp_misc::getIdentifier( aUpdData.aInstalledPackage ); + if ( !bIgnoreAll ) + aVersion = aUpdData.updateVersion; + } + else if ( pIndex->m_eKind == DISABLED_UPDATE ) + { + DisabledUpdate &rData = m_disabledUpdates[ pIndex->m_nIndex ]; + dp_misc::DescriptionInfoset aInfoset( m_context, rData.aUpdateInfo ); + ::boost::optional< ::rtl::OUString > aID( aInfoset.getIdentifier() ); + if ( aID ) + aExtensionID = *aID; + if ( !bIgnoreAll ) + aVersion = aInfoset.getVersion(); + } + + if ( aExtensionID.getLength() ) + { + bool bFound = false; + for ( std::vector< UpdateDialog::IgnoredUpdate* >::iterator i( m_ignoredUpdates.begin() ); i != m_ignoredUpdates.end(); ++i ) + { + if ( (*i)->sExtensionID == aExtensionID ) + { + (*i)->sVersion = aVersion; + (*i)->bRemoved = !bIgnore; + bFound = true; + break; + } + } + if ( bIgnore && !bFound ) + { + IgnoredUpdate *pData = new IgnoredUpdate( aExtensionID, aVersion ); + m_ignoredUpdates.push_back( pData ); + } + } +} + +//------------------------------------------------------------------------------ + +IMPL_LINK(UpdateDialog, selectionHandler, void *, EMPTYARG) +{ + rtl::OUStringBuffer b; + bool bInserted = false; + UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( + m_updates.GetEntryData(m_updates.GetSelectEntryPos())); + clearDescription(); + + if ( p != NULL ) + { + sal_uInt16 pos = p->m_nIndex; + + switch (p->m_eKind) + { + case ENABLED_UPDATE: + { + if ( m_enabledUpdates[ pos ].aUpdateSource.is() ) + bInserted = showDescription( m_enabledUpdates[ pos ].aUpdateSource ); + else + bInserted = showDescription( m_enabledUpdates[ pos ].aUpdateInfo ); + + if ( p->m_bIgnored ) + b.append( m_ignoredUpdate ); + + break; + } + case DISABLED_UPDATE: + { + if ( !m_disabledUpdates.empty() ) + bInserted = showDescription( m_disabledUpdates[pos].aUpdateInfo ); + + if ( p->m_bIgnored ) + b.append( m_ignoredUpdate ); + + if ( m_disabledUpdates.empty() ) + break; + + UpdateDialog::DisabledUpdate & data = m_disabledUpdates[ pos ]; + if (data.unsatisfiedDependencies.getLength() != 0) + { + // create error string for version mismatch + ::rtl::OUString sVersion( RTL_CONSTASCII_USTRINGPARAM("%VERSION") ); + ::rtl::OUString sProductName( RTL_CONSTASCII_USTRINGPARAM("%PRODUCTNAME") ); + sal_Int32 nPos = m_noDependencyCurVer.indexOf( sVersion ); + if ( nPos >= 0 ) + { + ::rtl::OUString sCurVersion( RTL_CONSTASCII_USTRINGPARAM( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":Version:OOOPackageVersion}")); + ::rtl::Bootstrap::expandMacros(sCurVersion); + m_noDependencyCurVer = m_noDependencyCurVer.replaceAt( nPos, sVersion.getLength(), sCurVersion ); + } + nPos = m_noDependencyCurVer.indexOf( sProductName ); + if ( nPos >= 0 ) + { + m_noDependencyCurVer = m_noDependencyCurVer.replaceAt( nPos, sProductName.getLength(), BrandName::get() ); + } + nPos = m_noDependency.indexOf( sProductName ); + if ( nPos >= 0 ) + { + m_noDependency = m_noDependency.replaceAt( nPos, sProductName.getLength(), BrandName::get() ); + } + + b.append(m_noInstall); + b.append(LF); + b.append(m_noDependency); + for (sal_Int32 i = 0; + i < data.unsatisfiedDependencies.getLength(); ++i) + { + b.append(LF); + b.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); + // U+2003 EM SPACE would be better than two spaces, + // but some fonts do not contain it + b.append( + confineToParagraph( + data.unsatisfiedDependencies[i])); + } + b.append(LF); + b.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); + b.append(m_noDependencyCurVer); + } + break; + } + case SPECIFIC_ERROR: + { + UpdateDialog::SpecificError & data = m_specificErrors[ pos ]; + b.append(m_failure); + b.append(LF); + b.append( data.message.getLength() == 0 ? m_unknownError : data.message ); + break; + } + default: + OSL_ASSERT(false); + break; + } + } + + if ( b.getLength() == 0 ) + b.append( m_noDescription ); + + showDescription( b.makeStringAndClear(), bInserted ); + return 0; +} + +IMPL_LINK(UpdateDialog, allHandler, void *, EMPTYARG) +{ + if (m_all.IsChecked()) + { + m_update.Enable(); + m_updates.Enable(); + m_description.Enable(); + m_descriptions.Enable(); + + for (std::vector< UpdateDialog::Index* >::iterator i( m_ListboxEntries.begin() ); + i != m_ListboxEntries.end(); ++i ) + { + if ( (*i)->m_bIgnored || ( (*i)->m_eKind != ENABLED_UPDATE ) ) + insertItem( (*i), SvLBoxButtonKind_disabledCheckbox ); + } + } + else + { + for ( sal_uInt16 i = 0; i < m_updates.getItemCount(); ) + { + UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( m_updates.GetEntryData(i) ); + if ( p->m_bIgnored || ( p->m_eKind != ENABLED_UPDATE ) ) + { + m_updates.RemoveEntry(i); + } else { + ++i; + } + } + + if (m_updates.getItemCount() == 0) + { + clearDescription(); + m_update.Disable(); + m_updates.Disable(); + if (m_checking.IsVisible()) + m_description.Disable(); + else + showDescription(m_noInstallable,false); + } + } + return 0; +} + +IMPL_LINK(UpdateDialog, okHandler, void *, EMPTYARG) +{ + //If users are going to update a shared extension then we need + //to warn them + typedef ::std::vector<UpdateData>::const_iterator CIT; + for (CIT i = m_enabledUpdates.begin(); i < m_enabledUpdates.end(); ++i) + { + OSL_ASSERT(i->aInstalledPackage.is()); + //If the user has no write access to the shared folder then the update + //for a shared extension is disable, that is it cannot be in m_enabledUpdates + } + + + for (sal_uInt16 i = 0; i < m_updates.getItemCount(); ++i) { + UpdateDialog::Index const * p = + static_cast< UpdateDialog::Index const * >( + m_updates.GetEntryData(i)); + if (p->m_eKind == ENABLED_UPDATE && m_updates.IsChecked(i)) { + m_updateData.push_back( m_enabledUpdates[ p->m_nIndex ] ); + } + } + + EndDialog(RET_OK); + return 0; +} + +IMPL_LINK(UpdateDialog, closeHandler, void *, EMPTYARG) { + m_thread->stop(); + EndDialog(RET_CANCEL); + return 0; +} + +IMPL_LINK( UpdateDialog, hyperlink_clicked, svt::FixedHyperlink*, pHyperlink ) +{ + ::rtl::OUString sURL; + if ( pHyperlink ) + sURL = ::rtl::OUString( pHyperlink->GetURL() ); + if ( sURL.getLength() == 0 ) + return 0; + + try + { + uno::Reference< com::sun::star::system::XSystemShellExecute > xSystemShellExecute( + m_context->getServiceManager()->createInstanceWithContext( + OUSTR( "com.sun.star.system.SystemShellExecute" ), + m_context), uno::UNO_QUERY_THROW); + //throws lang::IllegalArgumentException, system::SystemShellExecuteException + xSystemShellExecute->execute( + sURL, ::rtl::OUString(), com::sun::star::system::SystemShellExecuteFlags::DEFAULTS); + } + catch (uno::Exception& ) + { + } + + return 1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.hxx b/desktop/source/deployment/gui/dp_gui_updatedialog.hxx new file mode 100644 index 000000000000..ea1cc8d56201 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.hxx @@ -0,0 +1,232 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_GUI_DP_GUI_UPDATEDIALOG_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_UPDATEDIALOG_HXX + +#include "sal/config.h" + +#include <memory> +#include <vector> +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" +#include "svtools/svlbitm.hxx" +#include "svx/checklbx.hxx" +#include "tools/link.hxx" +#include "tools/solar.h" +#include "vcl/button.hxx" +#include "vcl/dialog.hxx" +#include "vcl/fixed.hxx" +#include <svtools/fixedhyper.hxx> +#include <vcl/throbber.hxx> + +#include "descedit.hxx" +#include "dp_gui_updatedata.hxx" + +/// @HTML + +class Image; +class KeyEvent; +class MouseEvent; +class ResId; +class Window; + +namespace com { namespace sun { namespace star { + namespace deployment { class XExtensionManager; + class XPackage; } + namespace uno { class XComponentContext; } +} } } + +namespace dp_gui { +/** + The modal “Check for Updates” dialog. +*/ +class UpdateDialog: public ModalDialog { +public: + /** + Create an instance. + + <p>Exactly one of <code>selectedPackages</code> and + <code>packageManagers</code> must be non-null.</p> + + @param context + a non-null component context + + @param parent + the parent window, may be null + + @param vExtensionList + check for updates for the contained extensions. There must only be one extension with + a particular identifier. If one extension is installed in several repositories, then the + one with the highest version must be used, because it contains the latest known update + information. + */ + UpdateDialog( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > const & context, + Window * parent, + const std::vector< com::sun::star::uno::Reference< + com::sun::star::deployment::XPackage > > & vExtensionList, + std::vector< dp_gui::UpdateData > * updateData); + + ~UpdateDialog(); + + virtual sal_Bool Close(); + + virtual short Execute(); + + void notifyMenubar( bool bPrepareOnly, bool bRecheckOnly ); + static void createNotifyJob( bool bPrepareOnly, + com::sun::star::uno::Sequence< com::sun::star::uno::Sequence< rtl::OUString > > &rItemList ); + +private: + UpdateDialog(UpdateDialog &); // not defined + void operator =(UpdateDialog &); // not defined + + struct DisabledUpdate; + struct SpecificError; + struct IgnoredUpdate; + struct Index; + friend struct Index; + class Thread; + friend class Thread; + + class CheckListBox: public SvxCheckListBox { + public: + CheckListBox( + UpdateDialog & dialog, ResId const & resource, + Image const & normalStaticImage); + + virtual ~CheckListBox(); + + sal_uInt16 getItemCount() const; + + private: + CheckListBox(UpdateDialog::CheckListBox &); // not defined + void operator =(UpdateDialog::CheckListBox &); // not defined + + virtual void MouseButtonDown(MouseEvent const & event); + virtual void MouseButtonUp(MouseEvent const & event); + virtual void KeyInput(KeyEvent const & event); + + void handlePopupMenu( const Point &rPos ); + + rtl::OUString m_ignoreUpdate; + rtl::OUString m_ignoreAllUpdates; + rtl::OUString m_enableUpdate; + UpdateDialog & m_dialog; + }; + + + friend class CheckListBox; + + sal_uInt16 insertItem( UpdateDialog::Index *pIndex, SvLBoxButtonKind kind ); + void addAdditional( UpdateDialog::Index *pIndex, SvLBoxButtonKind kind ); + bool isIgnoredUpdate( UpdateDialog::Index *pIndex ); + void setIgnoredUpdate( UpdateDialog::Index *pIndex, bool bIgnore, bool bIgnoreAll ); + + void addEnabledUpdate( rtl::OUString const & name, dp_gui::UpdateData & data ); + void addDisabledUpdate( UpdateDialog::DisabledUpdate & data ); + void addSpecificError( UpdateDialog::SpecificError & data ); + + void checkingDone(); + + void enableOk(); + + void getIgnoredUpdates(); + void storeIgnoredUpdates(); + + void initDescription(); + void clearDescription(); + bool showDescription(::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage > const & aExtension); + bool showDescription(std::pair< rtl::OUString, rtl::OUString > const & pairPublisher, + rtl::OUString const & sReleaseNotes); + bool showDescription( ::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XNode > const & aUpdateInfo); + bool showDescription( const String& rDescription, bool bWithPublisher ); + bool isReadOnly( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + + DECL_LINK(selectionHandler, void *); + DECL_LINK(allHandler, void *); + DECL_LINK(okHandler, void *); + DECL_LINK(closeHandler, void *); + DECL_LINK(hyperlink_clicked, svt::FixedHyperlink *); + + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + m_context; + FixedText m_checking; + Throbber m_throbber; + FixedText m_update; + UpdateDialog::CheckListBox m_updates; + CheckBox m_all; + FixedLine m_description; + FixedText m_PublisherLabel; + svt::FixedHyperlink m_PublisherLink; + FixedText m_ReleaseNotesLabel; + svt::FixedHyperlink m_ReleaseNotesLink; + dp_gui::DescriptionEdit m_descriptions; + FixedLine m_line; + HelpButton m_help; + PushButton m_ok; + PushButton m_close; + rtl::OUString m_error; + rtl::OUString m_none; + rtl::OUString m_noInstallable; + rtl::OUString m_failure; + rtl::OUString m_unknownError; + rtl::OUString m_noDescription; + rtl::OUString m_noInstall; + rtl::OUString m_noDependency; + rtl::OUString m_noDependencyCurVer; + rtl::OUString m_browserbased; + rtl::OUString m_version; + rtl::OUString m_ignoredUpdate; + std::vector< dp_gui::UpdateData > m_enabledUpdates; + std::vector< UpdateDialog::DisabledUpdate > m_disabledUpdates; + std::vector< UpdateDialog::SpecificError > m_specificErrors; + std::vector< UpdateDialog::IgnoredUpdate* > m_ignoredUpdates; + std::vector< Index* > m_ListboxEntries; + std::vector< dp_gui::UpdateData > & m_updateData; + rtl::Reference< UpdateDialog::Thread > m_thread; + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > m_xExtensionManager; + + Point m_aFirstLinePos; + Size m_aFirstLineSize; + long m_nFirstLineDelta; + long m_nOneLineMissing; + sal_uInt16 m_nLastID; + bool m_bModified; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.src b/desktop/source/deployment/gui/dp_gui_updatedialog.src new file mode 100644 index 000000000000..b6b6bb7c41e3 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.src @@ -0,0 +1,275 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "svtools/controldims.hrc" + +#include "dp_gui.hrc" + +#define LOCAL_WIDTH (60 * RSC_BS_CHARWIDTH) +#define LABEL_WIDTH (1 * RSC_BS_CHARWIDTH) +#define LOCAL_LIST_HEIGHT1 (6 * RSC_BS_CHARHEIGHT) + 4 +#define LOCAL_LIST_HEIGHT2 (7 * RSC_BS_CHARHEIGHT) + 3 + +ModalDialog RID_DLG_UPDATE { + HelpID = HID_DEPLOYMENT_GUI_UPDATE; + Size = MAP_APPFONT( + (RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH + + RSC_SP_DLG_INNERBORDER_RIGHT), + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT2 + RSC_SP_FLGR_SPACE_Y + + RSC_CD_FIXEDLINE_HEIGHT + RSC_SP_FLGR_SPACE_Y + + RSC_CD_PUSHBUTTON_HEIGHT + RSC_SP_DLG_INNERBORDER_BOTTOM)); + Text[en-US] = "Extension Update"; + Moveable = TRUE; + Closeable = TRUE; + FixedText RID_DLG_UPDATE_CHECKING { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH * 2 / 3, + RSC_SP_DLG_INNERBORDER_TOP); + Size = MAP_APPFONT( + (LOCAL_WIDTH - LOCAL_WIDTH * 2 / 3 - RSC_SP_CTRL_DESC_X - + RSC_CD_FIXEDTEXT_HEIGHT), + RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Checking..."; + Right = TRUE; + NoLabel = TRUE; + }; + FixedImage RID_DLG_UPDATE_THROBBER { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH - RSC_CD_FIXEDTEXT_HEIGHT, + RSC_SP_DLG_INNERBORDER_TOP); + Size = MAP_APPFONT(RSC_CD_FIXEDTEXT_HEIGHT, RSC_CD_FIXEDTEXT_HEIGHT + 1); + }; + FixedText RID_DLG_UPDATE_UPDATE { + Disable = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP); + Size = MAP_APPFONT( + LOCAL_WIDTH * 2 / 3 - RSC_SP_CTRL_GROUP_X, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "~Available extension updates"; + }; + Control RID_DLG_UPDATE_UPDATES { + HelpId = HID_DEPLOYMENT_GUI_UPDATE_AVAILABLE_UPDATES; + Disable = TRUE; + Border = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, LOCAL_LIST_HEIGHT1); + TabStop = TRUE; + }; + CheckBox RID_DLG_UPDATE_ALL { + HelpID = "desktop:CheckBox:RID_DLG_UPDATE:RID_DLG_UPDATE_ALL"; + Disable = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_CHECKBOX_HEIGHT); + Text[en-US] = "~Show all updates"; + }; + FixedLine RID_DLG_UPDATE_DESCRIPTION { + Disable = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Description"; + }; + FixedText RID_DLG_UPDATE_PUBLISHER_LABEL + { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LABEL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Publisher:"; + }; + FixedText RID_DLG_UPDATE_PUBLISHER_LINK + { + HelpId = HID_DEPLOYMENT_GUI_UPDATE_PUBLISHER; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LABEL_WIDTH + RSC_SP_CTRL_DESC_X, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH - LABEL_WIDTH - RSC_SP_CTRL_DESC_X, RSC_CD_FIXEDTEXT_HEIGHT); + }; + FixedText RID_DLG_UPDATE_RELEASENOTES_LABEL + { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LABEL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "What is new:"; + }; + FixedText RID_DLG_UPDATE_RELEASENOTES_LINK + { + HelpId = HID_DEPLOYMENT_GUI_UPDATE_RELEASENOTES; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LABEL_WIDTH + RSC_SP_CTRL_DESC_X, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH - LABEL_WIDTH - RSC_SP_CTRL_DESC_X, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Release Notes"; + }; + MultiLineEdit RID_DLG_UPDATE_DESCRIPTIONS { + HelpID = "desktop:MultiLineEdit:RID_DLG_UPDATE:RID_DLG_UPDATE_DESCRIPTIONS"; + Disable = TRUE; + Border = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, LOCAL_LIST_HEIGHT2); + ReadOnly = TRUE; + VScroll = TRUE; + IgnoreTab = TRUE; + }; + FixedLine RID_DLG_UPDATE_LINE { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT2 + RSC_SP_FLGR_SPACE_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDLINE_HEIGHT); + }; + HelpButton RID_DLG_UPDATE_HELP { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT2 + RSC_SP_FLGR_SPACE_Y + + RSC_CD_FIXEDLINE_HEIGHT + RSC_SP_FLGR_SPACE_Y)); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + }; + PushButton RID_DLG_UPDATE_OK { + HelpID = "desktop:PushButton:RID_DLG_UPDATE:RID_DLG_UPDATE_OK"; + Disable = TRUE; + Pos = MAP_APPFONT( + (RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH - RSC_CD_PUSHBUTTON_WIDTH - + RSC_SP_CTRL_GROUP_X - RSC_CD_PUSHBUTTON_WIDTH), + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT2 + RSC_SP_FLGR_SPACE_Y + + RSC_CD_FIXEDLINE_HEIGHT + RSC_SP_FLGR_SPACE_Y)); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + Text[en-US] = "~Install"; + DefButton = TRUE; + }; + PushButton RID_DLG_UPDATE_CLOSE { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH - RSC_CD_PUSHBUTTON_WIDTH, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT2 + RSC_SP_FLGR_SPACE_Y + + RSC_CD_FIXEDLINE_HEIGHT + RSC_SP_FLGR_SPACE_Y)); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + Text[en-US] = "Close"; + }; + + Image RID_DLG_UPDATE_NORMALALERT { + ImageBitmap = Bitmap { + File = "caution_12.png"; + }; + }; + String RID_DLG_UPDATE_ERROR { + Text[en-US] = "Error"; + }; + String RID_DLG_UPDATE_NONE { + Text[en-US] = "No new updates are available."; + }; + String RID_DLG_UPDATE_NOINSTALLABLE { + Text[en-US] = "No installable updates are available. To see ignored or disabled updates, mark the check box 'Show all updates'."; + }; + String RID_DLG_UPDATE_FAILURE { + Text[en-US] = "An error occurred:"; + }; + String RID_DLG_UPDATE_UNKNOWNERROR { + Text[en-US] = "Unknown error."; + }; + String RID_DLG_UPDATE_NODESCRIPTION { + Text[en-US] = "No more details are available for this update."; + }; + String RID_DLG_UPDATE_NOINSTALL { + Text[en-US] = "The extension cannot be updated because:"; + }; + String RID_DLG_UPDATE_NODEPENDENCY { + Text[en-US] = "Required %PRODUCTNAME version doesn't match:"; + }; + String RID_DLG_UPDATE_NODEPENDENCY_CUR_VER { + Text[en-US] = "You have %PRODUCTNAME %VERSION"; + }; + String RID_DLG_UPDATE_BROWSERBASED { + Text[en-US] = "browser based update"; + }; + String RID_DLG_UPDATE_VERSION { + Text[en-US] = "Version"; + }; + String RID_DLG_UPDATE_IGNORE { + Text[en-US] = "Ignore this Update"; + }; + String RID_DLG_UPDATE_IGNORE_ALL { + Text[en-US] = "Ignore all Updates"; + }; + String RID_DLG_UPDATE_ENABLE { + Text[en-US] = "Enable Updates"; + }; + String RID_DLG_UPDATE_IGNORED_UPDATE { + Text[en-US] = "This update will be ignored.\n"; + }; +}; + +WarningBox RID_WARNINGBOX_UPDATE_SHARED_EXTENSION +{ + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "Make sure that no further users are working with the same " + "%PRODUCTNAME, when changing shared extensions in a multi user environment.\n" + "Click \'OK\' to update the extensions.\n" + "Click \'Cancel\' to stop updating the extensions."; +}; + diff --git a/desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx new file mode 100644 index 000000000000..696c2fe3ef0c --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx @@ -0,0 +1,757 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_gui_updatedata.hxx" + +#include "sal/config.h" +#include "osl/file.hxx" +#include "osl/conditn.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "tools/resid.hxx" +#include "tools/resmgr.hxx" +#include "tools/solar.h" +#include "tools/string.hxx" +#include "vcl/dialog.hxx" +#include "vcl/msgbox.hxx" +#include "vcl/svapp.hxx" +#include "osl/mutex.hxx" +#include "vcl/dialog.hxx" +#include "cppuhelper/implbase3.hxx" + +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/beans/NamedValue.hpp" +#include "com/sun/star/xml/dom/XElement.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" +#include "com/sun/star/xml/dom/XNodeList.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/ucb/XProgressHandler.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/XUpdateInformationProvider.hpp" +#include "com/sun/star/deployment/DependencyException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/ui/LicenseDialog.hpp" +#include "com/sun/star/task/XInteractionHandler.hpp" +#include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" +#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" + +#include "dp_descriptioninfoset.hxx" +#include "dp_gui.hrc" +#include "dp_gui_updateinstalldialog.hxx" +#include "dp_gui_shared.hxx" +#include "dp_gui_updatedata.hxx" +#include "dp_ucb.h" +#include "dp_misc.h" +#include "dp_version.hxx" +#include "dp_gui_thread.hxx" +#include "dp_gui_extensioncmdqueue.hxx" +#include "ucbhelper/content.hxx" +#include "osl/mutex.hxx" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "com/sun/star/uno/Sequence.h" +#include "comphelper/anytostring.hxx" +#include "toolkit/helper/vclunohelper.hxx" + +#include <vector> + +class Window; + +namespace cssu = ::com::sun::star::uno; +namespace css = ::com::sun::star; + +using ::rtl::OUString; + + +namespace dp_gui { + +class UpdateInstallDialog::Thread: public dp_gui::Thread { + friend class UpdateCommandEnv; +public: + Thread(cssu::Reference< cssu::XComponentContext > ctx, + UpdateInstallDialog & dialog, std::vector< dp_gui::UpdateData > & aVecUpdateData); + + void stop(); + + + +private: + Thread(Thread &); // not defined + void operator =(Thread &); // not defined + + virtual ~Thread(); + + virtual void execute(); + void downloadExtensions(); + void download(::rtl::OUString const & aUrls, UpdateData & aUpdatData); + void installExtensions(); + void removeTempDownloads(); + + UpdateInstallDialog & m_dialog; + cssu::Reference< css::deployment::XUpdateInformationProvider > + m_updateInformation; + + // guarded by Application::GetSolarMutex(): + cssu::Reference< css::task::XAbortChannel > m_abort; + cssu::Reference< cssu::XComponentContext > m_xComponentContext; + std::vector< dp_gui::UpdateData > & m_aVecUpdateData; + ::rtl::Reference<UpdateCommandEnv> m_updateCmdEnv; + + //A folder which is created in the temp directory in which then the updates are downloaded + ::rtl::OUString m_sDownloadFolder; + + bool m_stop; + +}; + +class UpdateCommandEnv + : public ::cppu::WeakImplHelper3< css::ucb::XCommandEnvironment, + css::task::XInteractionHandler, + css::ucb::XProgressHandler > +{ + friend class UpdateInstallDialog::Thread; + + UpdateInstallDialog & m_updateDialog; + ::rtl::Reference<UpdateInstallDialog::Thread> m_installThread; + cssu::Reference< cssu::XComponentContext > m_xContext; + +public: + virtual ~UpdateCommandEnv(); + UpdateCommandEnv( cssu::Reference< cssu::XComponentContext > const & xCtx, + UpdateInstallDialog & updateDialog, + ::rtl::Reference<UpdateInstallDialog::Thread>const & thread); + + // XCommandEnvironment + virtual cssu::Reference<css::task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (cssu::RuntimeException); + virtual cssu::Reference<css::ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (cssu::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + cssu::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (cssu::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( cssu::Any const & Status ) + throw (cssu::RuntimeException); + virtual void SAL_CALL update( cssu::Any const & Status ) + throw (cssu::RuntimeException); + virtual void SAL_CALL pop() throw (cssu::RuntimeException); +}; + + +UpdateInstallDialog::Thread::Thread( + cssu::Reference< cssu::XComponentContext> xCtx, + UpdateInstallDialog & dialog, + std::vector< dp_gui::UpdateData > & aVecUpdateData): + m_dialog(dialog), + m_xComponentContext(xCtx), + m_aVecUpdateData(aVecUpdateData), + m_updateCmdEnv(new UpdateCommandEnv(xCtx, m_dialog, this)), + m_stop(false) +{} + +void UpdateInstallDialog::Thread::stop() { + cssu::Reference< css::task::XAbortChannel > abort; + { + SolarMutexGuard g; + abort = m_abort; + m_stop = true; + } + if (abort.is()) { + abort->sendAbort(); + } +} + +UpdateInstallDialog::Thread::~Thread() {} + +void UpdateInstallDialog::Thread::execute() +{ + try { + downloadExtensions(); + installExtensions(); + } + catch (...) + { + } + + //clean up the temp directories + try { + removeTempDownloads(); + } catch( ... ) { + } + + { + //make sure m_dialog is still alive + SolarMutexGuard g; + if (! m_stop) + m_dialog.updateDone(); + } + //UpdateCommandEnv keeps a reference to Thread and prevents destruction. Therefore remove it. + m_updateCmdEnv->m_installThread.clear(); +} + + +UpdateInstallDialog::UpdateInstallDialog( + Window * parent, + std::vector<dp_gui::UpdateData> & aVecUpdateData, + cssu::Reference< cssu::XComponentContext > const & xCtx): + ModalDialog( + parent, + DpGuiResId(RID_DLG_UPDATEINSTALL)), + + m_thread(new Thread(xCtx, *this, aVecUpdateData)), + m_xComponentContext(xCtx), + m_bError(false), + m_bNoEntry(true), + m_bActivated(false), + m_sInstalling(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_INSTALLING))), + m_sFinished(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_FINISHED))), + m_sNoErrors(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_NO_ERRORS))), + m_sErrorDownload(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_DOWNLOAD))), + m_sErrorInstallation(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_INSTALLATION))), + m_sErrorLicenseDeclined(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_LIC_DECLINED))), + m_sNoInstall(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_EXTENSION_NOINSTALL))), + m_sThisErrorOccurred(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_THIS_ERROR_OCCURRED))), + m_ft_action(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_DOWNLOADING)), + m_statusbar(this,DpGuiResId(RID_DLG_UPDATE_INSTALL_STATUSBAR)), + m_ft_extension_name(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_EXTENSION_NAME)), + m_ft_results(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_RESULTS)), + m_mle_info(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_INFO)), + m_line(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_LINE)), + m_help(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_HELP)), + m_ok(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_OK)), + m_cancel(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_ABORT)) +{ + FreeResource(); + + m_xExtensionManager = css::deployment::ExtensionManager::get( xCtx ); + + m_cancel.SetClickHdl(LINK(this, UpdateInstallDialog, cancelHandler)); + m_mle_info.EnableCursor(sal_False); + if ( ! dp_misc::office_is_running()) + m_help.Disable(); +} + +UpdateInstallDialog::~UpdateInstallDialog() {} + +sal_Bool UpdateInstallDialog::Close() +{ + m_thread->stop(); + return ModalDialog::Close(); +} + +short UpdateInstallDialog::Execute() +{ + m_thread->launch(); + return ModalDialog::Execute(); +} + + +// make sure the solar mutex is locked before calling +void UpdateInstallDialog::updateDone() +{ + if (!m_bError) + m_mle_info.InsertText(m_sNoErrors); + m_ok.Enable(); + m_ok.GrabFocus(); + m_cancel.Disable(); +} +// make sure the solar mutex is locked before calling +//sets an error message in the text area +void UpdateInstallDialog::setError(INSTALL_ERROR err, ::rtl::OUString const & sExtension, + OUString const & exceptionMessage) +{ + String sError; + m_bError = true; + + switch (err) + { + case ERROR_DOWNLOAD: + sError = m_sErrorDownload; + break; + case ERROR_INSTALLATION: + sError = m_sErrorInstallation; + break; + case ERROR_LICENSE_DECLINED: + sError = m_sErrorLicenseDeclined; + break; + + default: + OSL_ASSERT(0); + } + + sError.SearchAndReplace(String(OUSTR("%NAME")), String(sExtension), 0); + //We want to have an empty line between the error messages. However, + //there shall be no empty line after the last entry. + if (m_bNoEntry) + m_bNoEntry = false; + else + m_mle_info.InsertText(OUSTR("\n")); + m_mle_info.InsertText(sError); + //Insert more information about the error + if (exceptionMessage.getLength()) + m_mle_info.InsertText(m_sThisErrorOccurred + exceptionMessage + OUSTR("\n")); + + m_mle_info.InsertText(m_sNoInstall); + m_mle_info.InsertText(OUSTR("\n")); +} + +void UpdateInstallDialog::setError(OUString const & exceptionMessage) +{ + m_bError = true; + m_mle_info.InsertText(exceptionMessage + OUSTR("\n")); +} + +IMPL_LINK(UpdateInstallDialog, cancelHandler, void *, EMPTYARG) +{ + m_thread->stop(); + EndDialog(RET_CANCEL); + return 0; +} + +//------------------------------------------------------------------------------------------------ + +void UpdateInstallDialog::Thread::downloadExtensions() +{ + try + { + //create the download directory in the temp folder + OUString sTempDir; + if (::osl::FileBase::getTempDirURL(sTempDir) != ::osl::FileBase::E_None) + throw cssu::Exception(OUSTR("Could not get URL for the temp directory. No extensions will be installed."), 0); + + //create a unique name for the directory + OUString tempEntry, destFolder; + if (::osl::File::createTempFile(&sTempDir, 0, &tempEntry ) != ::osl::File::E_None) + throw cssu::Exception(OUSTR("Could not create a temporary file in ") + sTempDir + + OUSTR(". No extensions will be installed"), 0 ); + + tempEntry = tempEntry.copy( tempEntry.lastIndexOf( '/' ) + 1 ); + + destFolder = dp_misc::makeURL( sTempDir, tempEntry ); + destFolder += OUSTR("_"); + m_sDownloadFolder = destFolder; + try + { + dp_misc::create_folder(0, destFolder, m_updateCmdEnv.get(), true ); + } catch (cssu::Exception & e) + { + throw cssu::Exception(e.Message + OUSTR(" No extensions will be installed."), 0); + } + + + sal_uInt16 count = 0; + typedef std::vector<UpdateData>::iterator It; + for (It i = m_aVecUpdateData.begin(); i != m_aVecUpdateData.end(); ++i) + { + UpdateData & curData = *i; + + if (!curData.aUpdateInfo.is() || curData.aUpdateSource.is()) + continue; + //We assume that m_aVecUpdateData contains only information about extensions which + //can be downloaded directly. + OSL_ASSERT(curData.sWebsiteURL.getLength() == 0); + + //update the name of the extension which is to be downloaded + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.m_ft_extension_name.SetText(curData.aInstalledPackage->getDisplayName()); + sal_uInt16 prog = (sal::static_int_cast<sal_uInt16>(100) * ++count) / + sal::static_int_cast<sal_uInt16>(m_aVecUpdateData.size()); + m_dialog.m_statusbar.SetValue(prog); + } + dp_misc::DescriptionInfoset info(m_xComponentContext, curData.aUpdateInfo); + //remember occurring exceptions in case we need to print out error information + ::std::vector< ::std::pair<OUString, cssu::Exception> > vecExceptions; + cssu::Sequence<OUString> seqDownloadURLs = info.getUpdateDownloadUrls(); + OSL_ENSURE(seqDownloadURLs.getLength() > 0, "No download URL provided!"); + for (sal_Int32 j = 0; j < seqDownloadURLs.getLength(); j++) + { + try + { + OSL_ENSURE(seqDownloadURLs[j].getLength() > 0, "Download URL is empty!"); + download(seqDownloadURLs[j], curData); + if (curData.sLocalURL.getLength() > 0) + break; + } + catch ( cssu::Exception & e ) + { + vecExceptions.push_back( ::std::make_pair(seqDownloadURLs[j], e)); + //There can be several different errors, for example, the URL is wrong, webserver cannot be reached, + //name cannot be resolved. The UCB helper API does not specify different special exceptions for these + //cases. Therefore ignore and continue. + continue; + } + } + //update the progress and display download error + { + SolarMutexGuard g; + if (m_stop) { + return; + } + if (curData.sLocalURL.getLength() == 0) + { + //Construct a string of all messages contained in the exceptions plus the respective download URLs + ::rtl::OUStringBuffer buf(256); + typedef ::std::vector< ::std::pair<OUString, cssu::Exception > >::const_iterator CIT; + for (CIT j = vecExceptions.begin(); j != vecExceptions.end(); j++) + { + if (j != vecExceptions.begin()) + buf.appendAscii("\n"); + buf.append(OUSTR("Could not download ")); + buf.append(j->first); + buf.appendAscii(". "); + buf.append(j->second.Message); + } + m_dialog.setError(UpdateInstallDialog::ERROR_DOWNLOAD, curData.aInstalledPackage->getDisplayName(), + buf.makeStringAndClear()); + } + } + + } + } + catch (cssu::Exception & e) + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.setError(e.Message); + } +} +void UpdateInstallDialog::Thread::installExtensions() +{ + //Update the fix text in the dialog to "Installing extensions..." + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.m_ft_action.SetText(m_dialog.m_sInstalling); + m_dialog.m_statusbar.SetValue(0); + } + + sal_uInt16 count = 0; + typedef std::vector<UpdateData>::iterator It; + for (It i = m_aVecUpdateData.begin(); i != m_aVecUpdateData.end(); ++i, ++count) + { + //update the name of the extension which is to be installed + { + SolarMutexGuard g; + if (m_stop) { + return; + } + //we only show progress after an extension has been installed. + if (count > 0) { + m_dialog.m_statusbar.SetValue( + (sal::static_int_cast<sal_uInt16>(100) * count) / + sal::static_int_cast<sal_uInt16>(m_aVecUpdateData.size())); + } + m_dialog.m_ft_extension_name.SetText(i->aInstalledPackage->getDisplayName()); + } + bool bError = false; + bool bLicenseDeclined = false; + cssu::Reference<css::deployment::XPackage> xExtension; + UpdateData & curData = *i; + cssu::Exception exc; + try + { + cssu::Reference< css::task::XAbortChannel > xAbortChannel( + curData.aInstalledPackage->createAbortChannel() ); + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_abort = xAbortChannel; + } + if (!curData.aUpdateSource.is() && curData.sLocalURL.getLength()) + { + css::beans::NamedValue prop(OUSTR("EXTENSION_UPDATE"), css::uno::makeAny(OUSTR("1"))); + if (!curData.bIsShared) + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("user"), xAbortChannel, m_updateCmdEnv.get()); + else + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("shared"), xAbortChannel, m_updateCmdEnv.get()); + } + else if (curData.aUpdateSource.is()) + { + OSL_ASSERT(curData.aUpdateSource.is()); + //I am not sure if we should obtain the install properties and pass them into + //add extension. Currently it contains only "SUPPRESS_LICENSE". So it it could happen + //that a license is displayed when updating from the shared repository, although the + //shared extension was installed using "SUPPRESS_LICENSE". + css::beans::NamedValue prop(OUSTR("EXTENSION_UPDATE"), css::uno::makeAny(OUSTR("1"))); + if (!curData.bIsShared) + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.aUpdateSource->getURL(), css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("user"), xAbortChannel, m_updateCmdEnv.get()); + else + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.aUpdateSource->getURL(), css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("shared"), xAbortChannel, m_updateCmdEnv.get()); + } + } + catch (css::deployment::DeploymentException & de) + { + if (de.Cause.has<css::deployment::LicenseException>()) + { + bLicenseDeclined = true; + } + else + { + exc = de.Cause.get<cssu::Exception>(); + bError = true; + } + } + catch (cssu::Exception& e) + { + exc = e; + bError = true; + } + + if (bLicenseDeclined) + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.setError(UpdateInstallDialog::ERROR_LICENSE_DECLINED, + curData.aInstalledPackage->getDisplayName(), OUString()); + } + else if (!xExtension.is() || bError) + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.setError(UpdateInstallDialog::ERROR_INSTALLATION, + curData.aInstalledPackage->getDisplayName(), exc.Message); + } + } + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.m_statusbar.SetValue(100); + m_dialog.m_ft_extension_name.SetText(OUString()); + m_dialog.m_ft_action.SetText(m_dialog.m_sFinished); + } +} + +void UpdateInstallDialog::Thread::removeTempDownloads() +{ + if (m_sDownloadFolder.getLength()) + { + dp_misc::erase_path(m_sDownloadFolder, + cssu::Reference<css::ucb::XCommandEnvironment>(),false /* no throw: ignore errors */ ); + //remove also the temp file which we have used to create the unique name + OUString tempFile = m_sDownloadFolder.copy(0, m_sDownloadFolder.getLength() - 1); + dp_misc::erase_path(tempFile, cssu::Reference<css::ucb::XCommandEnvironment>(),false); + m_sDownloadFolder = OUString(); + } +} + + +void UpdateInstallDialog::Thread::download(OUString const & sDownloadURL, UpdateData & aUpdateData) +{ + { + SolarMutexGuard g; + if (m_stop) { + return; + } + } + + OSL_ASSERT(m_sDownloadFolder.getLength()); + OUString destFolder, tempEntry; + if (::osl::File::createTempFile( + &m_sDownloadFolder, + 0, &tempEntry ) != ::osl::File::E_None) + { + //ToDo feedback in window that download of this component failed + throw cssu::Exception(OUSTR("Could not create temporary file in folder ") + destFolder + OUSTR("."), 0); + } + tempEntry = tempEntry.copy( tempEntry.lastIndexOf( '/' ) + 1 ); + + destFolder = dp_misc::makeURL( m_sDownloadFolder, tempEntry ); + destFolder += OUSTR("_"); + + ::ucbhelper::Content destFolderContent; + dp_misc::create_folder( &destFolderContent, destFolder, m_updateCmdEnv.get() ); + + ::ucbhelper::Content sourceContent; + dp_misc::create_ucb_content( &sourceContent, sDownloadURL, m_updateCmdEnv.get() ); + + const OUString sTitle(sourceContent.getPropertyValue( + dp_misc::StrTitle::get() ).get<OUString>() ); + + if (destFolderContent.transferContent( + sourceContent, ::ucbhelper::InsertOperation_COPY, + sTitle, css::ucb::NameClash::OVERWRITE )) + { + //the user may have cancelled the dialog because downloading took to long + { + SolarMutexGuard g; + if (m_stop) { + return; + } + //all errors should be handeld by the command environment. + aUpdateData.sLocalURL = destFolder + OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ) + sTitle; + } + } +} + + +// ------------------------------------------------------------------------------------------------------- + +UpdateCommandEnv::UpdateCommandEnv( cssu::Reference< cssu::XComponentContext > const & xCtx, + UpdateInstallDialog & updateDialog, + ::rtl::Reference<UpdateInstallDialog::Thread>const & thread) + : m_updateDialog( updateDialog ), + m_installThread(thread), + m_xContext(xCtx) +{ +} + +UpdateCommandEnv::~UpdateCommandEnv() +{ +} + + +// XCommandEnvironment +//______________________________________________________________________________ +cssu::Reference<css::task::XInteractionHandler> UpdateCommandEnv::getInteractionHandler() +throw (cssu::RuntimeException) +{ + return this; +} + +//______________________________________________________________________________ +cssu::Reference<css::ucb::XProgressHandler> UpdateCommandEnv::getProgressHandler() +throw (cssu::RuntimeException) +{ + return this; +} + +// XInteractionHandler +void UpdateCommandEnv::handle( + cssu::Reference< css::task::XInteractionRequest> const & xRequest ) + throw (cssu::RuntimeException) +{ + cssu::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == cssu::TypeClass_EXCEPTION ); + dp_misc::TRACE(OUSTR("[dp_gui_cmdenv.cxx] incoming request:\n") + + ::comphelper::anyToString(request) + OUSTR("\n\n")); + + css::deployment::VersionException verExc; + bool approve = false; + bool abort = false; + + if (request >>= verExc) + { //We must catch the version exception during the update, + //because otherwise the user would be confronted with the dialogs, asking + //them if they want to replace an already installed version of the same extension. + //During an update we assume that we always want to replace the old version with the + //new version. + approve = true; + } + + if (approve == false && abort == false) + { + //forward to interaction handler for main dialog. + handleInteractionRequest( m_xContext, xRequest ); + } + else + { + // select: + cssu::Sequence< cssu::Reference< css::task::XInteractionContinuation > > conts( + xRequest->getContinuations() ); + cssu::Reference< css::task::XInteractionContinuation > const * pConts = + conts.getConstArray(); + sal_Int32 len = conts.getLength(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + if (approve) { + cssu::Reference< css::task::XInteractionApprove > xInteractionApprove( + pConts[ pos ], cssu::UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + // don't query again for ongoing continuations: + approve = false; + } + } + else if (abort) { + cssu::Reference< css::task::XInteractionAbort > xInteractionAbort( + pConts[ pos ], cssu::UNO_QUERY ); + if (xInteractionAbort.is()) { + xInteractionAbort->select(); + // don't query again for ongoing continuations: + abort = false; + } + } + } + } +} + +// XProgressHandler +void UpdateCommandEnv::push( cssu::Any const & /*Status*/ ) +throw (cssu::RuntimeException) +{ +} + + +void UpdateCommandEnv::update( cssu::Any const & /*Status */) +throw (cssu::RuntimeException) +{ +} + +void UpdateCommandEnv::pop() throw (cssu::RuntimeException) +{ +} + + +} //end namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updateinstalldialog.hxx b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.hxx new file mode 100644 index 000000000000..4f89fdf4a4d7 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.hxx @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_GUI_DP_GUI_INSTALLDIALOG_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_INSTALLDIALOG_HXX + +#include "sal/config.h" +#include "vcl/button.hxx" +#include "vcl/fixed.hxx" +#include "vcl/dialog.hxx" +#include "svtools/prgsbar.hxx" +#include "rtl/ref.hxx" +#include <vector> + +#include "dp_gui_autoscrolledit.hxx" +/// @HTML + +namespace com { namespace sun { namespace star { namespace deployment { + class XExtensionManager; +}}}} +namespace com { namespace sun { namespace star { namespace uno { + class XComponentContext; +}}}} +namespace com { namespace sun { namespace star { namespace xml { namespace dom { + class XNode; +}}}}} +namespace com { namespace sun { namespace star { namespace xml { namespace xpath { + class XXPathAPI; +}}}}} + +class Window; +namespace osl { + class Condition; +} + +namespace dp_gui { + + struct UpdateData; + class UpdateCommandEnv; + + +/** + The modal “Download and Installation” dialog. +*/ +class UpdateInstallDialog: public ModalDialog { +public: + /** + Create an instance. + + @param parent + the parent window, may be null + */ + UpdateInstallDialog(Window * parent, std::vector<UpdateData> & aVecUpdateData, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xCtx); + + ~UpdateInstallDialog(); + + sal_Bool Close(); + virtual short Execute(); + +private: + UpdateInstallDialog(UpdateInstallDialog &); // not defined + void operator =(UpdateInstallDialog &); // not defined + + class Thread; + friend class Thread; + friend class UpdateCommandEnv; + + DECL_LINK(cancelHandler, void *); + + //signals in the dialog that we have finished. + void updateDone(); + //Writes a particular error into the info listbox. + enum INSTALL_ERROR + { + ERROR_DOWNLOAD, + ERROR_INSTALLATION, + ERROR_LICENSE_DECLINED + }; + void setError(INSTALL_ERROR err, ::rtl::OUString const & sExtension, ::rtl::OUString const & exceptionMessage); + void setError(::rtl::OUString const & exceptionMessage); + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > getExtensionManager() const + { return m_xExtensionManager; } + + rtl::Reference< Thread > m_thread; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xComponentContext; + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > m_xExtensionManager; + //Signals that an error occurred during download and installation + bool m_bError; + bool m_bNoEntry; + bool m_bActivated; + + ::rtl::OUString m_sInstalling; + ::rtl::OUString m_sFinished; + ::rtl::OUString m_sNoErrors; + ::rtl::OUString m_sErrorDownload; + ::rtl::OUString m_sErrorInstallation; + ::rtl::OUString m_sErrorLicenseDeclined; + ::rtl::OUString m_sNoInstall; + ::rtl::OUString m_sThisErrorOccurred; + + FixedText m_ft_action; + ProgressBar m_statusbar; + FixedText m_ft_extension_name; + FixedText m_ft_results; + AutoScrollEdit m_mle_info; + FixedLine m_line; + HelpButton m_help; + OKButton m_ok; + CancelButton m_cancel; +}; + + + + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updateinstalldialog.src b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.src new file mode 100644 index 000000000000..f7cc93493b5d --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.src @@ -0,0 +1,204 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "svtools/controldims.hrc" + +#include "dp_gui.hrc" + + +#define LOCAL_WIDTH (60 * RSC_BS_CHARWIDTH) +#define LOCAL_LIST_HEIGHT (7 * RSC_BS_CHARHEIGHT) +#define LOCAL_BUTTON_WIDTH 80 + +ModalDialog RID_DLG_UPDATEINSTALL { + HelpId = HID_DEPLOYMENT_GUI_UPDATEINSTALL; + Size = MAP_APPFONT( + (RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH + + RSC_SP_DLG_INNERBORDER_RIGHT), + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_FLGR_SPACE_Y + LOCAL_LIST_HEIGHT + + RSC_SP_FLGR_SPACE_Y + RSC_CD_FIXEDLINE_HEIGHT + + RSC_SP_FLGR_SPACE_Y + RSC_CD_PUSHBUTTON_HEIGHT + + RSC_SP_DLG_INNERBORDER_BOTTOM)); + Text[en-US] = "Download and Installation"; + Moveable = TRUE; + Closeable = TRUE; + FixedText RID_DLG_UPDATE_INSTALL_DOWNLOADING { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Downloading extensions..."; + NoLabel = TRUE; + }; + + Window RID_DLG_UPDATE_INSTALL_STATUSBAR { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_CHECKBOX_HEIGHT); + Border = TRUE; + }; + + FixedText RID_DLG_UPDATE_INSTALL_EXTENSION_NAME { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_DESC_Y); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = ""; + NoLabel = TRUE; + }; + + FixedText RID_DLG_UPDATE_INSTALL_RESULTS { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Result"; + }; + + MultiLineEdit RID_DLG_UPDATE_INSTALL_INFO { + HelpID = "desktop:MultiLineEdit:RID_DLG_UPDATEINSTALL:RID_DLG_UPDATE_INSTALL_INFO"; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y); + + Size = MAP_APPFONT(LOCAL_WIDTH, LOCAL_LIST_HEIGHT); + Border = TRUE; + ReadOnly = TRUE; + VScroll = TRUE; + TabStop = FALSE; + }; + + FixedLine RID_DLG_UPDATE_INSTALL_LINE { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT + + RSC_SP_FLGR_SPACE_Y); + + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDLINE_HEIGHT); + }; + + OKButton RID_DLG_UPDATE_INSTALL_OK { + Disable = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH - LOCAL_BUTTON_WIDTH - + RSC_SP_CTRL_GROUP_X - RSC_CD_PUSHBUTTON_WIDTH, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT + + RSC_SP_FLGR_SPACE_Y + RSC_CD_FIXEDLINE_HEIGHT + + RSC_SP_FLGR_SPACE_Y); + + + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + Text[en-US] = "OK"; + }; + + CancelButton RID_DLG_UPDATE_INSTALL_ABORT { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH - LOCAL_BUTTON_WIDTH, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT + + RSC_SP_FLGR_SPACE_Y + RSC_CD_FIXEDLINE_HEIGHT + + RSC_SP_FLGR_SPACE_Y); + + Size = MAP_APPFONT(LOCAL_BUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + Text[en-US] = "Cancel Update"; + DefButton = TRUE; + }; + + HelpButton RID_DLG_UPDATE_INSTALL_HELP { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT + + RSC_SP_FLGR_SPACE_Y + RSC_CD_FIXEDLINE_HEIGHT + + RSC_SP_FLGR_SPACE_Y); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + }; + + + String RID_DLG_UPDATE_INSTALL_INSTALLING { + Text[en-US] = "Installing extensions..."; + }; + + String RID_DLG_UPDATE_INSTALL_FINISHED { + Text[en-US] = "Installation finished"; + }; + + String RID_DLG_UPDATE_INSTALL_NO_ERRORS { + Text[en-US] = "No errors."; + }; + + String RID_DLG_UPDATE_INSTALL_ERROR_DOWNLOAD { + Text[en-US] = "Error while downloading extension %NAME. "; + }; + + String RID_DLG_UPDATE_INSTALL_THIS_ERROR_OCCURRED { + Text[en-US] = "The error message is: "; + }; + + + String RID_DLG_UPDATE_INSTALL_ERROR_INSTALLATION { + Text[en-US] = "Error while installing extension %NAME. "; + }; + + String RID_DLG_UPDATE_INSTALL_ERROR_LIC_DECLINED { + Text[en-US] = "The license agreement for extension %NAME was refused. "; + }; + + String RID_DLG_UPDATE_INSTALL_EXTENSION_NOINSTALL{ + Text[en-US] = "The extension will not be installed."; + }; + +}; + diff --git a/desktop/source/deployment/gui/dp_gui_versionboxes.src b/desktop/source/deployment/gui/dp_gui_versionboxes.src new file mode 100644 index 000000000000..878521ad6dd2 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_versionboxes.src @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_gui.hrc" + +WarningBox RID_WARNINGBOX_VERSION_LESS { + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "The newer version $DEPLOYED is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +}; + +String RID_STR_WARNINGBOX_VERSION_LESS_DIFFERENT_NAMES { + Text [en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "The newer version $DEPLOYED, named \'$OLDNAME\', is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +}; + +WarningBox RID_WARNINGBOX_VERSION_EQUAL { + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "That version is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +}; + +String RID_STR_WARNINGBOX_VERSION_EQUAL_DIFFERENT_NAMES { + Text [en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "That version, named \'$OLDNAME\', is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +}; + +WarningBox RID_WARNINGBOX_VERSION_GREATER { + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_OK; + Message[en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "The older version $DEPLOYED is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +}; + +String RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES { + TEXT [en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "The older version $DEPLOYED, named \'$OLDNAME\', is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +};
\ No newline at end of file diff --git a/desktop/source/deployment/gui/license_dialog.cxx b/desktop/source/deployment/gui/license_dialog.cxx new file mode 100644 index 000000000000..ebe7c2b52ecb --- /dev/null +++ b/desktop/source/deployment/gui/license_dialog.cxx @@ -0,0 +1,325 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "cppuhelper/implbase2.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "unotools/configmgr.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/unwrapargs.hxx" +#include "i18npool/mslangid.hxx" +#include "vcl/svapp.hxx" +#include "vcl/msgbox.hxx" +#include "toolkit/helper/vclunohelper.hxx" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/task/XJobExecutor.hpp" +#include "svtools/svmedit.hxx" +#include "svl/lstner.hxx" +#include "svtools/xtextedt.hxx" +#include <vcl/scrbar.hxx> +#include "vcl/threadex.hxx" + + + +#include "boost/bind.hpp" +#include "dp_gui_shared.hxx" +#include "license_dialog.hxx" +#include "dp_gui.hrc" + +using namespace ::dp_misc; +namespace cssu = ::com::sun::star::uno; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace dp_gui { + +class LicenseView : public MultiLineEdit, public SfxListener +{ + sal_Bool mbEndReached; + Link maEndReachedHdl; + Link maScrolledHdl; + +public: + LicenseView( Window* pParent, const ResId& rResId ); + ~LicenseView(); + + void ScrollDown( ScrollType eScroll ); + + sal_Bool IsEndReached() const; + sal_Bool EndReached() const { return mbEndReached; } + void SetEndReached( sal_Bool bEnd ) { mbEndReached = bEnd; } + + void SetEndReachedHdl( const Link& rHdl ) { maEndReachedHdl = rHdl; } + const Link& GetAutocompleteHdl() const { return maEndReachedHdl; } + + void SetScrolledHdl( const Link& rHdl ) { maScrolledHdl = rHdl; } + const Link& GetScrolledHdl() const { return maScrolledHdl; } + + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); + +protected: + using MultiLineEdit::Notify; +}; + +struct LicenseDialogImpl : public ModalDialog +{ + cssu::Reference<cssu::XComponentContext> m_xComponentContext; + FixedText m_ftHead; + FixedText m_ftBody1; + FixedText m_ftBody1Txt; + FixedText m_ftBody2; + FixedText m_ftBody2Txt; + FixedImage m_fiArrow1; + FixedImage m_fiArrow2; + LicenseView m_mlLicense; + PushButton m_pbDown; + FixedLine m_flBottom; + + OKButton m_acceptButton; + CancelButton m_declineButton; + + DECL_LINK(PageDownHdl, PushButton*); + DECL_LINK(ScrolledHdl, LicenseView*); + DECL_LINK(EndReachedHdl, LicenseView*); + + bool m_bLicenseRead; + + virtual ~LicenseDialogImpl(); + + LicenseDialogImpl( + Window * pParent, + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const ::rtl::OUString & sExtensionName, + const ::rtl::OUString & sLicenseText); + + virtual void Activate(); + +}; + +LicenseView::LicenseView( Window* pParent, const ResId& rResId ) + : MultiLineEdit( pParent, rResId ) +{ + SetLeftMargin( 5 ); + mbEndReached = IsEndReached(); + StartListening( *GetTextEngine() ); +} + +LicenseView::~LicenseView() +{ + maEndReachedHdl = Link(); + maScrolledHdl = Link(); + EndListeningAll(); +} + +void LicenseView::ScrollDown( ScrollType eScroll ) +{ + ScrollBar* pScroll = GetVScrollBar(); + if ( pScroll ) + pScroll->DoScrollAction( eScroll ); +} + +sal_Bool LicenseView::IsEndReached() const +{ + sal_Bool bEndReached; + + ExtTextView* pView = GetTextView(); + ExtTextEngine* pEdit = GetTextEngine(); + sal_uLong nHeight = pEdit->GetTextHeight(); + Size aOutSize = pView->GetWindow()->GetOutputSizePixel(); + Point aBottom( 0, aOutSize.Height() ); + + if ( (sal_uLong) pView->GetDocPos( aBottom ).Y() >= nHeight - 1 ) + bEndReached = sal_True; + else + bEndReached = sal_False; + + return bEndReached; +} + +void LicenseView::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.IsA( TYPE(TextHint) ) ) + { + sal_Bool bLastVal = EndReached(); + sal_uLong nId = ((const TextHint&)rHint).GetId(); + + if ( nId == TEXT_HINT_PARAINSERTED ) + { + if ( bLastVal ) + mbEndReached = IsEndReached(); + } + else if ( nId == TEXT_HINT_VIEWSCROLLED ) + { + if ( ! mbEndReached ) + mbEndReached = IsEndReached(); + maScrolledHdl.Call( this ); + } + + if ( EndReached() && !bLastVal ) + { + maEndReachedHdl.Call( this ); + } + } +} + +//============================================================================================================== + +LicenseDialogImpl::LicenseDialogImpl( + Window * pParent, + cssu::Reference< cssu::XComponentContext > const & xContext, + const ::rtl::OUString & sExtensionName, + const ::rtl::OUString & sLicenseText): + ModalDialog(pParent, DpGuiResId(RID_DLG_LICENSE)) + ,m_xComponentContext(xContext) + ,m_ftHead(this, DpGuiResId(FT_LICENSE_HEADER)) + ,m_ftBody1(this, DpGuiResId(FT_LICENSE_BODY_1)) + ,m_ftBody1Txt(this, DpGuiResId(FT_LICENSE_BODY_1_TXT)) + ,m_ftBody2(this, DpGuiResId(FT_LICENSE_BODY_2)) + ,m_ftBody2Txt(this, DpGuiResId(FT_LICENSE_BODY_2_TXT)) + ,m_fiArrow1(this, DpGuiResId(FI_LICENSE_ARROW1)) + ,m_fiArrow2(this, DpGuiResId(FI_LICENSE_ARROW2)) + ,m_mlLicense(this, DpGuiResId(ML_LICENSE)) + ,m_pbDown(this, DpGuiResId(PB_LICENSE_DOWN)) + ,m_flBottom(this, DpGuiResId(FL_LICENSE)) + ,m_acceptButton(this, DpGuiResId(BTN_LICENSE_ACCEPT)) + ,m_declineButton(this, DpGuiResId(BTN_LICENSE_DECLINE)) + ,m_bLicenseRead(false) + +{ + + FreeResource(); + + m_acceptButton.SetUniqueId(UID_BTN_LICENSE_ACCEPT); + m_fiArrow1.Show(true); + m_fiArrow2.Show(false); + m_mlLicense.SetText(sLicenseText); + m_ftHead.SetText(m_ftHead.GetText() + OUString('\n') + sExtensionName); + + m_mlLicense.SetEndReachedHdl( LINK(this, LicenseDialogImpl, EndReachedHdl) ); + m_mlLicense.SetScrolledHdl( LINK(this, LicenseDialogImpl, ScrolledHdl) ); + m_pbDown.SetClickHdl( LINK(this, LicenseDialogImpl, PageDownHdl) ); + + // We want a automatic repeating page down button + WinBits aStyle = m_pbDown.GetStyle(); + aStyle |= WB_REPEAT; + m_pbDown.SetStyle( aStyle ); +} + +LicenseDialogImpl::~LicenseDialogImpl() +{ +} + +void LicenseDialogImpl::Activate() +{ + if (!m_bLicenseRead) + { + //Only enable the scroll down button if the license text does not fit into the window + if (m_mlLicense.IsEndReached()) + { + m_pbDown.Disable(); + m_acceptButton.Enable(); + m_acceptButton.GrabFocus(); + } + else + { + m_pbDown.Enable(); + m_pbDown.GrabFocus(); + m_acceptButton.Disable(); + } + } +} + +IMPL_LINK( LicenseDialogImpl, ScrolledHdl, LicenseView *, EMPTYARG ) +{ + + if (m_mlLicense.IsEndReached()) + m_pbDown.Disable(); + else + m_pbDown.Enable(); + + return 0; +} + +IMPL_LINK( LicenseDialogImpl, PageDownHdl, PushButton *, EMPTYARG ) +{ + m_mlLicense.ScrollDown( SCROLL_PAGEDOWN ); + return 0; +} + +IMPL_LINK( LicenseDialogImpl, EndReachedHdl, LicenseView *, EMPTYARG ) +{ + m_acceptButton.Enable(); + m_acceptButton.GrabFocus(); + m_fiArrow1.Show(false); + m_fiArrow2.Show(true); + m_bLicenseRead = true; + return 0; +} + +//================================================================================= + + + + +LicenseDialog::LicenseDialog( Sequence<Any> const& args, + Reference<XComponentContext> const& xComponentContext) + : m_xComponentContext(xComponentContext) +{ + comphelper::unwrapArgs( args, m_parent, m_sExtensionName, m_sLicenseText ); +} + +// XExecutableDialog +//______________________________________________________________________________ +void LicenseDialog::setTitle( OUString const & ) throw (RuntimeException) +{ + +} + +//______________________________________________________________________________ +sal_Int16 LicenseDialog::execute() throw (RuntimeException) +{ + return vcl::solarthread::syncExecute( + boost::bind( &LicenseDialog::solar_execute, this)); +} + +sal_Int16 LicenseDialog::solar_execute() +{ + std::auto_ptr<LicenseDialogImpl> dlg( + new LicenseDialogImpl( + VCLUnoHelper::GetWindow(m_parent), + m_xComponentContext, m_sExtensionName, m_sLicenseText)); + + return dlg->Execute(); +} + +} // namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/license_dialog.hxx b/desktop/source/deployment/gui/license_dialog.hxx new file mode 100644 index 000000000000..2bddfd4f4102 --- /dev/null +++ b/desktop/source/deployment/gui/license_dialog.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_GUI_LICENSE_DIALOG_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_LICENSE_DIALOG_HXX + +#include "dp_gui.h" +#include "cppuhelper/implbase1.hxx" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/task/XJobExecutor.hpp" +#include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" + +#include "boost/bind.hpp" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace dp_gui { + +class LicenseDialog + : public ::cppu::WeakImplHelper1<ui::dialogs::XExecutableDialog> +{ + Reference<XComponentContext> const m_xComponentContext; + Reference<awt::XWindow> /* const */ m_parent; + OUString m_sExtensionName; + OUString /* const */ m_sLicenseText; + OUString m_initialTitle; + + sal_Int16 solar_execute(); + +public: + LicenseDialog( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XExecutableDialog + virtual void SAL_CALL setTitle( OUString const & title ) + throw (RuntimeException); + virtual sal_Int16 SAL_CALL execute() throw (RuntimeException); +}; +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/makefile.mk b/desktop/source/deployment/gui/makefile.mk new file mode 100755 index 000000000000..eed15ac25be7 --- /dev/null +++ b/desktop/source/deployment/gui/makefile.mk @@ -0,0 +1,109 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deploymentgui +ENABLE_EXCEPTIONS = TRUE +NO_BSYMBOLIC = TRUE +USE_PCH := +ENABLE_PCH := +PRJINC:=..$/.. + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/source$/deployment$/inc$/dp_misc.mk +DLLPRE = + +SLOFILES = \ + $(SLO)$/dp_gui_service.obj \ + $(SLO)$/dp_gui_extlistbox.obj \ + $(SLO)$/dp_gui_dialog2.obj \ + $(SLO)$/dp_gui_theextmgr.obj \ + $(SLO)$/license_dialog.obj \ + $(SLO)$/dp_gui_dependencydialog.obj \ + $(SLO)$/dp_gui_thread.obj \ + $(SLO)$/dp_gui_updatedialog.obj \ + $(SLO)$/dp_gui_updateinstalldialog.obj \ + $(SLO)$/dp_gui_autoscrolledit.obj \ + $(SLO)$/dp_gui_extensioncmdqueue.obj \ + $(SLO)$/descedit.obj + +SHL1TARGET = $(TARGET)$(DLLPOSTFIX).uno +SHL1VERSIONMAP = $(SOLARENV)/src/component.map + +SHL1STDLIBS = \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(UCBHELPERLIB) \ + $(COMPHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(I18NISOLANGLIB) \ + $(TKLIB) \ + $(VCLLIB) \ + $(SVTOOLLIB) \ + $(SVLLIB) \ + $(SVXLIB) \ + $(SVXCORELIB) \ + $(SFXLIB) \ + $(DEPLOYMENTMISCLIB) \ + $(OLE32LIB) + +SHL1DEPN = +SHL1IMPLIB = i$(TARGET) +SHL1LIBS = $(SLB)$/$(TARGET).lib +SHL1DEF = $(MISC)$/$(SHL1TARGET).def + +DEF1NAME = $(SHL1TARGET) + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_gui_dialog.src \ + dp_gui_dialog2.src \ + dp_gui_backend.src \ + dp_gui_dependencydialog.src \ + dp_gui_updatedialog.src \ + dp_gui_versionboxes.src \ + dp_gui_updateinstalldialog.src + +RESLIB1NAME = $(TARGET) +RESLIB1SRSFILES = $(SRS)$/$(TARGET).srs +RESLIB1IMAGES= $(PRJ)$/res + +.INCLUDE : target.mk + + +ALLTAR : $(MISC)/deploymentgui.component + +$(MISC)/deploymentgui.component .ERRREMOVE : \ + $(SOLARENV)/bin/createcomponent.xslt deploymentgui.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt deploymentgui.component diff --git a/desktop/source/deployment/inc/db.hxx b/desktop/source/deployment/inc/db.hxx new file mode 100644 index 000000000000..a2dd27df80b2 --- /dev/null +++ b/desktop/source/deployment/inc/db.hxx @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 BERKELEYDBPROXY_DB_HXX_ +#define BERKELEYDBPROXY_DB_HXX_ + +#include <boost/noncopyable.hpp> + +#ifdef SYSTEM_DB_HEADER +#include SYSTEM_DB_HEADER +#else +#include <berkeleydb/db.h> +#endif + +#include <rtl/string.hxx> +#include "dp_misc_api.hxx" + +extern "C" { + typedef void *(*db_malloc_fcn_type)(size_t); + typedef void *(*db_realloc_fcn_type)(void *, size_t); + typedef void (*db_free_fcn_type)(void *); +} + +namespace berkeleydbproxy { + + class DbEnv; + class Dbc; + class Dbt; + + class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC DbException + { + rtl::OString what_; + public: + explicit DbException(rtl::OString const & theWhat) + : what_(theWhat) + {} + + const char *what() const + { return what_.getStr(); } + int get_errno() const + { return 0; } + }; + + + class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC DbEnv : boost::noncopyable + { + friend class Db; + + private: + DB_ENV* m_pDBENV; + + public: + static char *strerror(int); + }; + + class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Db : boost::noncopyable + { + private: + DB* m_pDBP; + + public: + Db(DbEnv* dbbenv,u_int32_t flags); + ~Db(); + + int close(u_int32_t flags); + + int open(DB_TXN *txnid, + const char *file, + const char *database, + DBTYPE type, + u_int32_t flags, + int mode); + + int sync(u_int32_t flags); + int del(Dbt *key, u_int32_t flags); + + int get(DB_TXN* txnid, Dbt *key, Dbt *data, u_int32_t flags); + int put(DB_TXN* txnid, Dbt *key, Dbt *data, u_int32_t flags); + + int cursor(DB_TXN *txnid, Dbc **cursorp, u_int32_t flags); + }; + + class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Dbc : boost::noncopyable + { + friend class Db; + friend class Dbt; + + private: + DBC* m_pDBC; + + SAL_DLLPRIVATE explicit Dbc(DBC* pDBC); + SAL_DLLPRIVATE ~Dbc(); + + public: + int close(); + + int get(Dbt *key, Dbt *data, u_int32_t flags); + }; + + class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Dbt: private DBT + { + friend class Db; + friend class Dbc; + + public: + Dbt(void *data_arg, u_int32_t size_arg); + + Dbt(); + Dbt(const Dbt & other); + Dbt & operator=(const Dbt & other); + + ~Dbt(); + + void *get_data() const; + void set_data(void *value); + + u_int32_t get_size() const; + void set_size(u_int32_t value); + }; +} + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_dependencies.hxx b/desktop/source/deployment/inc/dp_dependencies.hxx new file mode 100644 index 000000000000..246d176bc4ec --- /dev/null +++ b/desktop/source/deployment/inc/dp_dependencies.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_INC_DP_DEPENDENCIES_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_INC_DP_DEPENDENCIES_HXX + +#include "unotools/configmgr.hxx" +#include "sal/config.h" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "dp_misc_api.hxx" + +/// @HTML + +namespace com { namespace sun { namespace star { namespace xml { namespace dom { + class XElement; +} } } } } +namespace dp_misc { class DescriptionInfoset; } +namespace rtl { class OUString; } + +namespace dp_misc { + +struct BrandName : public ::rtl::StaticWithInit< ::rtl::OUString, BrandName > { + const ::rtl::OUString operator () () { + return ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTNAME ).get< ::rtl::OUString >(); + } +}; + + +/** + Dependency handling. +*/ +namespace Dependencies { + /** + Check for unsatisfied dependencies. + + @param infoset + the infoset containing the dependencies to check + + @return + a list of the unsatisfied dependencies from <code>infoset</code> (in no + specific order) + */ + DESKTOP_DEPLOYMENTMISC_DLLPUBLIC + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XElement > > + check(::dp_misc::DescriptionInfoset const & infoset); + + /** + Obtain the (human-readable) error message of a failed dependency. + + @param dependency + a dependency represented as a non-null XML element + + @return + the name of the dependency; will never be empty, as a localized + “unknown” is substituted for an empty/missing name + */ + DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString getErrorText( + ::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XElement > const & dependency); +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_descriptioninfoset.hxx b/desktop/source/deployment/inc/dp_descriptioninfoset.hxx new file mode 100644 index 000000000000..d16e9127af8a --- /dev/null +++ b/desktop/source/deployment/inc/dp_descriptioninfoset.hxx @@ -0,0 +1,302 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_INC_DP_DESCRIPTIONINFOSET_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_INC_DP_DESCRIPTIONINFOSET_HXX + +#include "sal/config.h" + +#include "boost/optional.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" +#include "dp_misc_api.hxx" + +/// @HTML + +namespace com { namespace sun { namespace star { + namespace lang { struct Locale; } + namespace uno { class XComponentContext; } + namespace xml { + namespace dom { + class XNode; + class XNodeList; + } + namespace xpath { class XXPathAPI; } + } +} } } +namespace rtl { class OUString; } + +namespace dp_misc { + +struct DESKTOP_DEPLOYMENTMISC_DLLPUBLIC SimpleLicenseAttributes +{ + ::rtl::OUString acceptBy; + //Attribute suppress-on-update. Default is false. + bool suppressOnUpdate; + //Attribute suppress-if-required. Default is false. + bool suppressIfRequired; +}; + + +/** + Access to the content of an XML <code>description</code> element. + + <p>This works for <code>description</code> elements in both the + <code>description.xml</code> file and online update information formats.</p> +*/ +class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC DescriptionInfoset { +public: + /** + Create an instance. + + @param context + a non-null component context + + @param element + a <code>description</code> element; may be null (equivalent to an element + with no content) + */ + DescriptionInfoset( + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const & context, + ::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XNode > const & element); + + ~DescriptionInfoset(); + + /** + Return the identifier. + + @return + the identifier, or an empty <code>optional</code> if none is specified + */ + ::boost::optional< ::rtl::OUString > getIdentifier() const; + + /** + Return the textual version representation. + + @return + textual version representation + */ + ::rtl::OUString getVersion() const; + + /** + Returns a list of supported platforms. + + If the extension does not specify a platform by leaving out the platform element + then we assume that the extension supports all platforms. In this case the returned + sequence will have one element, which is "all". + If the platform element is present but does not specify a platform then an empty + sequence is returned. Examples for invalid platform elements: + <pre> + <platform />, <platform value="" />, <platfrom value=","> + </pre> + + The value attribute can contain various platform tokens. They must be separated by + commas.Each token will be stripped from leading and trailing white space (trim()). + */ + ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedPlaforms() const; + + /** + Returns the localized publisher name and the corresponding URL. + + In case there is no publisher element then a pair of two empty strings is returned. + */ + ::std::pair< ::rtl::OUString, ::rtl::OUString > getLocalizedPublisherNameAndURL() const; + + /** + Returns the URL for the release notes corresponding to the office's locale. + + In case there is no release-notes element then an empty string is returned. + */ + ::rtl::OUString getLocalizedReleaseNotesURL() const; + + /** returns the relative path to the license file. + + In case there is no simple-license element then an empty string is returned. + */ + ::rtl::OUString getLocalizedLicenseURL() const; + + /** returns the attributes of the simple-license element + + As long as there is a simple-license element, the function will return + the structure. If it does not exist, then the optional object is uninitialized. + */ + ::boost::optional<SimpleLicenseAttributes> getSimpleLicenseAttributes() const; + + /** returns the localized display name of the extensions. + + In case there is no localized display-name then an empty string is returned. + */ + ::rtl::OUString getLocalizedDisplayName() const; + + /** + returns the download website URL from the update information. + + There can be multiple URLs where each is assigned to a particular locale. + The function returs the URL which locale matches best the one used in the office. + + The return value is an optional because it may be necessary to find out if there + was a value provided or not. This is necessary to flag the extension in the update dialog + properly as "browser based update". The return value will only then not be initialized + if there is no <code><update-website></code>. If the element exists, then it must + have at least one child element containing an URL. + + The <code><update-website></code> and <code><update-download></code> + elements are mutually exclusiv. + + @return + the download website URL, or an empty <code>optional</code> if none is + specified + */ + ::boost::optional< ::rtl::OUString > getLocalizedUpdateWebsiteURL() const; + + /** returns the relative URL to the description. + + The URL is relative to the root directory of the extensions. + */ + ::rtl::OUString getLocalizedDescriptionURL() const; + /** + Return the dependencies. + + @return + dependencies; will never be null + */ + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNodeList > + getDependencies() const; + + /** + Return the update information URLs. + + @return + update information URLs + */ + ::com::sun::star::uno::Sequence< ::rtl::OUString > + getUpdateInformationUrls() const; + + /** + Return the download URLs from the update information. + + Because the <code><update-download></code> and the <code><update-website></code> + elements are mutually exclusive one may need to determine exacty if the element + was provided. + + @return + download URLs + */ + ::com::sun::star::uno::Sequence< ::rtl::OUString > + getUpdateDownloadUrls() const; + + /** + Returns the URL for the icon image. + */ + ::rtl::OUString getIconURL( sal_Bool bHighContrast ) const; + + bool hasDescription() const; + +private: + SAL_DLLPRIVATE ::boost::optional< ::rtl::OUString > getOptionalValue( + ::rtl::OUString const & expression) const; + + SAL_DLLPRIVATE ::com::sun::star::uno::Sequence< ::rtl::OUString > getUrls( + ::rtl::OUString const & expression) const; + + /** Retrieves a child element which as lang attribute which matches the office locale. + + Only top-level children are taken into account. It is also assumed that they are all + of the same element type and have a lang attribute. The matching algoritm is according + to RFC 3066, with the exception that only one variant is allowed. + @param parent + the expression used to obtain the parent of the localized children. It can be null. + Then a null reference is returned. + */ + SAL_DLLPRIVATE ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > + getLocalizedChild( ::rtl::OUString const & sParent) const; + SAL_DLLPRIVATE ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode> + matchFullLocale(::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XNode > const & xParent, ::rtl::OUString const & sLocale) const; + SAL_DLLPRIVATE ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode> + matchCountryAndLanguage(::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XNode > const & xParent, + ::com::sun::star::lang::Locale const & officeLocale) const; + SAL_DLLPRIVATE ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode> + matchLanguage( + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > const & xParent, + ::com::sun::star::lang::Locale const & officeLocale) const; + + /** If there is no child element with a locale matching the office locale, then we use + the first child. In the case of the simple-license we also use the former default locale, which + was determined by the default-license-id (/description/registration/simple-license/@default-license-id) + and the license-id attributes (/description/registration/simple-license/license-text/@license-id). + However, since OOo 2.4 we use also the first child as default for the license + unless the two attributes are present. + */ + SAL_DLLPRIVATE ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode> + getChildWithDefaultLocale( + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > const & xParent) const; + /** + @param out_bParentExists + indicates if the element node specified in sXPathParent exists. + */ + SAL_DLLPRIVATE ::rtl::OUString getLocalizedHREFAttrFromChild( + ::rtl::OUString const & sXPathParent, bool * out_bParentExists) const; + + static SAL_DLLPRIVATE ::rtl::OUString + localeToString(::com::sun::star::lang::Locale const & locale); + + /** Gets the node value for a given expression. The expression is used in + m_xpath-selectSingleNode. The value of the returned node is return value + of this function. + */ + SAL_DLLPRIVATE ::rtl::OUString + getNodeValueFromExpression(::rtl::OUString const & expression) const; + + ::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XNode > m_element; + ::com::sun::star::uno::Reference< + ::com::sun::star::xml::xpath::XXPathAPI > m_xpath; +}; + +inline bool DescriptionInfoset::hasDescription() const +{ + return m_element.is(); +} + +/** creates a DescriptionInfoset object. + + The argument sExtensionFolderURL is a file URL to extension folder containing + the description.xml. + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +DescriptionInfoset getDescriptionInfoset(::rtl::OUString const & sExtensionFolderURL); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_identifier.hxx b/desktop/source/deployment/inc/dp_identifier.hxx new file mode 100644 index 000000000000..f58b7663a173 --- /dev/null +++ b/desktop/source/deployment/inc/dp_identifier.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_INC_DP_IDENTIFIER_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_INC_DP_IDENTIFIER_HXX + +#include "sal/config.h" + +#include "boost/optional.hpp" +#include "com/sun/star/uno/Reference.hxx" + +#include "dp_misc_api.hxx" + +namespace com { namespace sun { namespace star { namespace deployment { + class XPackage; +} } } } +namespace rtl { class OUString; } + +namespace dp_misc { + +/** + Generates an identifier from an optional identifier. + + @param optional + an optional identifier + + @param fileName + a file name + + @return + the given optional identifier if present, otherwise a legacy identifier based + on the given file name +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString generateIdentifier( + ::boost::optional< ::rtl::OUString > const & optional, + ::rtl::OUString const & fileName); + +/** + Gets the identifier of a package. + + @param package + a non-null package + + @return + the explicit identifier of the given package if present, otherwise the + implicit legacy identifier of the given package + + @throws com::sun::star::uno::RuntimeException +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString getIdentifier( + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > + const & package); + +/** + Generates a legacy identifier based on a file name. + + @param fileName + a file name + + @return + a legacy identifier based on the given file name +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString generateLegacyIdentifier( + ::rtl::OUString const & fileName); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_interact.h b/desktop/source/deployment/inc/dp_interact.h new file mode 100755 index 000000000000..7a59e944f6af --- /dev/null +++ b/desktop/source/deployment/inc/dp_interact.h @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_INTERACT_H +#define INCLUDED_DP_INTERACT_H + +#include "rtl/ref.hxx" +#include "cppuhelper/implbase1.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/task/XAbortChannel.hpp" +#include "dp_misc_api.hxx" + +namespace css = ::com::sun::star; + +namespace dp_misc +{ + +inline void progressUpdate( + ::rtl::OUString const & status, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) +{ + if (xCmdEnv.is()) { + css::uno::Reference<css::ucb::XProgressHandler> xProgressHandler( + xCmdEnv->getProgressHandler() ); + if (xProgressHandler.is()) { + xProgressHandler->update( css::uno::makeAny(status) ); + } + } +} + +//============================================================================== +class ProgressLevel +{ + css::uno::Reference<css::ucb::XProgressHandler> m_xProgressHandler; + +public: + inline ~ProgressLevel(); + inline ProgressLevel( + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + ::rtl::OUString const & status ); + + inline void update( ::rtl::OUString const & status ) const; + inline void update( css::uno::Any const & status ) const; +}; + +//______________________________________________________________________________ +inline ProgressLevel::ProgressLevel( + css::uno::Reference< css::ucb::XCommandEnvironment > const & xCmdEnv, + ::rtl::OUString const & status ) +{ + if (xCmdEnv.is()) + m_xProgressHandler = xCmdEnv->getProgressHandler(); + if (m_xProgressHandler.is()) + m_xProgressHandler->push( css::uno::makeAny(status) ); +} + +//______________________________________________________________________________ +inline ProgressLevel::~ProgressLevel() +{ + if (m_xProgressHandler.is()) + m_xProgressHandler->pop(); +} + +//______________________________________________________________________________ +inline void ProgressLevel::update( ::rtl::OUString const & status ) const +{ + if (m_xProgressHandler.is()) + m_xProgressHandler->update( css::uno::makeAny(status) ); +} + +//______________________________________________________________________________ +inline void ProgressLevel::update( css::uno::Any const & status ) const +{ + if (m_xProgressHandler.is()) + m_xProgressHandler->update( status ); +} + +//############################################################################## + +/** @return true if ia handler is present and any selection has been chosen + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool interactContinuation( + css::uno::Any const & request, + css::uno::Type const & continuation, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool * pcont, bool * pabort ); + +//############################################################################## + +//============================================================================== +class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC AbortChannel : + public ::cppu::WeakImplHelper1<css::task::XAbortChannel> +{ + bool m_aborted; + css::uno::Reference<css::task::XAbortChannel> m_xNext; + +public: + inline AbortChannel() : m_aborted( false ) {} + inline static AbortChannel * get( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel ) + { return static_cast<AbortChannel *>(xAbortChannel.get()); } + + inline bool isAborted() const { return m_aborted; } + + // XAbortChannel + virtual void SAL_CALL sendAbort() throw (css::uno::RuntimeException); + + class SAL_DLLPRIVATE Chain + { + const ::rtl::Reference<AbortChannel> m_abortChannel; + public: + inline Chain( + ::rtl::Reference<AbortChannel> const & abortChannel, + css::uno::Reference<css::task::XAbortChannel> const & xNext ) + : m_abortChannel( abortChannel ) + { if (m_abortChannel.is()) m_abortChannel->m_xNext = xNext; } + inline ~Chain() + { if (m_abortChannel.is()) m_abortChannel->m_xNext.clear(); } + }; + friend class Chain; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_misc.h b/desktop/source/deployment/inc/dp_misc.h new file mode 100755 index 000000000000..9e912531e9f8 --- /dev/null +++ b/desktop/source/deployment/inc/dp_misc.h @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_MISC_H +#define INCLUDED_DP_MISC_H + +#include "rtl/ustrbuf.hxx" +#include "rtl/instance.hxx" +#include "osl/mutex.hxx" +#include "osl/process.h" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/deployment/XPackageRegistry.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/awt/XWindow.hpp" +#include "dp_misc_api.hxx" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) +#define ARLEN(x) (sizeof (x) / sizeof *(x)) + +namespace dp_misc { + +const sal_Char CR = 0x0d; +const sal_Char LF = 0x0a; + +//============================================================================== +class MutexHolder +{ + mutable ::osl::Mutex m_mutex; +protected: + inline ::osl::Mutex & getMutex() const { return m_mutex; } +}; + +//============================================================================== +inline void try_dispose( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> const & x ) +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> xComp( x, ::com::sun::star::uno::UNO_QUERY ); + if (xComp.is()) + xComp->dispose(); +} + +//############################################################################## + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString expandUnoRcTerm( ::rtl::OUString const & term ); + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString makeRcTerm( ::rtl::OUString const & url ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString expandUnoRcUrl( ::rtl::OUString const & url ); + +//============================================================================== + +/** appends a relative path to a url. + + The relative path must already be correctly encoded for use in an URL. + If the URL starts with vnd.sun.star.expand then the relative path will + be again encoded for use in an "expand" URL. + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString makeURL( + ::rtl::OUString const & baseURL, ::rtl::OUString const & relPath ); + + +/** appends a relative path to a url. + + This is the same as makeURL, but the relative Path must me a segment + of an system path. + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString makeURLAppendSysPathSegment( + ::rtl::OUString const & baseURL, ::rtl::OUString const & relPath ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString generateRandomPipeId(); + +class AbortChannel; +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> resolveUnoURL( + ::rtl::OUString const & connectString, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> const & xLocalContext, + AbortChannel * abortChannel = 0 ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool office_is_running(); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +oslProcess raiseProcess( ::rtl::OUString const & appURL, + ::com::sun::star::uno::Sequence< ::rtl::OUString > const & args ); + +//============================================================================== + +/** writes the argument string to the console. + On Linux/Unix/etc. it converts the UTF16 string to an ANSI string using + osl_getThreadTextEncoding() as target encoding. On Windows it uses WriteFile + with the standard out stream. unopkg.com reads the data and prints them out using + WriteConsoleW. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void writeConsole(::rtl::OUString const & sText); + +/** writes the argument string to the console. + On Linux/Unix/etc. the string is passed into fprintf without any conversion. + On Windows the string is converted to UTF16 assuming the argument is UTF8 + encoded. The UTF16 string is written to stdout with WriteFile. unopkg.com + reads the data and prints them out using WriteConsoleW. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void writeConsole(::rtl::OString const & sText); + +/** writes the argument to the console using the error stream. + Otherwise the same as writeConsole. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void writeConsoleError(::rtl::OUString const & sText); + + +/** writes the argument to the console using the error stream. + Otherwise the same as writeConsole. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void writeConsoleError(::rtl::OString const & sText); + + +/** reads from the console. + On Linux/Unix/etc. it uses fgets to read char values and converts them to OUString + using osl_getThreadTextEncoding as target encoding. The returned string has a maximum + size of 1024 and does NOT include leading and trailing white space(applied OUString::trim()) +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString readConsole(); + +/** print the text to the console in a debug build. + The argument is forwarded to writeConsole. The function does not add new line. + The code is only executed if OSL_DEBUG_LEVEL > 1 +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void TRACE(::rtl::OUString const & sText); +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void TRACE(::rtl::OString const & sText); + +/** registers or revokes shared or bundled extensions which have been + recently added or removed. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void syncRepositories(::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment> const & xCmdEnv); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_misc.mk b/desktop/source/deployment/inc/dp_misc.mk new file mode 100755 index 000000000000..a2d3d6e5e05b --- /dev/null +++ b/desktop/source/deployment/inc/dp_misc.mk @@ -0,0 +1,40 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +# To be included after settings.mk + +# Although the deployment shared library is a UNO component, it also exports +# some C++ functionality: +.IF "$(OS)" == "WNT" +.IF "$(COM)" == "GCC" +DEPLOYMENTMISCLIB = -ldeploymentmisc$(DLLPOSTFIX) +.ELSE +DEPLOYMENTMISCLIB = ideploymentmisc$(DLLPOSTFIX).lib +.ENDIF +.ELSE +DEPLOYMENTMISCLIB = -ldeploymentmisc$(DLLPOSTFIX) +.ENDIF diff --git a/desktop/source/deployment/inc/dp_misc_api.hxx b/desktop/source/deployment/inc/dp_misc_api.hxx new file mode 100644 index 000000000000..fbc248a1dfb2 --- /dev/null +++ b/desktop/source/deployment/inc/dp_misc_api.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_INC_DP_MISC_API_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_INC_DP_MISC_API_HXX + +#include "sal/config.h" +#include "sal/types.h" + +#if defined DESKTOP_DEPLOYMENTMISC_DLLIMPLEMENTATION +#define DESKTOP_DEPLOYMENTMISC_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define DESKTOP_DEPLOYMENTMISC_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_persmap.h b/desktop/source/deployment/inc/dp_persmap.h new file mode 100755 index 000000000000..c078cf902ec5 --- /dev/null +++ b/desktop/source/deployment/inc/dp_persmap.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_PERSMAP_H +#define INCLUDED_DP_PERSMAP_H + +#include "rtl/ustring.hxx" +#include "db.hxx" +#include <boost/unordered_map.hpp> + +using namespace berkeleydbproxy; + +namespace dp_misc +{ + +typedef ::boost::unordered_map< + ::rtl::OString, ::rtl::OString, ::rtl::OStringHash > t_string2string_map; + +//============================================================================== +class PersistentMap +{ + ::rtl::OUString m_sysPath; + mutable Db m_db; + void throw_rtexc( int err, char const * msg = 0 ) const; + +public: + ~PersistentMap(); + PersistentMap( ::rtl::OUString const & url, bool readOnly ); + /** in mem db */ + PersistentMap(); + + bool has( ::rtl::OString const & key ) const; + bool get( ::rtl::OString * value, ::rtl::OString const & key ) const; + t_string2string_map getEntries() const; + void put( ::rtl::OString const & key, ::rtl::OString const & value ); + bool erase( ::rtl::OString const & key, bool flush_immediately = true ); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_platform.hxx b/desktop/source/deployment/inc/dp_platform.hxx new file mode 100644 index 000000000000..b2b9fad07f49 --- /dev/null +++ b/desktop/source/deployment/inc/dp_platform.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_PLATFORM_HXX +#define INCLUDED_DP_PLATFORM_HXX + + +#include "dp_misc_api.hxx" + +#include "com/sun/star/uno/Sequence.hxx" +#include "rtl/ustring.hxx" + +namespace dp_misc +{ + + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString const & getPlatformString(); + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC + bool platform_fits( ::rtl::OUString const & platform_string ); + +/** determines if the current platform corresponds to one of the platform strings. + +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +bool hasValidPlatform( ::com::sun::star::uno::Sequence< ::rtl::OUString > const & platformStrings); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_resource.h b/desktop/source/deployment/inc/dp_resource.h new file mode 100755 index 000000000000..d7c16bb69b52 --- /dev/null +++ b/desktop/source/deployment/inc/dp_resource.h @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_RESOURCE_H +#define INCLUDED_DP_RESOURCE_H + +#include "tools/resmgr.hxx" +#include "tools/string.hxx" +#include "tools/resid.hxx" +#include "com/sun/star/lang/Locale.hpp" +#include "dp_misc.h" +#include <memory> +#include "dp_misc_api.hxx" + +namespace dp_misc { + +//============================================================================== +ResId getResId( sal_uInt16 id ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC String getResourceString( sal_uInt16 id ); + +template <typename Unique, sal_uInt16 id> +struct StaticResourceString : + public ::rtl::StaticWithInit< ::rtl::OUString, Unique > { + const ::rtl::OUString operator () () { return getResourceString(id); } +}; + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::com::sun::star::lang::Locale toLocale( ::rtl::OUString const & slang ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::com::sun::star::lang::Locale getOfficeLocale(); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString getOfficeLocaleString(); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_ucb.h b/desktop/source/deployment/inc/dp_ucb.h new file mode 100755 index 000000000000..52ac31369ac0 --- /dev/null +++ b/desktop/source/deployment/inc/dp_ucb.h @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_UCB_H +#define INCLUDED_DP_UCB_H + +#include <list> +#include "rtl/byteseq.hxx" +#include "rtl/instance.hxx" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "dp_misc_api.hxx" + +namespace ucbhelper +{ +class Content; +} + +namespace css = ::com::sun::star; + +namespace dp_misc { + +struct DESKTOP_DEPLOYMENTMISC_DLLPUBLIC StrTitle : + public rtl::StaticWithInit<rtl::OUString, StrTitle> +{ + const rtl::OUString operator () (); +}; + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_ucb_content( + ::ucbhelper::Content * ucb_content, + ::rtl::OUString const & url, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool throw_exc = true ); + +//============================================================================== +/** @return true if previously non-existing folder has been created + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_folder( + ::ucbhelper::Content * ucb_content, + ::rtl::OUString const & url, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool throw_exc = true ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool erase_path( + ::rtl::OUString const & url, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool throw_exc = true ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::ByteSequence readFile( ::ucbhelper::Content & ucb_content ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +bool readLine( ::rtl::OUString * res, ::rtl::OUString const & startingWith, + ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc ); + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +bool readProperties( ::std::list< ::std::pair< ::rtl::OUString, ::rtl::OUString> > & out_result, + ::ucbhelper::Content & ucb_content); + + + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_update.hxx b/desktop/source/deployment/inc/dp_update.hxx new file mode 100644 index 000000000000..1f22b2bb8d40 --- /dev/null +++ b/desktop/source/deployment/inc/dp_update.hxx @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_UPDATE_HXX +#define INCLUDED_DP_UPDATE_HXX + + +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/XUpdateInformationProvider.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" + +#include "rtl/ustrbuf.hxx" +#include "dp_misc_api.hxx" + +#include <map> +#include <vector> + +namespace dp_misc { + +/** returns the default update URL (for the update information) which + is used when an extension does not provide its own URL. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString getExtensionDefaultUpdateURL(); + +enum UPDATE_SOURCE +{ + UPDATE_SOURCE_NONE, + UPDATE_SOURCE_SHARED, + UPDATE_SOURCE_BUNDLED, + UPDATE_SOURCE_ONLINE +}; + +/* determine if an update is available which is installed in the + user repository. + + If the return value is UPDATE_SOURCE_NONE, then no update is + available, otherwise the return value determine from which the + repository the update is used. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +UPDATE_SOURCE isUpdateUserExtension( + bool bReadOnlyShared, + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion); + +/* determine if an update is available which is installed in the + shared repository. + + If the return value is UPDATE_SOURCE_NONE, then no update is + available, otherwise the return value determine from which the + repository the update is used. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +UPDATE_SOURCE isUpdateSharedExtension( + bool bReadOnlyShared, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion); + +/* determines the extension with the highest identifier and returns it + + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> +getExtensionWithHighestVersion( + ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage> > const & seqExtensionsWithSameId); + + +struct UpdateInfo +{ + UpdateInfo( ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> const & ext); + ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage> extension; +//version of the update + ::rtl::OUString version; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > info; +}; + +typedef std::map< ::rtl::OUString, UpdateInfo > UpdateInfoMap; + +/* + @param extensionList + List of extension for which online update information are to be obtained. If NULL, then + for update information are obtained for all installed extension. There may be only one extension + with a particular identifier contained in the list. If one extension is installed + in several repositories, then the one with the highest version must be used, because it contains + the more recent URLs for getting the update information (if at all). + @param out_errors + the first member of the pair is the extension and the second the exception that was produced + when processing the extension. + + @return + A map of UpdateInfo instances. If the parameter extensionList was given, then the map contains + at only information for those extensions. + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +UpdateInfoMap getOnlineUpdateInfos( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> const &xContext, + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager> const & xExtMgr, + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XUpdateInformationProvider > const & updateInformation, + std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > > const * extensionList, + ::std::vector< ::std::pair< ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage>, ::com::sun::star::uno::Any> > & out_errors); + +/* retunrs the highest version from the provided arguments. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString getHighestVersion( + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_version.hxx b/desktop/source/deployment/inc/dp_version.hxx new file mode 100644 index 000000000000..f335b986c5e3 --- /dev/null +++ b/desktop/source/deployment/inc/dp_version.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_INC_DP_VERSION_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_INC_DP_VERSION_HXX + +#include "sal/config.h" +#include "com/sun/star/uno/Reference.hxx" +#include "dp_misc_api.hxx" + +namespace com { namespace sun { namespace star { namespace deployment { + class XPackage; +} } } } +namespace rtl { class OUString; } + +namespace dp_misc { + +enum Order { LESS, EQUAL, GREATER }; + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order compareVersions( + ::rtl::OUString const & version1, ::rtl::OUString const & version2); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_xml.h b/desktop/source/deployment/inc/dp_xml.h new file mode 100755 index 000000000000..4e178e1b37bf --- /dev/null +++ b/desktop/source/deployment/inc/dp_xml.h @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_XML_H +#define INCLUDED_DP_XML_H + +#include "rtl/ref.hxx" +#include "rtl/ustrbuf.hxx" +#include "cppuhelper/implbase1.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/input/XRoot.hpp" +#include "com/sun/star/xml/sax/XDocumentHandler.hpp" + + +namespace ucbhelper +{ +class Content; +} + +namespace css = ::com::sun::star; + +namespace dp_misc +{ + +//============================================================================== +void xml_parse( + css::uno::Reference< css::xml::sax::XDocumentHandler > const & xDocHandler, + ::ucbhelper::Content & ucb_content, + css::uno::Reference< css::uno::XComponentContext > const & xContext ); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/makefile.mk b/desktop/source/deployment/makefile.mk new file mode 100755 index 000000000000..bffc8241c300 --- /dev/null +++ b/desktop/source/deployment/makefile.mk @@ -0,0 +1,109 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment +ENABLE_EXCEPTIONS = TRUE +NO_BSYMBOLIC = TRUE + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/source$/deployment$/inc$/dp_misc.mk + +CFLAGS+= $(SYSTEM_DB_CFLAGS) + +INCPRE += inc + +DLLPRE = + +SHL1TARGET = $(TARGET)$(DLLPOSTFIX).uno +SHL1VERSIONMAP = $(SOLARENV)/src/component.map + +SHL1LIBS = \ + $(SLB)$/deployment_manager.lib \ + $(SLB)$/deployment_registry.lib \ + $(SLB)$/deployment_registry_executable.lib \ + $(SLB)$/deployment_registry_component.lib \ + $(SLB)$/deployment_registry_configuration.lib \ + $(SLB)$/deployment_registry_package.lib \ + $(SLB)$/deployment_registry_script.lib \ + $(SLB)$/deployment_registry_sfwk.lib \ + $(SLB)$/deployment_registry_help.lib + +SHL1OBJS = \ + $(SLO)$/dp_log.obj \ + $(SLO)$/dp_persmap.obj \ + $(SLO)$/dp_services.obj \ + $(SLO)$/dp_xml.obj + +SHL1STDLIBS = \ + $(SALLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(UCBHELPERLIB) \ + $(COMPHELPERLIB) \ + $(TOOLSLIB) \ + $(XMLSCRIPTLIB) \ + $(SVLLIB) \ + $(UNOTOOLSLIB) \ + $(DEPLOYMENTMISCLIB) \ + $(HELPLINKERLIB) + +SHL1DEPN = +SHL1IMPLIB = i$(TARGET) +SHL1DEF = $(MISC)$/$(SHL1TARGET).def + +DEF1NAME = $(SHL1TARGET) + +SLOFILES = $(LIB1OBJFILES) + +RESLIB1NAME = $(TARGET) + +RESLIB1SRSFILES = \ + $(SRS)$/deployment_registry_configuration.srs \ + $(SRS)$/deployment_registry_component.srs \ + $(SRS)$/deployment_registry_script.srs \ + $(SRS)$/deployment_registry_sfwk.srs \ + $(SRS)$/deployment_registry_package.srs \ + $(SRS)$/deployment_registry_help.srs \ + $(SRS)$/deployment_registry.srs \ + $(SRS)$/deployment_manager.srs \ + $(SRS)$/deployment_unopkg.srs + +RESLIB1SRSFILES += $(SRS)$/deployment_misc.srs + +.INCLUDE : target.mk + + +ALLTAR : $(MISC)/deployment.component + +$(MISC)/deployment.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + deployment.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt deployment.component diff --git a/desktop/source/deployment/manager/dp_activepackages.cxx b/desktop/source/deployment/manager/dp_activepackages.cxx new file mode 100644 index 000000000000..f220aaf40daa --- /dev/null +++ b/desktop/source/deployment/manager/dp_activepackages.cxx @@ -0,0 +1,209 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "precompiled_desktop.hxx" + +#include "sal/config.h" + +#include <cstddef> +#include <utility> +#include <vector> + +#include "osl/diagnose.h" +#include "rtl/strbuf.hxx" +#include "rtl/string.hxx" +#include "rtl/textenc.h" +#include "rtl/uri.h" +#include "rtl/uri.hxx" +#include "rtl/ustring.hxx" +#include <boost/unordered_map.hpp> + +#include "dp_identifier.hxx" +#include "dp_persmap.h" + +#include "dp_activepackages.hxx" + +// Old format of database entry: +// key: UTF8(filename) +// value: UTF8(tempname ";" mediatype) +// New format of database entry: +// key: 0xFF UTF8(identifier) +// value: UTF8(tempname) 0xFF UTF8(filename) 0xFF UTF8(mediatype) + +namespace { + +static char const separator = static_cast< char >( + static_cast< unsigned char >(0xFF)); + +static char const legacyPrefix[] = "org.openoffice.legacy."; + +::rtl::OString oldKey(::rtl::OUString const & fileName) { + return ::rtl::OUStringToOString(fileName, RTL_TEXTENCODING_UTF8); +} + +::rtl::OString newKey(::rtl::OUString const & id) { + ::rtl::OStringBuffer b; + b.append(separator); + b.append(::rtl::OUStringToOString(id, RTL_TEXTENCODING_UTF8)); + return b.makeStringAndClear(); +} + +::dp_manager::ActivePackages::Data decodeOldData( + ::rtl::OUString const & fileName, ::rtl::OString const & value) +{ + ::dp_manager::ActivePackages::Data d; + sal_Int32 i = value.indexOf(';'); + OSL_ASSERT(i >= 0); + d.temporaryName = ::rtl::OUString(value.getStr(), i, RTL_TEXTENCODING_UTF8); + d.fileName = fileName; + d.mediaType = ::rtl::OUString( + value.getStr() + i + 1, value.getLength() - i - 1, + RTL_TEXTENCODING_UTF8); + return d; +} + +::dp_manager::ActivePackages::Data decodeNewData(::rtl::OString const & value) { + ::dp_manager::ActivePackages::Data d; + sal_Int32 i1 = value.indexOf(separator); + OSL_ASSERT(i1 >= 0); + d.temporaryName = ::rtl::OUString( + value.getStr(), i1, RTL_TEXTENCODING_UTF8); + sal_Int32 i2 = value.indexOf(separator, i1 + 1); + OSL_ASSERT(i2 >= 0); + d.fileName = ::rtl::OUString( + value.getStr() + i1 + 1, i2 - i1 - 1, RTL_TEXTENCODING_UTF8); + sal_Int32 i3 = value.indexOf(separator, i2 + 1); + + if (i3 < 0) + { + //Before ActivePackages::Data::version was added + d.mediaType = ::rtl::OUString( + value.getStr() + i2 + 1, value.getLength() - i2 - 1, + RTL_TEXTENCODING_UTF8); + } + else + { + sal_Int32 i4 = value.indexOf(separator, i3 + 1); + d.mediaType = ::rtl::OUString( + value.getStr() + i2 + 1, i3 - i2 -1, RTL_TEXTENCODING_UTF8); + d.version = ::rtl::OUString( + value.getStr() + i3 + 1, i4 - i3 - 1, + RTL_TEXTENCODING_UTF8); + d.failedPrerequisites = ::rtl::OUString( + value.getStr() + i4 + 1, value.getLength() - i4 - 1, + RTL_TEXTENCODING_UTF8); + } + return d; +} + +} + +namespace dp_manager { + +ActivePackages::ActivePackages() {} + +ActivePackages::ActivePackages(::rtl::OUString const & url, bool readOnly): + m_map(url, readOnly) {} + +ActivePackages::~ActivePackages() {} + +bool ActivePackages::has( + ::rtl::OUString const & id, ::rtl::OUString const & fileName) const +{ + return get(NULL, id, fileName); +} + +bool ActivePackages::get( + Data * data, ::rtl::OUString const & id, ::rtl::OUString const & fileName) + const +{ + ::rtl::OString v; + if (m_map.get(&v, newKey(id))) { + if (data != NULL) { + *data = decodeNewData(v); + } + return true; + } else if (m_map.get(&v, oldKey(fileName))) { + if (data != NULL) { + *data = decodeOldData(fileName, v); + } + return true; + } else { + return false; + } +} + +ActivePackages::Entries ActivePackages::getEntries() const { + Entries es; + ::dp_misc::t_string2string_map m(m_map.getEntries()); + for (::dp_misc::t_string2string_map::const_iterator i(m.begin()); + i != m.end(); ++i) + { + if (i->first.getLength() > 0 && i->first[0] == separator) { + es.push_back( + ::std::make_pair( + ::rtl::OUString( + i->first.getStr() + 1, i->first.getLength() - 1, + RTL_TEXTENCODING_UTF8), + decodeNewData(i->second))); + } else { + ::rtl::OUString fn( + ::rtl::OStringToOUString(i->first, RTL_TEXTENCODING_UTF8)); + es.push_back( + ::std::make_pair( + ::dp_misc::generateLegacyIdentifier(fn), + decodeOldData(fn, i->second))); + } + } + return es; +} + +void ActivePackages::put(::rtl::OUString const & id, Data const & data) { + ::rtl::OStringBuffer b; + b.append( + ::rtl::OUStringToOString(data.temporaryName, RTL_TEXTENCODING_UTF8)); + b.append(separator); + b.append(::rtl::OUStringToOString(data.fileName, RTL_TEXTENCODING_UTF8)); + b.append(separator); + b.append(::rtl::OUStringToOString(data.mediaType, RTL_TEXTENCODING_UTF8)); + b.append(separator); + b.append(::rtl::OUStringToOString(data.version, RTL_TEXTENCODING_UTF8)); + b.append(separator); + b.append(::rtl::OUStringToOString(data.failedPrerequisites, RTL_TEXTENCODING_UTF8)); + m_map.put(newKey(id), b.makeStringAndClear()); +} + +void ActivePackages::erase( + ::rtl::OUString const & id, ::rtl::OUString const & fileName) +{ + m_map.erase(newKey(id), true) || m_map.erase(oldKey(fileName), true); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_activepackages.hxx b/desktop/source/deployment/manager/dp_activepackages.hxx new file mode 100644 index 000000000000..2a4d18686346 --- /dev/null +++ b/desktop/source/deployment/manager/dp_activepackages.hxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_DEPLOYMENT_MANAGER_DP_ACTIVEPACKAGES_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_MANAGER_DP_ACTIVEPACKAGES_HXX + +#include "sal/config.h" + +#include <utility> +#include <vector> + +#include "dp_persmap.h" + +namespace rtl { class OUString; } + +namespace dp_manager { + +class ActivePackages { +public: + struct Data { + Data(): failedPrerequisites(::rtl::OUString::valueOf((sal_Int32)0)) + {} + /* name of the temporary file (shared, user extension) or the name of + the folder of the bundled extension. + It does not contain the trailing '_' of the folder. + UTF-8 encoded + */ + ::rtl::OUString temporaryName; + /* The file name (shared, user) or the folder name (bundled) + If the key is the file name, then file name is not encoded. + If the key is the idendifier then the file name is UTF-8 encoded. + */ + ::rtl::OUString fileName; + ::rtl::OUString mediaType; + ::rtl::OUString version; + /* If this string contains the value according to + com::sun::star::deployment::Prerequisites or "0". That is, if + the value is > 0 then + the call to XPackage::checkPrerequisites failed. + In this case the extension must not be registered. + */ + ::rtl::OUString failedPrerequisites; + }; + + typedef ::std::vector< ::std::pair< ::rtl::OUString, Data > > Entries; + + ActivePackages(); + + ActivePackages(::rtl::OUString const & url, bool readOnly); + + ~ActivePackages(); + + bool has(::rtl::OUString const & id, ::rtl::OUString const & fileName) + const; + + bool get( + Data * data, ::rtl::OUString const & id, + ::rtl::OUString const & fileName) const; + + Entries getEntries() const; + + void put(::rtl::OUString const & id, Data const & value); + + void erase(::rtl::OUString const & id, ::rtl::OUString const & fileName); + +private: + ActivePackages(ActivePackages &); // not defined + void operator =(ActivePackages &); // not defined + + ::dp_misc::PersistentMap m_map; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_commandenvironments.cxx b/desktop/source/deployment/manager/dp_commandenvironments.cxx new file mode 100644 index 000000000000..f8237f35499f --- /dev/null +++ b/desktop/source/deployment/manager/dp_commandenvironments.cxx @@ -0,0 +1,287 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/deployment/DependencyException.hpp" +#include "com/sun/star/deployment/PlatformException.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/task/XInteractionHandler.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "dp_commandenvironments.hxx" + +namespace deployment = com::sun::star::deployment; +namespace lang = com::sun::star::lang; +namespace task = com::sun::star::task; +namespace ucb = com::sun::star::ucb; +namespace uno = com::sun::star::uno; +namespace css = com::sun::star; + +#define OUSTR(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +namespace dp_manager { + +BaseCommandEnv::BaseCommandEnv() +{ +} + +BaseCommandEnv::BaseCommandEnv( + Reference< task::XInteractionHandler> const & handler) + : m_forwardHandler(handler) +{ +} + +BaseCommandEnv::~BaseCommandEnv() +{ +} +// XCommandEnvironment +//______________________________________________________________________________ +Reference<task::XInteractionHandler> BaseCommandEnv::getInteractionHandler() +throw (uno::RuntimeException) +{ + return this; +} + +//______________________________________________________________________________ +Reference<ucb::XProgressHandler> BaseCommandEnv::getProgressHandler() +throw (uno::RuntimeException) +{ + return this; +} + +void BaseCommandEnv::handle( + Reference< task::XInteractionRequest> const & /*xRequest*/ ) + throw (uno::RuntimeException) +{ +} + +void BaseCommandEnv::handle_(bool approve, bool abort, + Reference< task::XInteractionRequest> const & xRequest ) +{ + if (approve == false && abort == false) + { + //not handled so far -> forwarding + if (m_forwardHandler.is()) + m_forwardHandler->handle(xRequest); + else + return; //cannot handle + } + else + { + // select: + uno::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::UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + // don't query again for ongoing continuations: + approve = false; + } + } + else if (abort) { + Reference< task::XInteractionAbort > xInteractionAbort( + pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionAbort.is()) { + xInteractionAbort->select(); + // don't query again for ongoing continuations: + abort = false; + } + } + } + } + +} + +// XProgressHandler +void BaseCommandEnv::push( uno::Any const & /*Status*/ ) +throw (uno::RuntimeException) +{ +} + +void BaseCommandEnv::update( uno::Any const & /*Status */) +throw (uno::RuntimeException) +{ +} + +void BaseCommandEnv::pop() throw (uno::RuntimeException) +{ +} +//============================================================================== + +TmpRepositoryCommandEnv::TmpRepositoryCommandEnv() +{ +} + +TmpRepositoryCommandEnv::TmpRepositoryCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler): + BaseCommandEnv(handler) +{ +} +// XInteractionHandler +void TmpRepositoryCommandEnv::handle( + Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + deployment::VersionException verExc; + deployment::LicenseException licExc; + deployment::InstallException instExc; + + bool approve = false; + bool abort = false; + + if ((request >>= verExc) + || (request >>= licExc) + || (request >>= instExc)) + { + approve = true; + } + + handle_(approve, abort, xRequest); +} +//================================================================================ + +LicenseCommandEnv::LicenseCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler, + bool bSuppressLicense, + OUString const & repository): + BaseCommandEnv(handler), m_repository(repository), + m_bSuppressLicense(bSuppressLicense) +{ +} +// XInteractionHandler +void LicenseCommandEnv::handle( + Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + deployment::LicenseException licExc; + + bool approve = false; + bool abort = false; + + if (request >>= licExc) + { + if (m_bSuppressLicense + || m_repository.equals(OUSTR("bundled")) + || licExc.AcceptBy.equals(OUSTR("admin"))) + { + //always approve in bundled case, because we do not support + //showing licenses anyway. + //The "admin" already accepted the license when installing the + // shared extension + approve = true; + } + } + + handle_(approve, abort, xRequest); +} + +//================================================================================ + +NoLicenseCommandEnv::NoLicenseCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler): + BaseCommandEnv(handler) +{ +} +// XInteractionHandler +void NoLicenseCommandEnv::handle( + Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + deployment::LicenseException licExc; + + bool approve = false; + bool abort = false; + + if (request >>= licExc) + { + approve = true; + } + handle_(approve, abort, xRequest); +} + +SilentCheckPrerequisitesCommandEnv::SilentCheckPrerequisitesCommandEnv() +{ +} + +void SilentCheckPrerequisitesCommandEnv::handle( + Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + deployment::LicenseException licExc; + deployment::PlatformException platformExc; + deployment::DependencyException depExc; + bool approve = false; + bool abort = false; + + if (request >>= licExc) + { + approve = true; + handle_(approve, abort, xRequest); + } + else if ((request >>= platformExc) + || (request >>= depExc)) + { + m_Exception = request; + } + else + { + m_UnknownException = request; + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_commandenvironments.hxx b/desktop/source/deployment/manager/dp_commandenvironments.hxx new file mode 100644 index 000000000000..59349c469af0 --- /dev/null +++ b/desktop/source/deployment/manager/dp_commandenvironments.hxx @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_COMMANDENVIRONMENTS_HXX +#define INCLUDED_DP_COMMANDENVIRONMENTS_HXX + +#include "cppuhelper/compbase3.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/uno/Type.hxx" + +namespace css = ::com::sun::star; + +namespace dp_manager { + +/** + This command environment is to be used when an extension is temporarily + stored in the "tmp" repository. It prevents all kind of user interaction. + */ +class BaseCommandEnv + : public ::cppu::WeakImplHelper3< css::ucb::XCommandEnvironment, + css::task::XInteractionHandler, + css::ucb::XProgressHandler > +{ +protected: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::task::XInteractionHandler> m_forwardHandler; + + void handle_(bool approve, bool abort, + css::uno::Reference< css::task::XInteractionRequest> const & xRequest ); +public: + virtual ~BaseCommandEnv(); + BaseCommandEnv(); + BaseCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler); + + // XCommandEnvironment + virtual css::uno::Reference<css::task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (css::uno::RuntimeException); + virtual css::uno::Reference<css::ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (css::uno::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( css::uno::Any const & Status ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL update( css::uno::Any const & Status ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL pop() throw (css::uno::RuntimeException); +}; + +class TmpRepositoryCommandEnv : public BaseCommandEnv +{ +public: + TmpRepositoryCommandEnv(); + TmpRepositoryCommandEnv(css::uno::Reference< css::task::XInteractionHandler> const & handler); + +// XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + +}; + +/** this class is for use in XPackageManager::synchronize. + + It handles particular license cases. + */ +class LicenseCommandEnv : public BaseCommandEnv +{ +private: + ::rtl::OUString m_repository; + bool m_bSuppressLicense; +public: + LicenseCommandEnv() : m_bSuppressLicense(false) {}; + LicenseCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler, + bool bSuppressLicense, + ::rtl::OUString const & repository); + +// XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + +}; + +/** this class is for use in XPackageManager::checkPrerequisites + + It always prohibits a license interaction + */ +class NoLicenseCommandEnv : public BaseCommandEnv +{ + +public: + NoLicenseCommandEnv(){}; + NoLicenseCommandEnv(css::uno::Reference< css::task::XInteractionHandler> const & handler); + +// XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + +}; + +/* For use in XExtensionManager::addExtension in the call to + XPackage::checkPrerequisites + It prevents all user interactions. The license is always accepted. + It remembers if there was a platform or a dependency exception in + the member m_bException. if there was any other exception then m_bUnknownException + is set. + + */ +class SilentCheckPrerequisitesCommandEnv : public BaseCommandEnv +{ +public: + SilentCheckPrerequisitesCommandEnv(); + // XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + + // Set to true if a PlatformException or a DependencyException were handled. + css::uno::Any m_Exception; + // Set to true if an unknown exception was handled. + css::uno::Any m_UnknownException; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_extensionmanager.cxx b/desktop/source/deployment/manager/dp_extensionmanager.cxx new file mode 100644 index 000000000000..2151642df43c --- /dev/null +++ b/desktop/source/deployment/manager/dp_extensionmanager.cxx @@ -0,0 +1,1575 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <cppuhelper/implbase1.hxx> + +#include "comphelper/servicedecl.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "rtl/bootstrap.hxx" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/thePackageManagerFactory.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include "com/sun/star/deployment/XPackageManagerFactory.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/beans/Optional.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/beans/Ambiguous.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/util/XModifyBroadcaster.hpp" +#include "comphelper/sequence.hxx" +#include "xmlscript/xml_helper.hxx" +#include "osl/diagnose.h" +#include "dp_interact.h" +#include "dp_resource.h" +#include "dp_ucb.h" +#include "dp_identifier.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_extensionmanager.hxx" +#include "dp_commandenvironments.hxx" +#include "dp_properties.hxx" +#include "boost/bind.hpp" + +#include <list> +#include <boost/unordered_map.hpp> +#include <algorithm> + +namespace deploy = com::sun::star::deployment; +namespace lang = com::sun::star::lang; +namespace registry = com::sun::star::registry; +namespace task = com::sun::star::task; +namespace ucb = com::sun::star::ucb; +namespace uno = com::sun::star::uno; +namespace beans = com::sun::star::beans; +namespace util = com::sun::star::util; +namespace css = com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +namespace { + +struct CompIdentifiers +{ + bool operator() (::std::vector<Reference<deploy::XPackage> > const & a, + ::std::vector<Reference<deploy::XPackage> > const & b) + { + if (getName(a).compareTo(getName(b)) < 0) + return true; + return false; + } + + OUString getName(::std::vector<Reference<deploy::XPackage> > const & a); +}; + +OUString CompIdentifiers::getName(::std::vector<Reference<deploy::XPackage> > const & a) +{ + OSL_ASSERT(a.size() == 3); + //get the first non-null reference + Reference<deploy::XPackage> extension; + ::std::vector<Reference<deploy::XPackage> >::const_iterator it = a.begin(); + for (; it != a.end(); ++it) + { + if (it->is()) + { + extension = *it; + break; + } + } + OSL_ASSERT(extension.is()); + return extension->getDisplayName(); +} + +void writeLastModified(OUString & url, Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + //Write the lastmodified file + try { + ::rtl::Bootstrap::expandMacros(url); + ::ucbhelper::Content ucbStamp(url, xCmdEnv ); + dp_misc::erase_path( url, xCmdEnv ); + ::rtl::OString stamp("1" ); + Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(stamp.getStr()), + stamp.getLength() ) ) ); + ucbStamp.writeStream( xData, true /* replace existing */ ); + } + catch(...) + { + uno::Any exc(::cppu::getCaughtException()); + throw deploy::DeploymentException( + OUSTR("Failed to update") + url, 0, exc); + } +} + +class ExtensionRemoveGuard +{ + css::uno::Reference<css::deployment::XPackage> m_extension; + css::uno::Reference<css::deployment::XPackageManager> m_xPackageManager; + +public: + ExtensionRemoveGuard( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager): + m_extension(extension), m_xPackageManager(xPackageManager) {} + ~ExtensionRemoveGuard(); + + void reset(css::uno::Reference<css::deployment::XPackage> const & extension) { + m_extension = extension; + } +}; + +ExtensionRemoveGuard::~ExtensionRemoveGuard() +{ + try { + if (m_xPackageManager.is() && m_extension.is()) + m_xPackageManager->removePackage( + dp_misc::getIdentifier(m_extension), ::rtl::OUString(), + css::uno::Reference<css::task::XAbortChannel>(), + css::uno::Reference<css::ucb::XCommandEnvironment>()); + } catch (...) { + OSL_ASSERT(0); + } +} + +} + +namespace dp_manager { + +//------------------------------------------------------------------------------ + +//ToDo: bundled extension +ExtensionManager::ExtensionManager( Reference< uno::XComponentContext > const& xContext) : + ::cppu::WeakComponentImplHelper1< css::deployment::XExtensionManager >(getMutex()), + m_xContext( xContext ) +{ + m_xPackageManagerFactory = deploy::thePackageManagerFactory::get(m_xContext); + OSL_ASSERT(m_xPackageManagerFactory.is()); + + m_repositoryNames.push_back(OUSTR("user")); + m_repositoryNames.push_back(OUSTR("shared")); + m_repositoryNames.push_back(OUSTR("bundled")); +} + +//------------------------------------------------------------------------------ + +ExtensionManager::~ExtensionManager() +{ +} + +Reference<deploy::XPackageManager> ExtensionManager::getUserRepository() +{ + return m_xPackageManagerFactory->getPackageManager(OUSTR("user")); +} +Reference<deploy::XPackageManager> ExtensionManager::getSharedRepository() +{ + return m_xPackageManagerFactory->getPackageManager(OUSTR("shared")); +} +Reference<deploy::XPackageManager> ExtensionManager::getBundledRepository() +{ + return m_xPackageManagerFactory->getPackageManager(OUSTR("bundled")); +} +Reference<deploy::XPackageManager> ExtensionManager::getTmpRepository() +{ + return m_xPackageManagerFactory->getPackageManager(OUSTR("tmp")); +} + +Reference<task::XAbortChannel> ExtensionManager::createAbortChannel() + throw (uno::RuntimeException) +{ + return new dp_misc::AbortChannel; +} + +css::uno::Reference<css::deployment::XPackageManager> +ExtensionManager::getPackageManager(::rtl::OUString const & repository) + throw (css::lang::IllegalArgumentException) +{ + Reference<deploy::XPackageManager> xPackageManager; + if (repository.equals(OUSTR("user"))) + xPackageManager = getUserRepository(); + else if (repository.equals(OUSTR("shared"))) + xPackageManager = getSharedRepository(); + else if (repository.equals(OUSTR("bundled"))) + xPackageManager = getBundledRepository(); + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + return xPackageManager; +} + +/* + Enters the XPackage objects into a map. They must be all from the + same repository. The value type of the map is a vector, where each vector + represents an extension with a particular identifier. The first member + represents the user extension, the second the shared extension and the + third the bundled extension. + */ +void ExtensionManager::addExtensionsToMap( + id2extensions & mapExt, + uno::Sequence<Reference<deploy::XPackage> > const & seqExt, + OUString const & repository) +{ + //Determine the index in the vector where these extensions are to be + //added. + ::std::list<OUString>::const_iterator citNames = + m_repositoryNames.begin(); + int index = 0; + for (;citNames != m_repositoryNames.end(); ++citNames, ++index) + { + if (citNames->equals(repository)) + break; + } + + for (int i = 0; i < seqExt.getLength(); ++i) + { + Reference<deploy::XPackage> const & xExtension = seqExt[i]; + OUString id = dp_misc::getIdentifier(xExtension); + id2extensions::iterator ivec = mapExt.find(id); + if (ivec == mapExt.end()) + { + ::std::vector<Reference<deploy::XPackage> > vec(3); + vec[index] = xExtension; + mapExt[id] = vec; + } + else + { + ivec->second[index] = xExtension; + } + } +} + +/* + returns a list containing extensions with the same identifier from + all repositories (user, shared, bundled). If one repository does not + have this extension, then the list contains an empty Reference. The list + is ordered according to the priority of the repostories: + 1. user + 2. shared + 3. bundled + + The number of elements is always three, unless the number of repository + changes. + */ +::std::list<Reference<deploy::XPackage> > + ExtensionManager::getExtensionsWithSameId( + OUString const & identifier, OUString const & fileName, + Reference< ucb::XCommandEnvironment> const & /*xCmdEnv*/) + +{ + ::std::list<Reference<deploy::XPackage> > extensionList; + Reference<deploy::XPackageManager> lRepos[] = { + getUserRepository(), getSharedRepository(), getBundledRepository() }; + for (int i(0); i != SAL_N_ELEMENTS(lRepos); ++i) + { + Reference<deploy::XPackage> xPackage; + try + { + xPackage = lRepos[i]->getDeployedPackage( + identifier, fileName, Reference<ucb::XCommandEnvironment>()); + } + catch(lang::IllegalArgumentException &) + { + // thrown if the extension does not exist in this repository + } + extensionList.push_back(xPackage); + } + OSL_ASSERT(extensionList.size() == 3); + return extensionList; +} + +uno::Sequence<Reference<deploy::XPackage> > +ExtensionManager::getExtensionsWithSameIdentifier( + OUString const & identifier, + OUString const & fileName, + Reference< ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + deploy::DeploymentException, + ucb::CommandFailedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + ::std::list<Reference<deploy::XPackage> > listExtensions = + getExtensionsWithSameId( + identifier, fileName, xCmdEnv); + sal_Bool bHasExtension = false; + + //throw an IllegalArgumentException if there is no extension at all. + typedef ::std::list<Reference<deploy::XPackage> >::const_iterator CIT; + for (CIT i = listExtensions.begin(); i != listExtensions.end(); ++i) + bHasExtension |= i->is(); + if (!bHasExtension) + throw lang::IllegalArgumentException( + OUSTR("Could not find extension: ") + identifier + OUSTR(", ") + fileName, + static_cast<cppu::OWeakObject*>(this), -1); + + return comphelper::containerToSequence< + Reference<deploy::XPackage>, + ::std::list<Reference<deploy::XPackage> > + > (listExtensions); + } + catch (deploy::DeploymentException & ) + { + throw; + } + catch ( ucb::CommandFailedException & ) + { + throw; + } + catch (lang::IllegalArgumentException &) + { + throw; + } + catch (...) + { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during getExtensionsWithSameIdentifier"), + static_cast<OWeakObject*>(this), exc); + } +} + +bool ExtensionManager::isUserDisabled( + OUString const & identifier, OUString const & fileName) +{ + ::std::list<Reference<deploy::XPackage> > listExtensions; + + try { + listExtensions = getExtensionsWithSameId(identifier, fileName); + } catch (lang::IllegalArgumentException & ) { + } + OSL_ASSERT(listExtensions.size() == 3); + + return isUserDisabled( ::comphelper::containerToSequence< + Reference<deploy::XPackage>, + ::std::list<Reference<deploy::XPackage> > + > (listExtensions)); +} + +bool ExtensionManager::isUserDisabled( + uno::Sequence<Reference<deploy::XPackage> > const & seqExtSameId) +{ + OSL_ASSERT(seqExtSameId.getLength() == 3); + Reference<deploy::XPackage> const & userExtension = seqExtSameId[0]; + if (userExtension.is()) + { + beans::Optional<beans::Ambiguous<sal_Bool> > reg = + userExtension->isRegistered(Reference<task::XAbortChannel>(), + Reference<ucb::XCommandEnvironment>()); + //If the value is ambiguous is than we assume that the extension + //is enabled, but something went wrong during enabling. We do not + //automatically disable user extensions. + if (reg.IsPresent && + ! reg.Value.IsAmbiguous && ! reg.Value.Value) + return true; + } + return false; +} + +/* + This method determines the active extension (XPackage.registerPackage) with a + particular identifier. + + The parameter bUserDisabled determines if the user extension is disabled. + + When the user repository contains an extension with the given identifier and + it is not disabled by the user, then it is always registered. Otherwise an + extension is only registered when there is no registered extension in one of + the repositories with a higher priority. That is, if the extension is from + the shared repository and an active extension with the same identifer is in + the user repository, then the extension is not registered. Similarly a + bundled extension is not registered if there is an active extension with the + same identifier in the shared or user repository. +*/ +void ExtensionManager::activateExtension( + OUString const & identifier, OUString const & fileName, + bool bUserDisabled, + bool bStartup, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + ::std::list<Reference<deploy::XPackage> > listExtensions; + try { + listExtensions = getExtensionsWithSameId(identifier, fileName); + } catch (lang::IllegalArgumentException &) { + } + OSL_ASSERT(listExtensions.size() == 3); + + activateExtension( + ::comphelper::containerToSequence< + Reference<deploy::XPackage>, + ::std::list<Reference<deploy::XPackage> > + > (listExtensions), + bUserDisabled, bStartup, xAbortChannel, xCmdEnv); + + fireModified(); +} + +void ExtensionManager::activateExtension( + uno::Sequence<Reference<deploy::XPackage> > const & seqExt, + bool bUserDisabled, + bool bStartup, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + bool bActive = false; + sal_Int32 len = seqExt.getLength(); + for (sal_Int32 i = 0; i < len; i++) + { + Reference<deploy::XPackage> const & aExt = seqExt[i]; + if (aExt.is()) + { + //get the registration value of the current iteration + beans::Optional<beans::Ambiguous<sal_Bool> > optReg = + aExt->isRegistered(xAbortChannel, xCmdEnv); + //If nothing can be registered then break + if (!optReg.IsPresent) + break; + + //Check if this is a disabled user extension, + if (i == 0 && bUserDisabled) + { + aExt->revokePackage(xAbortChannel, xCmdEnv); + continue; + } + + //If we have already determined an active extension then we must + //make sure to unregister all extensions with the same id in + //repositories with a lower priority + if (bActive) + { + aExt->revokePackage(xAbortChannel, xCmdEnv); + } + else + { + //This is the first extension in the ordered list, which becomes + //the active extension + bActive = true; + //Register if not already done. + //reregister if the value is ambiguous, which indicates that + //something went wrong during last registration. + aExt->registerPackage(bStartup, xAbortChannel, xCmdEnv); + } + } + } +} + +Reference<deploy::XPackage> ExtensionManager::backupExtension( + OUString const & identifier, OUString const & fileName, + Reference<deploy::XPackageManager> const & xPackageManager, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + Reference<deploy::XPackage> xBackup; + Reference<ucb::XCommandEnvironment> tmpCmdEnv( + new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); + Reference<deploy::XPackage> xOldExtension; + xOldExtension = xPackageManager->getDeployedPackage( + identifier, fileName, tmpCmdEnv); + + if (xOldExtension.is()) + { + xBackup = getTmpRepository()->addPackage( + xOldExtension->getURL(), uno::Sequence<beans::NamedValue>(), + OUString(), Reference<task::XAbortChannel>(), tmpCmdEnv); + + OSL_ENSURE(xBackup.is(), "Failed to backup extension"); + } + return xBackup; +} + +//The supported package types are actually determined by the registry. However +//creating a registry +//(desktop/source/deployment/registry/dp_registry.cxx:PackageRegistryImpl) will +//create all the backends, so that the registry can obtain from them the package +//types. Creating the registry will also set up the registry folder containing +//all the subfolders for the respective backends. +//Because all repositories support the same backends, we can just delegate this +//call to one of the repositories. +uno::Sequence< Reference<deploy::XPackageTypeInfo> > +ExtensionManager::getSupportedPackageTypes() + throw (uno::RuntimeException) +{ + return getUserRepository()->getSupportedPackageTypes(); +} +//Do some necessary checks and user interaction. This function does not +//aquire the extension manager mutex and that mutex must not be aquired +//when this function is called. doChecksForAddExtension does synchronous +//user interactions which may require aquiring the solar mutex. +//Returns true if the extension can be installed. +bool ExtensionManager::doChecksForAddExtension( + Reference<deploy::XPackageManager> const & xPackageMgr, + uno::Sequence<beans::NamedValue> const & properties, + css::uno::Reference<css::deployment::XPackage> const & xTmpExtension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + Reference<deploy::XPackage> & out_existingExtension ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + Reference<deploy::XPackage> xOldExtension; + const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension); + const OUString sFileName = xTmpExtension->getName(); + const OUString sDisplayName = xTmpExtension->getDisplayName(); + const OUString sVersion = xTmpExtension->getVersion(); + + try + { + xOldExtension = xPackageMgr->getDeployedPackage( + sIdentifier, sFileName, xCmdEnv); + out_existingExtension = xOldExtension; + } + catch (lang::IllegalArgumentException &) + { + } + bool bCanInstall = false; + + //This part is not guarded against other threads removing, adding, disabling ... + //etc. the same extension. + //checkInstall is safe because it notifies the user if the extension is not yet + //installed in the same repository. Because addExtension has its own guard + //(m_addMutex), another thread cannot add the extension in the meantime. + //checkUpdate is called if the same extension exists in the same + //repository. The user is asked if they want to replace it. Another + //thread + //could already remove the extension. So asking the user was not + //necessary. No harm is done. The other thread may also ask the user + //if he wants to remove the extension. This depends on the + //XCommandEnvironment which it passes to removeExtension. + if (xOldExtension.is()) + { + //throws a CommandFailedException if the user cancels + //the action. + checkUpdate(sVersion, sDisplayName,xOldExtension, xCmdEnv); + } + else + { + //throws a CommandFailedException if the user cancels + //the action. + checkInstall(sDisplayName, xCmdEnv); + } + //Prevent showing the license if requested. + Reference<ucb::XCommandEnvironment> _xCmdEnv(xCmdEnv); + ExtensionProperties props(OUString(), properties, Reference<ucb::XCommandEnvironment>()); + + dp_misc::DescriptionInfoset info(dp_misc::getDescriptionInfoset(xTmpExtension->getURL())); + const ::boost::optional<dp_misc::SimpleLicenseAttributes> licenseAttributes = + info.getSimpleLicenseAttributes(); + + if (licenseAttributes && licenseAttributes->suppressIfRequired + && props.isSuppressedLicense()) + _xCmdEnv = Reference<ucb::XCommandEnvironment>( + new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler())); + + bCanInstall = xTmpExtension->checkPrerequisites( + xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0 ? true : false; + + return bCanInstall; + } + catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (uno::Exception &) { + uno::Any excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception in doChecksForAddExtension"), + static_cast<OWeakObject*>(this), excOccurred); + throw exc; + } catch (...) { + throw uno::RuntimeException( + OUSTR("Extension Manager: unexpected exception in doChecksForAddExtension"), + static_cast<OWeakObject*>(this)); + } +} + +// Only add to shared and user repository +Reference<deploy::XPackage> ExtensionManager::addExtension( + OUString const & url, uno::Sequence<beans::NamedValue> const & properties, + OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + Reference<deploy::XPackage> xNewExtension; + //Determine the repository to use + Reference<deploy::XPackageManager> xPackageManager; + if (repository.equals(OUSTR("user"))) + xPackageManager = getUserRepository(); + else if (repository.equals(OUSTR("shared"))) + xPackageManager = getSharedRepository(); + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + //We must make sure that the xTmpExtension is not create twice, because this + //would remove the first one. + ::osl::MutexGuard addGuard(m_addMutex); + + Reference<deploy::XPackage> xTmpExtension = + getTempExtension(url, xAbortChannel, xCmdEnv); + //Make sure the extension is removed from the tmp repository in case + //of an exception + ExtensionRemoveGuard tmpExtensionRemoveGuard(xTmpExtension, getTmpRepository()); + const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension); + const OUString sFileName = xTmpExtension->getName(); + Reference<deploy::XPackage> xOldExtension; + Reference<deploy::XPackage> xExtensionBackup; + + uno::Any excOccurred2; + bool bUserDisabled = false; + bool bCanInstall = doChecksForAddExtension( + xPackageManager, + properties, + xTmpExtension, + xAbortChannel, + xCmdEnv, + xOldExtension ); + + { + // In this garded section (getMutex) we must not use the argument xCmdEnv + // because it may bring up dialogs (XInteractionHandler::handle) this + //may potententially deadlock. See issue + //http://qa.openoffice.org/issues/show_bug.cgi?id=114933 + //By not providing xCmdEnv the underlying APIs will throw an exception if + //the XInteractionRequest cannot be handled + ::osl::MutexGuard guard(getMutex()); + + if (bCanInstall) + { + try + { + bUserDisabled = isUserDisabled(sIdentifier, sFileName); + if (xOldExtension.is()) + { + try + { + xOldExtension->revokePackage( + xAbortChannel, Reference<ucb::XCommandEnvironment>()); + //save the old user extension in case the user aborts + //store the extension in the tmp repository, this will overwrite + //xTmpPackage (same identifier). Do not let the user abort or + //interact + //importing the old extension in the tmp repository will remove + //the xTmpExtension + //no command environment supplied, only this class shall interact + //with the user! + xExtensionBackup = getTmpRepository()->importExtension( + xOldExtension, Reference<task::XAbortChannel>(), + Reference<ucb::XCommandEnvironment>()); + tmpExtensionRemoveGuard.reset(xExtensionBackup); + //xTmpExtension will later be used to check the dependencies + //again. However, only xExtensionBackup will be later removed + //from the tmp repository + xTmpExtension = xExtensionBackup; + OSL_ASSERT(xTmpExtension.is()); + } + catch (lang::DisposedException &) + { + //Another thread might have removed the extension meanwhile + } + } + //check again dependencies but prevent user interaction, + //We can disregard the license, because the user must have already + //accepted it, when we called checkPrerequisites the first time + SilentCheckPrerequisitesCommandEnv * pSilentCommandEnv = + new SilentCheckPrerequisitesCommandEnv(); + Reference<ucb::XCommandEnvironment> silentCommandEnv(pSilentCommandEnv); + + sal_Int32 failedPrereq = xTmpExtension->checkPrerequisites( + xAbortChannel, silentCommandEnv, true); + if (failedPrereq == 0) + { + xNewExtension = xPackageManager->addPackage( + url, properties, OUString(), xAbortChannel, + Reference<ucb::XCommandEnvironment>()); + //If we add a user extension and there is already one which was + //disabled by a user, then the newly installed one is enabled. If we + //add to another repository then the user extension remains + //disabled. + bool bUserDisabled2 = bUserDisabled; + if (repository.equals(OUSTR("user"))) + bUserDisabled2 = false; + + // pass the two values via variables to workaround gcc-4.3.4 specific bug (bnc#655912) + OUString sNewExtensionIdentifier = dp_misc::getIdentifier(xNewExtension); + OUString sNewExtensionFileName = xNewExtension->getName(); + + activateExtension( + sNewExtensionIdentifier, sNewExtensionFileName, + bUserDisabled2, false, xAbortChannel, + Reference<ucb::XCommandEnvironment>()); + } + else + { + if (pSilentCommandEnv->m_Exception.hasValue()) + ::cppu::throwException(pSilentCommandEnv->m_Exception); + else if ( pSilentCommandEnv->m_UnknownException.hasValue()) + ::cppu::throwException(pSilentCommandEnv->m_UnknownException); + else + throw deploy::DeploymentException ( + OUSTR("Extension Manager: exception during addExtension, ckeckPrerequisites failed"), + static_cast<OWeakObject*>(this), uno::Any()); + } + } + catch (deploy::DeploymentException& ) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (...) { + excOccurred2 = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during addExtension, url: ") + + url, static_cast<OWeakObject*>(this), excOccurred2); + excOccurred2 <<= exc; + } + } + + if (excOccurred2.hasValue()) + { + //It does not matter what exception is thrown. We try to + //recover the original status. + //If the user aborted installation then a ucb::CommandAbortedException + //is thrown. + //Use a private AbortChannel so the user cannot interrupt. + try + { + if (xExtensionBackup.is()) + { + Reference<deploy::XPackage> xRestored = + xPackageManager->importExtension( + xExtensionBackup, Reference<task::XAbortChannel>(), + Reference<ucb::XCommandEnvironment>()); + } + activateExtension( + sIdentifier, sFileName, bUserDisabled, false, + Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>()); + } + catch (...) + { + } + ::cppu::throwException(excOccurred2); + } + } // leaving the garded section (getMutex()) + + try + { + fireModified(); + + }catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (uno::Exception &) { + uno::Any excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception in doChecksForAddExtension"), + static_cast<OWeakObject*>(this), excOccurred); + throw exc; + } catch (...) { + throw uno::RuntimeException( + OUSTR("Extension Manager: unexpected exception in doChecksForAddExtension"), + static_cast<OWeakObject*>(this)); + } + + return xNewExtension; +} + +void ExtensionManager::removeExtension( + OUString const & identifier, OUString const & fileName, + OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + uno::Any excOccurred1; + Reference<deploy::XPackage> xExtensionBackup; + Reference<deploy::XPackageManager> xPackageManager; + bool bUserDisabled = false; + ::osl::MutexGuard guard(getMutex()); + try + { +//Determine the repository to use + if (repository.equals(OUSTR("user"))) + xPackageManager = getUserRepository(); + else if (repository.equals(OUSTR("shared"))) + xPackageManager = getSharedRepository(); + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + bUserDisabled = isUserDisabled(identifier, fileName); + //Backup the extension, in case the user cancels the action + xExtensionBackup = backupExtension( + identifier, fileName, xPackageManager, xCmdEnv); + + //revoke the extension if it is active + Reference<deploy::XPackage> xOldExtension = + xPackageManager->getDeployedPackage( + identifier, fileName, xCmdEnv); + xOldExtension->revokePackage(xAbortChannel, xCmdEnv); + + xPackageManager->removePackage( + identifier, fileName, xAbortChannel, xCmdEnv); + activateExtension(identifier, fileName, bUserDisabled, false, + xAbortChannel, xCmdEnv); + fireModified(); + } + catch (deploy::DeploymentException& ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (...) { + excOccurred1 = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during removeEtension"), + static_cast<OWeakObject*>(this), excOccurred1); + excOccurred1 <<= exc; + } + + if (excOccurred1.hasValue()) + { + //User aborted installation, restore the previous situation. + //Use a private AbortChannel so the user cannot interrupt. + try + { + Reference<ucb::XCommandEnvironment> tmpCmdEnv( + new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); + if (xExtensionBackup.is()) + { + Reference<deploy::XPackage> xRestored = + xPackageManager->importExtension( + xExtensionBackup, Reference<task::XAbortChannel>(), + tmpCmdEnv); + activateExtension( + identifier, fileName, bUserDisabled, false, + Reference<task::XAbortChannel>(), + tmpCmdEnv); + + getTmpRepository()->removePackage( + dp_misc::getIdentifier(xExtensionBackup), + xExtensionBackup->getName(), xAbortChannel, xCmdEnv); + fireModified(); + } + } + catch (...) + { + } + ::cppu::throwException(excOccurred1); + } + + if (xExtensionBackup.is()) + getTmpRepository()->removePackage( + dp_misc::getIdentifier(xExtensionBackup), + xExtensionBackup->getName(), xAbortChannel, xCmdEnv); +} + +// Only enable extensions from shared and user repository +void ExtensionManager::enableExtension( + Reference<deploy::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + ::osl::MutexGuard guard(getMutex()); + bool bUserDisabled = false; + uno::Any excOccurred; + try + { + if (!extension.is()) + return; + OUString repository = extension->getRepositoryName(); + if (!repository.equals(OUSTR("user"))) + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + bUserDisabled = isUserDisabled(dp_misc::getIdentifier(extension), + extension->getName()); + + activateExtension(dp_misc::getIdentifier(extension), + extension->getName(), false, false, + xAbortChannel, xCmdEnv); + } + catch (deploy::DeploymentException& ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (...) { + excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), excOccurred); + excOccurred <<= exc; + } + + if (excOccurred.hasValue()) + { + try + { + activateExtension(dp_misc::getIdentifier(extension), + extension->getName(), bUserDisabled, false, + xAbortChannel, xCmdEnv); + } + catch (...) + { + } + ::cppu::throwException(excOccurred); + } +} + +/** + */ +sal_Int32 ExtensionManager::checkPrerequisitesAndEnable( + Reference<deploy::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + if (!extension.is()) + return 0; + ::osl::MutexGuard guard(getMutex()); + sal_Int32 ret = 0; + Reference<deploy::XPackageManager> mgr = + getPackageManager(extension->getRepositoryName()); + ret = mgr->checkPrerequisites(extension, xAbortChannel, xCmdEnv); + if (ret) + { + //There are some unfulfilled prerequisites, try to revoke + extension->revokePackage(xAbortChannel, xCmdEnv); + } + const OUString id(dp_misc::getIdentifier(extension)); + activateExtension(id, extension->getName(), + isUserDisabled(id, extension->getName()), false, + xAbortChannel, xCmdEnv); + return ret; + } + catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during disableExtension"), + static_cast<OWeakObject*>(this), excOccurred); + throw exc; + } +} + +void ExtensionManager::disableExtension( + Reference<deploy::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + ::osl::MutexGuard guard(getMutex()); + uno::Any excOccurred; + bool bUserDisabled = false; + try + { + if (!extension.is()) + return; + const OUString repository( extension->getRepositoryName()); + if (!repository.equals(OUSTR("user"))) + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + const OUString id(dp_misc::getIdentifier(extension)); + bUserDisabled = isUserDisabled(id, extension->getName()); + + activateExtension(id, extension->getName(), true, false, + xAbortChannel, xCmdEnv); + } + catch (deploy::DeploymentException& ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (...) { + excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during disableExtension"), + static_cast<OWeakObject*>(this), excOccurred); + excOccurred <<= exc; + } + + if (excOccurred.hasValue()) + { + try + { + activateExtension(dp_misc::getIdentifier(extension), + extension->getName(), bUserDisabled, false, + xAbortChannel, xCmdEnv); + } + catch (...) + { + } + ::cppu::throwException(excOccurred); + } +} + +uno::Sequence< Reference<deploy::XPackage> > + ExtensionManager::getDeployedExtensions( + OUString const & repository, + Reference<task::XAbortChannel> const &xAbort, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + return getPackageManager(repository)->getDeployedPackages( + xAbort, xCmdEnv); +} + +Reference<deploy::XPackage> + ExtensionManager::getDeployedExtension( + OUString const & repository, + OUString const & identifier, + OUString const & filename, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + return getPackageManager(repository)->getDeployedPackage( + identifier, filename, xCmdEnv); +} + +uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > > + ExtensionManager::getAllExtensions( + Reference<task::XAbortChannel> const & xAbort, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + id2extensions mapExt; + + uno::Sequence<Reference<deploy::XPackage> > userExt = + getUserRepository()->getDeployedPackages(xAbort, xCmdEnv); + addExtensionsToMap(mapExt, userExt, OUSTR("user")); + uno::Sequence<Reference<deploy::XPackage> > sharedExt = + getSharedRepository()->getDeployedPackages(xAbort, xCmdEnv); + addExtensionsToMap(mapExt, sharedExt, OUSTR("shared")); + uno::Sequence<Reference<deploy::XPackage> > bundledExt = + getBundledRepository()->getDeployedPackages(xAbort, xCmdEnv); + addExtensionsToMap(mapExt, bundledExt, OUSTR("bundled")); + + //copy the values of the map to a vector for sorting + ::std::vector< ::std::vector<Reference<deploy::XPackage> > > + vecExtensions; + id2extensions::const_iterator mapIt = mapExt.begin(); + for (;mapIt != mapExt.end(); ++mapIt) + vecExtensions.push_back(mapIt->second); + + //sort the element according to the identifier + ::std::sort(vecExtensions.begin(), vecExtensions.end(), CompIdentifiers()); + + ::std::vector< ::std::vector<Reference<deploy::XPackage> > >::const_iterator + citVecVec = vecExtensions.begin(); + sal_Int32 j = 0; + uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > > seqSeq(vecExtensions.size()); + for (;citVecVec != vecExtensions.end(); citVecVec++, j++) + { + seqSeq[j] = comphelper::containerToSequence(*citVecVec); + } + return seqSeq; + + } catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), exc); + } +} + +//only to be called from unopkg!!! +void ExtensionManager::reinstallDeployedExtensions( + OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, ucb::CommandAbortedException, + lang::IllegalArgumentException, uno::RuntimeException) +{ + try + { + Reference<deploy::XPackageManager> + xPackageManager = getPackageManager(repository); + + ::osl::MutexGuard guard(getMutex()); + xPackageManager->reinstallDeployedPackages(xAbortChannel, xCmdEnv); + //We must sync here, otherwise we will get exceptions when extensions + //are removed. + dp_misc::syncRepositories(xCmdEnv); + const uno::Sequence< Reference<deploy::XPackage> > extensions( + xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv)); + + for ( sal_Int32 pos = 0; pos < extensions.getLength(); ++pos ) + { + try + { + const OUString id = dp_misc::getIdentifier(extensions[ pos ]); + const OUString fileName = extensions[ pos ]->getName(); + OSL_ASSERT(id.getLength()); + activateExtension(id, fileName, false, true, xAbortChannel, xCmdEnv ); + } + catch (lang::DisposedException &) + { + } + } + } catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), exc); + } +} + +/** Works on the bundled repository. That is using the variables + BUNDLED_EXTENSIONS and BUNDLED_EXTENSIONS_USER. + */ +void ExtensionManager::synchronizeBundledPrereg( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + uno::RuntimeException) +{ + try + { + String sSynchronizingBundled(StrSyncRepository::get()); + sSynchronizingBundled.SearchAndReplaceAllAscii( "%NAME", OUSTR("bundled")); + dp_misc::ProgressLevel progressBundled(xCmdEnv, sSynchronizingBundled); + + Reference<deploy::XPackageManagerFactory> xPackageManagerFactory( + deploy::thePackageManagerFactory::get(m_xContext)); + + Reference<deploy::XPackageManager> xMgr = + xPackageManagerFactory->getPackageManager(OUSTR("bundled_prereg")); + xMgr->synchronize(xAbortChannel, xCmdEnv); + progressBundled.update(OUSTR("\n\n")); + + uno::Sequence<Reference<deploy::XPackage> > extensions = xMgr->getDeployedPackages( + xAbortChannel, xCmdEnv); + try + { + for (sal_Int32 i = 0; i < extensions.getLength(); i++) + { + extensions[i]->registerPackage(true, xAbortChannel, xCmdEnv); + } + } + catch (...) + { + OSL_ASSERT(0); + } + OUString lastSyncBundled(RTL_CONSTASCII_USTRINGPARAM( + "$BUNDLED_EXTENSIONS_PREREG/lastsynchronized")); + writeLastModified(lastSyncBundled, xCmdEnv); + + } catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception in synchronize"), + static_cast<OWeakObject*>(this), exc); + } +} + +sal_Bool ExtensionManager::synchronize( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + sal_Bool bModified = sal_False; + + ::osl::MutexGuard guard(getMutex()); + String sSynchronizingShared(StrSyncRepository::get()); + sSynchronizingShared.SearchAndReplaceAllAscii( "%NAME", OUSTR("shared")); + dp_misc::ProgressLevel progressShared(xCmdEnv, sSynchronizingShared); + bModified = getSharedRepository()->synchronize(xAbortChannel, xCmdEnv); + progressShared.update(OUSTR("\n\n")); + + String sSynchronizingBundled(StrSyncRepository::get()); + sSynchronizingBundled.SearchAndReplaceAllAscii( "%NAME", OUSTR("bundled")); + dp_misc::ProgressLevel progressBundled(xCmdEnv, sSynchronizingBundled); + bModified |= getBundledRepository()->synchronize(xAbortChannel, xCmdEnv); + progressBundled.update(OUSTR("\n\n")); + + //Always determine the active extension. This is necessary for the + //first-start optimization. The setup creates the registration data for the + //bundled extensions (brand_layer/share/prereg/bundled), which is copied to the user + //installation (user_installation/extension/bundled) when a user starts OOo + //for the first time after running setup. All bundled extensions are registered + //at that moment. However, extensions with the same identifier can be in the + //shared or user repository, in which case the respective bundled extensions must + //be revoked. + try + { + const uno::Sequence<uno::Sequence<Reference<deploy::XPackage> > > + seqSeqExt = getAllExtensions(xAbortChannel, xCmdEnv); + for (sal_Int32 i = 0; i < seqSeqExt.getLength(); i++) + { + uno::Sequence<Reference<deploy::XPackage> > const & seqExt = + seqSeqExt[i]; + activateExtension(seqExt, isUserDisabled(seqExt), true, + xAbortChannel, xCmdEnv); + } + } + catch (...) + { + //We catch the exception, so we can write the lastmodified file + //so we will no repeat this everytime OOo starts. + OSL_FAIL("Extensions Manager: synchronize"); + } + OUString lastSyncBundled(RTL_CONSTASCII_USTRINGPARAM( + "$BUNDLED_EXTENSIONS_USER/lastsynchronized")); + writeLastModified(lastSyncBundled, xCmdEnv); + OUString lastSyncShared(RTL_CONSTASCII_USTRINGPARAM( + "$SHARED_EXTENSIONS_USER/lastsynchronized")); + writeLastModified(lastSyncShared, xCmdEnv); + return bModified; + } catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception in synchronize"), + static_cast<OWeakObject*>(this), exc); + } +} + +// Notify the user when a new extension is to be installed. This is only the +// case when one uses the system integration to install an extension (double +// clicking on .oxt file etc.)). The function must only be called if there is no +// extension with the same identifier already deployed. Then the checkUpdate +// function will inform the user that the extension is about to be installed In +// case the user cancels the installation a CommandFailed exception is +// thrown. +void ExtensionManager::checkInstall( + OUString const & displayName, + Reference<ucb::XCommandEnvironment> const & cmdEnv) +{ + uno::Any request( + deploy::InstallException( + OUSTR("Extension ") + displayName + + OUSTR(" is about to be installed."), + static_cast<OWeakObject *>(this), displayName)); + bool approve = false, abort = false; + if (! dp_misc::interactContinuation( + request, task::XInteractionApprove::static_type(), + cmdEnv, &approve, &abort )) + { + OSL_ASSERT( !approve && !abort ); + throw deploy::DeploymentException( + dp_misc::getResourceString(RID_STR_ERROR_WHILE_ADDING) + displayName, + static_cast<OWeakObject *>(this), request ); + } + if (abort || !approve) + throw ucb::CommandFailedException( + dp_misc::getResourceString(RID_STR_ERROR_WHILE_ADDING) + displayName, + static_cast<OWeakObject *>(this), request ); +} + +/* The function will make the user interaction in case there is an extension +installed with the same id. This function may only be called if there is already +an extension. +*/ +void ExtensionManager::checkUpdate( + OUString const & newVersion, + OUString const & newDisplayName, + Reference<deploy::XPackage> const & oldExtension, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + // package already deployed, interact --force: + uno::Any request( + (deploy::VersionException( + dp_misc::getResourceString( + RID_STR_PACKAGE_ALREADY_ADDED ) + newDisplayName, + static_cast<OWeakObject *>(this), newVersion, newDisplayName, + oldExtension ) ) ); + bool replace = false, abort = false; + if (! dp_misc::interactContinuation( + request, task::XInteractionApprove::static_type(), + xCmdEnv, &replace, &abort )) { + OSL_ASSERT( !replace && !abort ); + throw deploy::DeploymentException( + dp_misc::getResourceString( + RID_STR_ERROR_WHILE_ADDING) + newDisplayName, + static_cast<OWeakObject *>(this), request ); + } + if (abort || !replace) + throw ucb::CommandFailedException( + dp_misc::getResourceString( + RID_STR_PACKAGE_ALREADY_ADDED) + newDisplayName, + static_cast<OWeakObject *>(this), request ); +} + +Reference<deploy::XPackage> ExtensionManager::getTempExtension( + OUString const & url, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & /*xCmdEnv*/) + +{ + Reference<ucb::XCommandEnvironment> tmpCmdEnvA(new TmpRepositoryCommandEnv()); + Reference<deploy::XPackage> xTmpPackage = getTmpRepository()->addPackage( + url, uno::Sequence<beans::NamedValue>(),OUString(), xAbortChannel, tmpCmdEnvA); + if (!xTmpPackage.is()) + { + throw deploy::DeploymentException( + OUSTR("Extension Manager: Failed to create temporary XPackage for url: ") + url, + static_cast<OWeakObject*>(this), uno::Any()); + + } + return xTmpPackage; +} + +uno::Sequence<Reference<deploy::XPackage> > SAL_CALL +ExtensionManager::getExtensionsWithUnacceptedLicenses( + OUString const & repository, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) + throw (deploy::DeploymentException, + uno::RuntimeException) +{ + Reference<deploy::XPackageManager> + xPackageManager = getPackageManager(repository); + ::osl::MutexGuard guard(getMutex()); + return xPackageManager->getExtensionsWithUnacceptedLicenses(xCmdEnv); +} + +sal_Bool ExtensionManager::isReadOnlyRepository(::rtl::OUString const & repository) + throw (uno::RuntimeException) +{ + return getPackageManager(repository)->isReadOnly(); +} +//------------------------------------------------------------------------------ + +namespace sdecl = comphelper::service_decl; +sdecl::class_<ExtensionManager> servicePIP; +extern sdecl::ServiceDecl const serviceDecl( + servicePIP, + // a private one: + "com.sun.star.comp.deployment.ExtensionManager", + "com.sun.star.comp.deployment.ExtensionManager"); + +//------------------------------------------------------------------------------ +bool singleton_entries( + uno::Reference< registry::XRegistryKey > const & xRegistryKey ) +{ + try { + uno::Reference< registry::XRegistryKey > xKey( + xRegistryKey->createKey( + serviceDecl.getImplementationName() + + // xxx todo: use future generated function to get singleton name + OUSTR("/UNO/SINGLETONS/" + "com.sun.star.deployment.ExtensionManager") ) ); + xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] ); + return true; + } + catch (registry::InvalidRegistryException & exc) { + (void) exc; // avoid warnings + OSL_FAIL( ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + return false; + } +} + +// XModifyBroadcaster +//______________________________________________________________________________ +void ExtensionManager::addModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (uno::RuntimeException) +{ + check(); + rBHelper.addListener( ::getCppuType( &xListener ), xListener ); +} + +//______________________________________________________________________________ +void ExtensionManager::removeModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (uno::RuntimeException) +{ + check(); + rBHelper.removeListener( ::getCppuType( &xListener ), xListener ); +} + +void ExtensionManager::check() +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) { + throw lang::DisposedException( + OUSTR("ExtensionManager instance has already been disposed!"), + static_cast<OWeakObject *>(this) ); + } +} + +void ExtensionManager::fireModified() +{ + ::cppu::OInterfaceContainerHelper * pContainer = rBHelper.getContainer( + util::XModifyListener::static_type() ); + if (pContainer != 0) { + pContainer->forEach<util::XModifyListener>( + boost::bind(&util::XModifyListener::modified, _1, + lang::EventObject(static_cast<OWeakObject *>(this))) ); + } +} + +} // namespace dp_manager + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_extensionmanager.hxx b/desktop/source/deployment/manager/dp_extensionmanager.hxx new file mode 100644 index 000000000000..6c6bd5cb41f3 --- /dev/null +++ b/desktop/source/deployment/manager/dp_extensionmanager.hxx @@ -0,0 +1,321 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_EXTENSIONMANAGER_H +#define INCLUDED_DP_EXTENSIONMANAGER_H + +#include "dp_manager.hrc" +#include "dp_misc.h" +#include "dp_interact.h" +#include "dp_activepackages.hxx" +#include "rtl/ref.hxx" +#include "cppuhelper/compbase1.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/deployment/XPackageRegistry.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include "osl/mutex.hxx" +#include <list> + +namespace css = ::com::sun::star; + +namespace dp_manager { + +typedef ::boost::unordered_map< + ::rtl::OUString, + ::std::vector<css::uno::Reference<css::deployment::XPackage> >, + ::rtl::OUStringHash > id2extensions; + +class ExtensionManager : private ::dp_misc::MutexHolder, + public ::cppu::WeakComponentImplHelper1< css::deployment::XExtensionManager > +{ +public: + ExtensionManager( css::uno::Reference< css::uno::XComponentContext >const& xContext); + virtual ~ExtensionManager(); + + static css::uno::Sequence< ::rtl::OUString > getServiceNames(); + static ::rtl::OUString getImplName(); + + void check(); + void fireModified(); + +public: + +// XModifyBroadcaster + virtual void SAL_CALL addModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + +//XExtensionManager + virtual css::uno::Sequence< + css::uno::Reference<css::deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() + throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::task::XAbortChannel> SAL_CALL + createAbortChannel() throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL addExtension( + ::rtl::OUString const & url, + css::uno::Sequence<css::beans::NamedValue> const & properties, + ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL removeExtension( + ::rtl::OUString const & identifier, + ::rtl::OUString const & filename, + ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL enableExtension( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL disableExtension( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL checkPrerequisitesAndEnable( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Sequence< css::uno::Reference<css::deployment::XPackage> > + SAL_CALL getDeployedExtensions( + ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const &, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Reference< css::deployment::XPackage> + SAL_CALL getDeployedExtension( + ::rtl::OUString const & repository, + ::rtl::OUString const & identifier, + ::rtl::OUString const & filename, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > + SAL_CALL getExtensionsWithSameIdentifier( + ::rtl::OUString const & identifier, + ::rtl::OUString const & filename, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Sequence< css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > > + SAL_CALL getAllExtensions( + css::uno::Reference<css::task::XAbortChannel> const &, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL reinstallDeployedExtensions( + ::rtl::OUString const & repository, + css::uno::Reference< css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL synchronize( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL synchronizeBundledPrereg( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::uno::RuntimeException); + + virtual css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > SAL_CALL + getExtensionsWithUnacceptedLicenses( + ::rtl::OUString const & repository, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) + throw (css::deployment::DeploymentException, + css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isReadOnlyRepository(::rtl::OUString const & repository) + throw (css::uno::RuntimeException); + +private: + + struct StrSyncRepository : public ::dp_misc::StaticResourceString< + StrSyncRepository, RID_STR_SYNCHRONIZING_REPOSITORY> {}; + + struct ExtensionInfos + { + ::rtl::OUString identifier; + ::rtl::OUString fileName; + ::rtl::OUString displayName; + ::rtl::OUString version; + }; + + css::uno::Reference< css::uno::XComponentContext> m_xContext; + css::uno::Reference<css::deployment::XPackageManagerFactory> m_xPackageManagerFactory; + + //only to be used within addExtension + ::osl::Mutex m_addMutex; + /* contains the names of all repositories (except tmp) in order of there + priority. That is, the first element is "user" follod by "shared" and + then "bundled" + */ + ::std::list< ::rtl::OUString > m_repositoryNames; + + css::uno::Reference<css::deployment::XPackageManager> getUserRepository(); + css::uno::Reference<css::deployment::XPackageManager> getSharedRepository(); + css::uno::Reference<css::deployment::XPackageManager> getBundledRepository(); + css::uno::Reference<css::deployment::XPackageManager> getTmpRepository(); + + bool isUserDisabled(::rtl::OUString const & identifier, + ::rtl::OUString const & filename); + + bool isUserDisabled( + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > const & seqExtSameId); + + void activateExtension( + ::rtl::OUString const & identifier, + ::rtl::OUString const & fileName, + bool bUserDisabled, bool bStartup, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + void activateExtension( + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > const & seqExt, + bool bUserDisabled, bool bStartup, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ); + + ::std::list<css::uno::Reference<css::deployment::XPackage> > + getExtensionsWithSameId(::rtl::OUString const & identifier, + ::rtl::OUString const & fileName, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv = + css::uno::Reference< css::ucb::XCommandEnvironment>()); + + css::uno::Reference<css::deployment::XPackage> backupExtension( + ::rtl::OUString const & identifier, ::rtl::OUString const & fileName, + css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + void checkInstall( + ::rtl::OUString const & displayName, + css::uno::Reference<css::ucb::XCommandEnvironment> const & cmdEnv); + + void checkUpdate( + ::rtl::OUString const & newVersion, + ::rtl::OUString const & newDisplayName, + css::uno::Reference<css::deployment::XPackage> const & oldExtension, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + css::uno::Reference<css::deployment::XPackage> getTempExtension( + ::rtl::OUString const & url, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + void addExtensionsToMap( + id2extensions & mapExt, + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > const & seqExt, + ::rtl::OUString const & repository); + + css::uno::Reference<css::deployment::XPackageManager> + getPackageManager(::rtl::OUString const & repository) + throw (css::lang::IllegalArgumentException); + + bool doChecksForAddExtension( + css::uno::Reference<css::deployment::XPackageManager> const & xPackageMgr, + css::uno::Sequence<css::beans::NamedValue> const & properties, + css::uno::Reference<css::deployment::XPackage> const & xTmpExtension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + css::uno::Reference<css::deployment::XPackage> & out_existingExtension ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_informationprovider.cxx b/desktop/source/deployment/manager/dp_informationprovider.cxx new file mode 100644 index 000000000000..0786e7d84fa3 --- /dev/null +++ b/desktop/source/deployment/manager/dp_informationprovider.cxx @@ -0,0 +1,368 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <cppuhelper/implbase3.hxx> + +#include "comphelper/servicedecl.hxx" + +#include "com/sun/star/deployment/UpdateInformationProvider.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/XPackageInformationProvider.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/XUpdateInformationProvider.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/task/XAbortChannel.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/xml/dom/XElement.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" + +#include "com/sun/star/uno/Reference.hxx" +#include "rtl/ustring.hxx" +#include "ucbhelper/content.hxx" + +#include "dp_dependencies.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_identifier.hxx" +#include "dp_version.hxx" +#include "dp_misc.h" +#include "dp_update.hxx" + +namespace beans = com::sun::star::beans ; +namespace deployment = com::sun::star::deployment ; +namespace lang = com::sun::star::lang ; +namespace registry = com::sun::star::registry ; +namespace task = com::sun::star::task ; +namespace css_ucb = com::sun::star::ucb ; +namespace uno = com::sun::star::uno ; +namespace xml = com::sun::star::xml ; + +#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +namespace dp_info { + +class PackageInformationProvider : + public ::cppu::WeakImplHelper1< deployment::XPackageInformationProvider > + +{ + public: + PackageInformationProvider( uno::Reference< uno::XComponentContext >const& xContext); + virtual ~PackageInformationProvider(); + + static uno::Sequence< rtl::OUString > getServiceNames(); + static rtl::OUString getImplName(); + + // XPackageInformationProvider + virtual rtl::OUString SAL_CALL getPackageLocation( const rtl::OUString& extensionId ) + throw ( uno::RuntimeException ); + virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL isUpdateAvailable( const rtl::OUString& extensionId ) + throw ( uno::RuntimeException ); + virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL getExtensionList() + throw ( uno::RuntimeException ); +//--------- +private: + + uno::Reference< uno::XComponentContext> mxContext; + + rtl::OUString getPackageLocation( const rtl::OUString& repository, + const rtl::OUString& _sExtensionId ); + + uno::Reference< deployment::XUpdateInformationProvider > mxUpdateInformation; +}; + +//------------------------------------------------------------------------------ + +PackageInformationProvider::PackageInformationProvider( uno::Reference< uno::XComponentContext > const& xContext) : + mxContext( xContext ), + mxUpdateInformation( deployment::UpdateInformationProvider::create( xContext ) ) +{ +} + +//------------------------------------------------------------------------------ + +PackageInformationProvider::~PackageInformationProvider() +{ +} + +//------------------------------------------------------------------------------ +rtl::OUString PackageInformationProvider::getPackageLocation( + const rtl::OUString & repository, + const rtl::OUString& _rExtensionId ) +{ + rtl::OUString aLocationURL; + uno::Reference<deployment::XExtensionManager> xManager = + deployment::ExtensionManager::get(mxContext); + + if ( xManager.is() ) + { + const uno::Sequence< uno::Reference< deployment::XPackage > > packages( + xManager->getDeployedExtensions( + repository, + uno::Reference< task::XAbortChannel >(), + uno::Reference< css_ucb::XCommandEnvironment > () ) ); + + for ( int pos = packages.getLength(); pos--; ) + { + try + { + const rtl::OUString aName = packages[ pos ]->getName(); + const beans::Optional< rtl::OUString > aID = packages[ pos ]->getIdentifier(); + if ( aID.IsPresent && aID.Value.compareTo( _rExtensionId ) == 0 ) + { + aLocationURL = packages[ pos ]->getURL(); + break; + } + } + catch ( uno::RuntimeException & ) {} + } + } + + return aLocationURL; +} + +//------------------------------------------------------------------------------ + +rtl::OUString SAL_CALL +PackageInformationProvider::getPackageLocation( const rtl::OUString& _sExtensionId ) + throw ( uno::RuntimeException ) +{ + rtl::OUString aLocationURL = getPackageLocation( UNISTRING("user"), _sExtensionId ); + + if ( aLocationURL.getLength() == 0 ) + { + aLocationURL = getPackageLocation( UNISTRING("shared"), _sExtensionId ); + } + if ( aLocationURL.getLength() == 0 ) + { + aLocationURL = getPackageLocation( UNISTRING("bundled"), _sExtensionId ); + } + if ( aLocationURL.getLength() ) + { + ::ucbhelper::Content aContent( aLocationURL, NULL ); + aLocationURL = aContent.getURL(); + } + return aLocationURL; +} + +//------------------------------------------------------------------------------ + +uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL +PackageInformationProvider::isUpdateAvailable( const rtl::OUString& _sExtensionId ) + throw ( uno::RuntimeException ) +{ + uno::Sequence< uno::Sequence< rtl::OUString > > aList; + + uno::Reference<deployment::XExtensionManager> extMgr = + deployment::ExtensionManager::get(mxContext); + + if (!extMgr.is()) + { + OSL_ASSERT(0); + return aList; + } + std::vector<std::pair<uno::Reference<deployment::XPackage>, uno::Any > > errors; + dp_misc::UpdateInfoMap updateInfoMap; + if (_sExtensionId.getLength()) + { + std::vector<uno::Reference<deployment::XPackage> > vecExtensions; + uno::Reference<deployment::XPackage> extension; + try + { + extension = dp_misc::getExtensionWithHighestVersion( + extMgr->getExtensionsWithSameIdentifier( + _sExtensionId, _sExtensionId, uno::Reference<css_ucb::XCommandEnvironment>())); + vecExtensions.push_back(extension); + } + catch (lang::IllegalArgumentException &) + { + OSL_ASSERT(0); + } + updateInfoMap = dp_misc::getOnlineUpdateInfos( + mxContext, extMgr, mxUpdateInformation, &vecExtensions, errors); + } + else + { + updateInfoMap = dp_misc::getOnlineUpdateInfos( + mxContext, extMgr, mxUpdateInformation, NULL, errors); + } + + int nCount = 0; + for (dp_misc::UpdateInfoMap::iterator i(updateInfoMap.begin()); i != updateInfoMap.end(); ++i) + { + dp_misc::UpdateInfo const & info = i->second; + + rtl::OUString sOnlineVersion; + if (info.info.is()) + { + // check, if there are unsatisfied dependencies and ignore this online update + dp_misc::DescriptionInfoset infoset(mxContext, info.info); + uno::Sequence< uno::Reference< xml::dom::XElement > > + ds( dp_misc::Dependencies::check( infoset ) ); + if ( ! ds.getLength() ) + sOnlineVersion = info.version; + } + + rtl::OUString sVersionUser; + rtl::OUString sVersionShared; + rtl::OUString sVersionBundled; + uno::Sequence< uno::Reference< deployment::XPackage> > extensions; + try { + extensions = extMgr->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(info.extension), info.extension->getName(), + uno::Reference<css_ucb::XCommandEnvironment>()); + } catch (lang::IllegalArgumentException& ) { + OSL_ASSERT(0); + } + OSL_ASSERT(extensions.getLength() == 3); + if (extensions[0].is() ) + sVersionUser = extensions[0]->getVersion(); + if (extensions[1].is() ) + sVersionShared = extensions[1]->getVersion(); + if (extensions[2].is() ) + sVersionBundled = extensions[2]->getVersion(); + + bool bSharedReadOnly = extMgr->isReadOnlyRepository(OUSTR("shared")); + + dp_misc::UPDATE_SOURCE sourceUser = dp_misc::isUpdateUserExtension( + bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion); + dp_misc::UPDATE_SOURCE sourceShared = dp_misc::isUpdateSharedExtension( + bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion); + + rtl::OUString updateVersionUser; + rtl::OUString updateVersionShared; + if (sourceUser != dp_misc::UPDATE_SOURCE_NONE) + updateVersionUser = dp_misc::getHighestVersion( + rtl::OUString(), sVersionShared, sVersionBundled, sOnlineVersion); + if (sourceShared != dp_misc::UPDATE_SOURCE_NONE) + updateVersionShared = dp_misc::getHighestVersion( + rtl::OUString(), rtl::OUString(), sVersionBundled, sOnlineVersion); + rtl::OUString updateVersion; + if (dp_misc::compareVersions(updateVersionUser, updateVersionShared) == dp_misc::GREATER) + updateVersion = updateVersionUser; + else + updateVersion = updateVersionShared; + if (updateVersion.getLength()) + { + + rtl::OUString aNewEntry[2]; + aNewEntry[0] = i->first; + aNewEntry[1] = updateVersion; + aList.realloc( ++nCount ); + aList[ nCount-1 ] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 ); + } + } + return aList; +} + +//------------------------------------------------------------------------------ +uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL PackageInformationProvider::getExtensionList() + throw ( uno::RuntimeException ) +{ + const uno::Reference<deployment::XExtensionManager> mgr = + deployment::ExtensionManager::get(mxContext); + + if (!mgr.is()) + return uno::Sequence< uno::Sequence< rtl::OUString > >(); + + const uno::Sequence< uno::Sequence< uno::Reference<deployment::XPackage > > > + allExt = mgr->getAllExtensions( + uno::Reference< task::XAbortChannel >(), + uno::Reference< css_ucb::XCommandEnvironment > () ); + + uno::Sequence< uno::Sequence< rtl::OUString > > retList; + + sal_Int32 cAllIds = allExt.getLength(); + retList.realloc(cAllIds); + + for (sal_Int32 i = 0; i < cAllIds; i++) + { + //The inner sequence contains extensions with the same identifier from + //all the different repositories, that is user, share, bundled. + const uno::Sequence< uno::Reference< deployment::XPackage > > & + seqExtension = allExt[i]; + sal_Int32 cExt = seqExtension.getLength(); + OSL_ASSERT(cExt == 3); + for (sal_Int32 j = 0; j < cExt; j++) + { + //ToDo according to the old code the first found extenions is used + //even if another one with the same id has a better version. + uno::Reference< deployment::XPackage > const & xExtension( seqExtension[j] ); + if (xExtension.is()) + { + rtl::OUString aNewEntry[2]; + aNewEntry[0] = dp_misc::getIdentifier(xExtension); + aNewEntry[1] = xExtension->getVersion(); + retList[i] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 ); + break; + } + } + } + return retList; +} + + +//------------------------------------------------------------------------------ + +namespace sdecl = comphelper::service_decl; +sdecl::class_<PackageInformationProvider> servicePIP; +extern sdecl::ServiceDecl const serviceDecl( + servicePIP, + // a private one: + "com.sun.star.comp.deployment.PackageInformationProvider", + "com.sun.star.comp.deployment.PackageInformationProvider" ); + +//------------------------------------------------------------------------------ +bool singleton_entries( + uno::Reference< registry::XRegistryKey > const & xRegistryKey ) +{ + try { + uno::Reference< registry::XRegistryKey > xKey( + xRegistryKey->createKey( + serviceDecl.getImplementationName() + + // xxx todo: use future generated function to get singleton name + UNISTRING("/UNO/SINGLETONS/" + "com.sun.star.deployment.PackageInformationProvider") ) ); + xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] ); + return true; + } + catch (registry::InvalidRegistryException & exc) { + (void) exc; // avoid warnings + OSL_FAIL( ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + return false; + } +} + +} // namespace dp_info + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_manager.cxx b/desktop/source/deployment/manager/dp_manager.cxx new file mode 100644 index 000000000000..680dbf855d9d --- /dev/null +++ b/desktop/source/deployment/manager/dp_manager.cxx @@ -0,0 +1,1689 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_ucb.h" +#include "dp_resource.h" +#include "dp_platform.hxx" +#include "dp_manager.h" +#include "dp_identifier.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/string.hxx" +#include "rtl/uri.hxx" +#include "rtl/bootstrap.hxx" +#include "osl/diagnose.h" +#include "osl/file.hxx" +#include "osl/security.hxx" +#include "cppuhelper/weakref.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/interfacecontainer.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/sequence.hxx" +#include "xmlscript/xml_helper.hxx" +#include "svl/inettype.hxx" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/beans/UnknownPropertyException.hpp" +#include "com/sun/star/util/XUpdatable.hpp" +#include "com/sun/star/sdbc/XResultSet.hpp" +#include "com/sun/star/sdbc/XRow.hpp" +#include "com/sun/star/ucb/XContentAccess.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/deployment/Prerequisites.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/ucb/UnsupportedCommandException.hpp" +#include "boost/bind.hpp" +#include "tools/urlobj.hxx" +#include "unotools/tempfile.hxx" + +#include "osl/file.hxx" +#include <vector> +#include <list> +#include "dp_descriptioninfoset.hxx" +#include "dp_commandenvironments.hxx" +#include "dp_properties.hxx" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_log { +extern comphelper::service_decl::ServiceDecl const serviceDecl; +} + +namespace dp_registry { +Reference<deployment::XPackageRegistry> create( + OUString const & context, + OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ); +} + +namespace dp_manager { + +struct MatchTempDir +{ + OUString m_str; + MatchTempDir( OUString const & str ) : m_str( str ) {} + bool operator () ( ActivePackages::Entries::value_type const & v ) const { + return v.second.temporaryName.equalsIgnoreAsciiCase( m_str ); + } +}; + + +namespace { +OUString getExtensionFolder(OUString const & parentFolder, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + ::ucbhelper::Content tempFolder( + parentFolder, xCmdEnv ); + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_FOLDERS_ONLY ) ); + + OUString title; + while (xResultSet->next()) + { + title = Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString(1 /* Title */ ) ; + break; + } + return title; +} +} +//______________________________________________________________________________ +void PackageManagerImpl::initActivationLayer( + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (m_activePackages.getLength() == 0) + { + OSL_ASSERT( m_registryCache.getLength() == 0 ); + // documents temp activation: + m_activePackagesDB.reset( new ActivePackages ); + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, m_context, xCmdEnv, + false /* no throw */ )) + { + // scan for all entries in m_packagesDir: + Reference<sdbc::XResultSet> xResultSet( + ucbContent.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ) ); + while (xResultSet->next()) + { + Reference<sdbc::XRow> xRow( xResultSet, UNO_QUERY_THROW ); + OUString title( xRow->getString( 1 /* Title */ ) ); + // xxx todo: remove workaround for tdoc + if (title.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "this_is_a_dummy_stream_just_there_" + "as_a_workaround_for_a_" + "temporary_limitation_of_the_" + "storage_api_implementation") )) + continue; + if (title.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "META-INF") ) ) + continue; + + ::ucbhelper::Content sourceContent( + Reference<XContentAccess>( + xResultSet, UNO_QUERY_THROW )->queryContent(), + xCmdEnv ); + + OUString mediaType( detectMediaType( sourceContent, + false /* no throw */) ); + if (mediaType.getLength() >0) + { + ActivePackages::Data dbData; + insertToActivationLayer( + Sequence<css::beans::NamedValue>(),mediaType, sourceContent, + title, &dbData ); + + insertToActivationLayerDB( title, dbData ); + //TODO #i73136#: insertToActivationLayerDB needs id not + // title, but the whole m_activePackages.getLength()==0 + // case (i.e., document-relative deployment) currently + // does not work, anyway. + } + } + } + } + else + { + // user|share: + OSL_ASSERT( m_activePackages.getLength() > 0 ); + m_activePackages_expanded = expandUnoRcUrl( m_activePackages ); + m_registrationData_expanded = expandUnoRcUrl(m_registrationData); + if (!m_readOnly) + create_folder( 0, m_activePackages_expanded, xCmdEnv, true); + + OUString dbName; + if (m_context.equals(OUSTR("user"))) + dbName = m_activePackages_expanded + OUSTR(".db"); + else + { + //Create the extension data base in the user installation + create_folder( 0, m_registrationData_expanded, xCmdEnv, true); + dbName = m_registrationData_expanded + OUSTR("/extensions.db"); + } + //The data base can always be written because it it always in the user installation + m_activePackagesDB.reset( + new ActivePackages( dbName, false ) ); + + if (! m_readOnly && ! m_context.equals(OUSTR("bundled"))) + { + // clean up activation layer, scan for zombie temp dirs: + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + + ::ucbhelper::Content tempFolder( + m_activePackages_expanded, xCmdEnv ); + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ) ); + // get all temp directories: + ::std::vector<OUString> tempEntries; + ::std::vector<OUString> removedEntries; + while (xResultSet->next()) + { + OUString title( + Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString( + 1 /* Title */ ) ); + + const char extensionRemoved[] = "removed"; + if (title.endsWithAsciiL( + extensionRemoved, sizeof(extensionRemoved) - 1)) + { + //save the file name withouth the "removed" part + sal_Int32 index = title.lastIndexOfAsciiL( + extensionRemoved, sizeof(extensionRemoved) - 1); + OUString remFile = title.copy(0, index); + removedEntries.push_back(::rtl::Uri::encode( + remFile, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + } + else + { + tempEntries.push_back( ::rtl::Uri::encode( + title, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + } + } + + bool bShared = m_context.equals(OUSTR("shared")) ? true : false; + for ( ::std::size_t pos = 0; pos < tempEntries.size(); ++pos ) + { + OUString const & tempEntry = tempEntries[ pos ]; + const MatchTempDir match( tempEntry ); + if (::std::find_if( id2temp.begin(), id2temp.end(), match ) == + id2temp.end()) + { + const OUString url( + makeURL(m_activePackages_expanded, tempEntry ) ); + + //In case of shared extensions, new entries are regarded as + //added extensions if there is no xxx.tmpremoved file. + if (bShared) + { + if (::std::find(removedEntries.begin(), removedEntries.end(), tempEntry) == + removedEntries.end()) + { + continue; + } + else + { + //Make sure only the same user removes the extension, who + //previously unregistered it. This is avoid races if multiple instances + //of OOo are running which all have write access to the shared installation. + //For example, a user removes the extension, but keeps OOo + //running. Parts of the extension may still be loaded and used by OOo. + //Therefore the extension is only deleted the next time the extension manager is + //run after restarting OOo. While OOo is still running, another user starts OOo + //which would deleted the extension files. If the same user starts another + //instance of OOo then the lock file will prevent this. + OUString aUserName; + ::osl::Security aSecurity; + aSecurity.getUserName( aUserName ); + ucbhelper::Content remFileContent( + url + OUSTR("removed"), Reference<XCommandEnvironment>()); + ::rtl::ByteSequence data = dp_misc::readFile(remFileContent); + ::rtl::OString osData(reinterpret_cast<const sal_Char*>(data.getConstArray()), + data.getLength()); + OUString sData = ::rtl::OStringToOUString( + osData, RTL_TEXTENCODING_UTF8); + if (!sData.equals(aUserName)) + continue; + } + } + // temp entry not needed anymore: + erase_path( url + OUSTR("_"), + Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + erase_path( url, Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + //delete the xxx.tmpremoved file + erase_path(url + OUSTR("removed"), + Reference<XCommandEnvironment>(), false); + } + } + } + } +} + +//______________________________________________________________________________ +void PackageManagerImpl::initRegistryBackends() +{ + if (m_registryCache.getLength() > 0) + create_folder( 0, m_registryCache, + Reference<XCommandEnvironment>(), false); + m_xRegistry.set( ::dp_registry::create( + m_context, m_registryCache, false, + m_xComponentContext ) ); +} + +//______________________________________________________________________________ +Reference<deployment::XPackageManager> PackageManagerImpl::create( + Reference<XComponentContext> const & xComponentContext, + OUString const & context ) +{ + PackageManagerImpl * that = new PackageManagerImpl( + xComponentContext, context ); + Reference<deployment::XPackageManager> xPackageManager( that ); + + OUString packages, logFile, stampURL; + if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("user") )) { + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/registry"); + logFile = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/log.txt"); + //We use the extension .sys for the file because on Windows Vista a sys + //(as well as exe and dll) file + //will not be written in the VirtualStore. For example if the process has no + //admin right once cannot write to the %programfiles% folder. However, when + //virtualization is used, the file will be written into the VirtualStore and + //it appears as if one could write to %programfiles%. When we test for write + //access to the office/shared folder for shared extensions then this typically + //fails because a normal user typically cannot write to this folder. However, + //using virtualization it appears that he/she can. Then a shared extension can + //be installed but is only visible for the user (because the extension is in + //the virtual store). + stampURL = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/stamp.sys"); + } + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) { + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER/registry"); + logFile = OUSTR( + "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER/log.txt"); + stampURL = OUSTR( + "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/stamp.sys"); + } + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled") )) { + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER/registry"); + logFile = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER/log.txt"); + //No stamp file. We assume that bundled is always readonly. It must not be + //modified from ExtensionManager but only by the installer + } + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled_prereg") )) { + //This is a bundled repository but the registration data + //is in the brand layer: share/prereg + //It is special because the registration data are copied at the first startup + //into the user installation. The processed help and xcu files are not + //copied. Instead the backenddb.xml for the help backend references the help + //by using $BUNDLED_EXTENSION_PREREG instead $BUNDLED_EXTENSIONS_USER. The + //configmgr.ini also used $BUNDLED_EXTENSIONS_PREREG to refer to the xcu file + //which contain the replacement for %origin%. + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_PREREG"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_PREREG/registry"); + logFile = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_PREREG/log.txt"); + } + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("tmp") )) { + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS/extensions"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS/registry"); + stampURL = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS/stamp.sys"); + } + else if (! context.matchAsciiL( + RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.tdoc:/") )) { + throw lang::IllegalArgumentException( + OUSTR("invalid context given: ") + context, + Reference<XInterface>(), static_cast<sal_Int16>(-1) ); + } + + Reference<XCommandEnvironment> xCmdEnv; + + try { + //There is no stampURL for the bundled folder + if (stampURL.getLength() > 0) + { +#define CURRENT_STAMP "1" + try { + //The osl file API does not allow to find out if one can write + //into a folder. Therefore we try to write a file. Then we delete + //it, so that it does not hinder uninstallation of OOo + // probe writing: + ::ucbhelper::Content ucbStamp( stampURL, xCmdEnv ); + ::rtl::OString stamp( + RTL_CONSTASCII_STRINGPARAM(CURRENT_STAMP) ); + Reference<io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(stamp.getStr()), + stamp.getLength() ) ) ); + ucbStamp.writeStream( xData, true /* replace existing */ ); + that->m_readOnly = false; + erase_path( stampURL, xCmdEnv ); + } + catch (RuntimeException &) { + try { + erase_path( stampURL, xCmdEnv ); + } catch (...) + { + } + throw; + } + catch (Exception &) { + that->m_readOnly = true; + } + } + + if (!that->m_readOnly && logFile.getLength() > 0) + { + const Any any_logFile(logFile); + that->m_xLogFile.set( + that->m_xComponentContext->getServiceManager() + ->createInstanceWithArgumentsAndContext( + dp_log::serviceDecl.getSupportedServiceNames()[0], + Sequence<Any>( &any_logFile, 1 ), + that->m_xComponentContext ), + UNO_QUERY_THROW ); + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv, that->m_xLogFile ) ); + } + + that->initRegistryBackends(); + that->initActivationLayer( xCmdEnv ); + + return xPackageManager; + + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[context=\"") ); + buf.append( context ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\"] caught unexpected exception!") ); + throw lang::WrappedTargetRuntimeException( + buf.makeStringAndClear(), Reference<XInterface>(), exc ); + } +} + +//______________________________________________________________________________ +PackageManagerImpl::~PackageManagerImpl() +{ +} + +//______________________________________________________________________________ +void PackageManagerImpl::fireModified() +{ + ::cppu::OInterfaceContainerHelper * pContainer = rBHelper.getContainer( + util::XModifyListener::static_type() ); + if (pContainer != 0) { + pContainer->forEach<util::XModifyListener>( + boost::bind(&util::XModifyListener::modified, _1, + lang::EventObject(static_cast<OWeakObject *>(this))) ); + } +} + +//______________________________________________________________________________ +void PackageManagerImpl::disposing() +{ + try { +// // xxx todo: guarding? +// ::osl::MutexGuard guard( getMutex() ); + try_dispose( m_xLogFile ); + m_xLogFile.clear(); + try_dispose( m_xRegistry ); + m_xRegistry.clear(); + m_activePackagesDB.reset(0); + m_xComponentContext.clear(); + + t_pm_helper::disposing(); + + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( + OUSTR("caught unexpected exception while disposing..."), + static_cast<OWeakObject *>(this), exc ); + } +} + +// XComponent +//______________________________________________________________________________ +void PackageManagerImpl::dispose() throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::dispose(); +} + +//______________________________________________________________________________ +void PackageManagerImpl::addEventListener( + Reference<lang::XEventListener> const & xListener ) throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::addEventListener( xListener ); +} + +//______________________________________________________________________________ +void PackageManagerImpl::removeEventListener( + Reference<lang::XEventListener> const & xListener ) throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::removeEventListener( xListener ); +} + +// XPackageManager +//______________________________________________________________________________ +OUString PackageManagerImpl::getContext() throw (RuntimeException) +{ + check(); + return m_context; +} + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +PackageManagerImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + OSL_ASSERT( m_xRegistry.is() ); + return m_xRegistry->getSupportedPackageTypes(); +} + +//______________________________________________________________________________ +Reference<task::XAbortChannel> PackageManagerImpl::createAbortChannel() + throw (RuntimeException) +{ + check(); + return new AbortChannel; +} + +// XModifyBroadcaster +//______________________________________________________________________________ +void PackageManagerImpl::addModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (RuntimeException) +{ + check(); + rBHelper.addListener( ::getCppuType( &xListener ), xListener ); +} + +//______________________________________________________________________________ +void PackageManagerImpl::removeModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (RuntimeException) +{ + check(); + rBHelper.removeListener( ::getCppuType( &xListener ), xListener ); +} + +//______________________________________________________________________________ +OUString PackageManagerImpl::detectMediaType( + ::ucbhelper::Content const & ucbContent_, bool throw_exc ) +{ + ::ucbhelper::Content ucbContent(ucbContent_); + OUString url( ucbContent.getURL() ); + OUString mediaType; + if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.tdoc:") ) || + url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.pkg:") )) + { + try { + ucbContent.getPropertyValue( OUSTR("MediaType") ) >>= mediaType; + } + catch (beans::UnknownPropertyException &) { + } + OSL_ENSURE( mediaType.getLength() > 0, "### no media-type?!" ); + } + if (mediaType.getLength() == 0) + { + try { + Reference<deployment::XPackage> xPackage( + m_xRegistry->bindPackage( + url, OUString(), false, OUString(), ucbContent.getCommandEnvironment() ) ); + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) + mediaType = xPackageType->getMediaType(); + } + catch (lang::IllegalArgumentException & exc) { + if (throw_exc) + throw; + (void) exc; + OSL_FAIL( ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } + return mediaType; +} + +//______________________________________________________________________________ +OUString PackageManagerImpl::insertToActivationLayer( + Sequence<beans::NamedValue> const & properties, + OUString const & mediaType, ::ucbhelper::Content const & sourceContent_, + OUString const & title, ActivePackages::Data * dbData ) +{ + ::ucbhelper::Content sourceContent(sourceContent_); + Reference<XCommandEnvironment> xCmdEnv( + sourceContent.getCommandEnvironment() ); + + String baseDir(m_activePackages_expanded); + ::utl::TempFile aTemp(&baseDir, sal_False); + OUString tempEntry = aTemp.GetURL(); + tempEntry = tempEntry.copy(tempEntry.lastIndexOf('/') + 1); + OUString destFolder = makeURL( m_activePackages, tempEntry); + destFolder += OUSTR("_"); + + // prepare activation folder: + ::ucbhelper::Content destFolderContent; + create_folder( &destFolderContent, destFolder, xCmdEnv ); + + // copy content into activation temp dir: + if (mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.package-bundle") ) || + // xxx todo: more sophisticated parsing + mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.legacy-package-bundle") )) + { + // inflate content: + ::rtl::OUStringBuffer buf; + if (!sourceContent.isFolder()) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.zip://") ); + buf.append( ::rtl::Uri::encode( sourceContent.getURL(), + rtl_UriCharClassRegName, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + } + else + { + //Folder. No need to unzip, just copy + buf.append(sourceContent.getURL()); + } + buf.append( static_cast<sal_Unicode>('/') ); + sourceContent = ::ucbhelper::Content( + buf.makeStringAndClear(), xCmdEnv ); + } + if (! destFolderContent.transferContent( + sourceContent, ::ucbhelper::InsertOperation_COPY, + title, NameClash::OVERWRITE )) + throw RuntimeException( OUSTR("UCB transferContent() failed!"), 0 ); + + + // write to DB: + //bundled extensions should only be added by the synchronizeAddedExtensions + //functions. Moreover, there is no "temporary folder" for bundled extensions. + OSL_ASSERT(!m_context.equals(OUSTR("bundled"))); + OUString sFolderUrl = makeURLAppendSysPathSegment(destFolderContent.getURL(), title); + DescriptionInfoset info = + dp_misc::getDescriptionInfoset(sFolderUrl); + dbData->temporaryName = tempEntry; + dbData->fileName = title; + dbData->mediaType = mediaType; + dbData->version = info.getVersion(); + + //No write the properties file next to the extension + ExtensionProperties props(sFolderUrl, properties, xCmdEnv); + props.write(); + return destFolder; +} + +//______________________________________________________________________________ +void PackageManagerImpl::insertToActivationLayerDB( + OUString const & id, ActivePackages::Data const & dbData ) +{ + //access to the database must be guarded. See removePackage + const ::osl::MutexGuard guard( getMutex() ); + m_activePackagesDB->put( id, dbData ); +} + +//______________________________________________________________________________ +/* The function returns true if there is an extension with the same id already + installed which needs to be uninstalled, before the new extension can be installed. +*/ +bool PackageManagerImpl::isInstalled( + Reference<deployment::XPackage> const & package) +{ + OUString id(dp_misc::getIdentifier(package)); + OUString fn(package->getName()); + bool bInstalled = false; + if (m_activePackagesDB->has( id, fn )) + { + bInstalled = true; + } + return bInstalled; +} + +// XPackageManager +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageManagerImpl::importExtension( + Reference<deployment::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + CommandAbortedException, lang::IllegalArgumentException, + RuntimeException) +{ + return addPackage(extension->getURL(), Sequence<beans::NamedValue>(), + OUString(), xAbortChannel, xCmdEnv_); +} + +/* The function adds an extension but does not register it!!! + It may not do any user interaction. This is done in XExtensionManager::addExtension +*/ +Reference<deployment::XPackage> PackageManagerImpl::addPackage( + OUString const & url, + css::uno::Sequence<css::beans::NamedValue> const & properties, + OUString const & mediaType_, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + CommandAbortedException, lang::IllegalArgumentException, + RuntimeException) +{ + check(); + if (m_readOnly) + { + OUString message; + if (m_context == OUSTR("shared")) + message = OUSTR("You need write permissions to install a shared extension!"); + else + message = OUSTR("You need write permissions to install this extension!"); + throw deployment::DeploymentException( + message, static_cast<OWeakObject *>(this), Any() ); + } + Reference<XCommandEnvironment> xCmdEnv; + if (m_xLogFile.is()) + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); + else + xCmdEnv.set( xCmdEnv_ ); + + try { + ::ucbhelper::Content sourceContent; + create_ucb_content( &sourceContent, url, xCmdEnv ); // throws exc + const OUString title(sourceContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + const OUString title_enc( ::rtl::Uri::encode( + title, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + OUString destFolder; + + OUString mediaType(mediaType_); + if (mediaType.getLength() == 0) + mediaType = detectMediaType( sourceContent ); + + Reference<deployment::XPackage> xPackage; + // copy file: + progressUpdate( + getResourceString(RID_STR_COPYING_PACKAGE) + title, xCmdEnv ); + if (m_activePackages.getLength() == 0) + { + ::ucbhelper::Content docFolderContent; + create_folder( &docFolderContent, m_context, xCmdEnv ); + // copy into document, first: + if (! docFolderContent.transferContent( + sourceContent, ::ucbhelper::InsertOperation_COPY, + OUString(), + NameClash::ASK /* xxx todo: ASK not needed? */)) + throw RuntimeException( + OUSTR("UCB transferContent() failed!"), 0 ); + // set media-type: + ::ucbhelper::Content docContent( + makeURL( m_context, title_enc ), xCmdEnv ); + //TODO #i73136#: using title instead of id can lead to + // clashes, but the whole m_activePackages.getLength()==0 + // case (i.e., document-relative deployment) currently does + // not work, anyway. + docContent.setPropertyValue( + OUSTR("MediaType"), Any(mediaType) ); + + // xxx todo: obsolete in the future + try { + docFolderContent.executeCommand( OUSTR("flush"), Any() ); + } + catch (UnsupportedCommandException &) { + } + } + ActivePackages::Data dbData; + destFolder = insertToActivationLayer( + properties, mediaType, sourceContent, title, &dbData ); + + + // bind activation package: + //Because every shared/user extension will be unpacked in a folder, + //which was created with a unique name we will always have two different + //XPackage objects, even if the second extension is the same. + //Therefore bindPackage does not need a guard here. + xPackage = m_xRegistry->bindPackage( + makeURL( destFolder, title_enc ), mediaType, false, OUString(), xCmdEnv ); + + OSL_ASSERT( xPackage.is() ); + if (xPackage.is()) + { + bool install = false; + try + { + OUString const id = dp_misc::getIdentifier( xPackage ); + + ::osl::MutexGuard g(m_addMutex); + if (isInstalled(xPackage)) + { + //Do not guard the complete function with the getMutex + removePackage(id, xPackage->getName(), xAbortChannel, + xCmdEnv); + } + install = true; + insertToActivationLayerDB(id, dbData); + } + catch (...) + { + deletePackageFromCache( xPackage, destFolder ); + throw; + } + if (!install) + { + deletePackageFromCache( xPackage, destFolder ); + } + //ToDo: We should notify only if the extension is registered + fireModified(); + } + return xPackage; + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (CommandAbortedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (deployment::DeploymentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + logIntern( exc ); + throw deployment::DeploymentException( + getResourceString(RID_STR_ERROR_WHILE_ADDING) + url, + static_cast<OWeakObject *>(this), exc ); + } +} +void PackageManagerImpl::deletePackageFromCache( + Reference<deployment::XPackage> const & xPackage, + OUString const & destFolder) +{ + try_dispose( xPackage ); + + //we remove the package from the uno cache + //no service from the package may be loaded at this time!!! + erase_path( destFolder, Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + //rm last character '_' + OUString url = destFolder.copy(0, destFolder.getLength() - 1); + erase_path( url, Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + +} +//______________________________________________________________________________ +void PackageManagerImpl::removePackage( + OUString const & id, ::rtl::OUString const & fileName, + Reference<task::XAbortChannel> const & /*xAbortChannel*/, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + CommandAbortedException, lang::IllegalArgumentException, + RuntimeException) +{ + check(); + + Reference<XCommandEnvironment> xCmdEnv; + if (m_xLogFile.is()) + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); + else + xCmdEnv.set( xCmdEnv_ ); + + try { + Reference<deployment::XPackage> xPackage; + { + const ::osl::MutexGuard guard(getMutex()); + //Check if this extension exist and throw an IllegalArgumentException + //if it does not + //If the files of the extension are already removed, or there is a + //different extension at the same place, for example after updating the + //extension, then the returned object is that which uses the database data. + xPackage = getDeployedPackage_(id, fileName, xCmdEnv ); + + + //Because the extension is only removed the next time the extension + //manager runs after restarting OOo, we need to indicate that a + //shared extension was "deleted". When a user starts OOo, then it + //will check if something changed in the shared repository. Based on + //the flag file it will then recognize, that the extension was + //deleted and can then update the extnesion database of the shared + //extensions in the user installation. + if ( xPackage.is() && !m_readOnly && !xPackage->isRemoved() && m_context.equals(OUSTR("shared"))) + { + ActivePackages::Data val; + m_activePackagesDB->get( & val, id, fileName); + OSL_ASSERT(val.temporaryName.getLength()); + OUString url(makeURL(m_activePackages_expanded, + val.temporaryName + OUSTR("removed"))); + ::ucbhelper::Content contentRemoved(url, xCmdEnv ); + OUString aUserName; + ::osl::Security aSecurity; + aSecurity.getUserName( aUserName ); + + ::rtl::OString stamp = ::rtl::OUStringToOString(aUserName, RTL_TEXTENCODING_UTF8); + Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(stamp.getStr()), + stamp.getLength() ) ) ); + contentRemoved.writeStream( xData, true /* replace existing */ ); + } + m_activePackagesDB->erase( id, fileName ); // to be removed upon next start + //remove any cached data hold by the backend + m_xRegistry->packageRemoved(xPackage->getURL(), xPackage->getPackageType()->getMediaType()); + } + try_dispose( xPackage ); + + fireModified(); + } + catch (RuntimeException &) { + throw; + } + catch (lang::IllegalArgumentException &) { + throw; + } + catch (CommandFailedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (CommandAbortedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (deployment::DeploymentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + logIntern( exc ); + throw deployment::DeploymentException( + getResourceString(RID_STR_ERROR_WHILE_REMOVING) + id, + static_cast<OWeakObject *>(this), exc ); + } +} + +//______________________________________________________________________________ +OUString PackageManagerImpl::getDeployPath( ActivePackages::Data const & data ) +{ + ::rtl::OUStringBuffer buf; + buf.append( data.temporaryName ); + //The bundled extensions are not contained in an additional folder + //with a unique name. data.temporaryName contains already the + //UTF8 encoded folder name. See PackageManagerImpl::synchronize + if (!m_context.equals(OUSTR("bundled")) + && !m_context.equals(OUSTR("bundled_prereg"))) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("_/") ); + buf.append( ::rtl::Uri::encode( data.fileName, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + } + return makeURL( m_activePackages, buf.makeStringAndClear() ); +} + +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageManagerImpl::getDeployedPackage_( + OUString const & id, OUString const & fileName, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + ActivePackages::Data val; + if (m_activePackagesDB->get( &val, id, fileName )) + { + return getDeployedPackage_( id, val, xCmdEnv, false ); + } + throw lang::IllegalArgumentException( + getResourceString(RID_STR_NO_SUCH_PACKAGE) + id, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); +} + +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageManagerImpl::getDeployedPackage_( + OUString const & id, ActivePackages::Data const & data, + Reference<XCommandEnvironment> const & xCmdEnv, bool ignoreAlienPlatforms ) +{ + if (ignoreAlienPlatforms) + { + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( data.mediaType, type, subType, ¶ms )) + { + INetContentTypeParameter const * param = params.find( + ByteString("platform") ); + if (param != 0 && !platform_fits( param->m_sValue )) + throw lang::IllegalArgumentException( + getResourceString(RID_STR_NO_SUCH_PACKAGE) + id, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); + } + } + Reference<deployment::XPackage> xExtension; + try + { + //Ignore extensions where XPackage::checkPrerequisites failed. + //They must not be usable for this user. + if (data.failedPrerequisites.equals(OUSTR("0"))) + { + xExtension = m_xRegistry->bindPackage( + getDeployPath( data ), data.mediaType, false, OUString(), xCmdEnv ); + } + } + catch (deployment::InvalidRemovedParameterException& e) + { + xExtension = e.Extension; + } + return xExtension; +} + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackage> > +PackageManagerImpl::getDeployedPackages_( + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + ::std::vector< Reference<deployment::XPackage> > packages; + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + ActivePackages::Entries::const_iterator iPos( id2temp.begin() ); + ActivePackages::Entries::const_iterator const iEnd( id2temp.end() ); + for ( ; iPos != iEnd; ++iPos ) + { + if (! iPos->second.failedPrerequisites.equals(OUSTR("0"))) + continue; + try { + packages.push_back( + getDeployedPackage_( + iPos->first, iPos->second, xCmdEnv, + true /* xxx todo: think of GUI: + ignore other platforms than the current one */ ) ); + } + catch (lang::IllegalArgumentException & exc) { + // ignore + (void) exc; // avoid warnings + OSL_FAIL( ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + catch (deployment::DeploymentException& exc) { + // ignore + (void) exc; // avoid warnings + OSL_FAIL( ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } + return comphelper::containerToSequence(packages); +} + +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageManagerImpl::getDeployedPackage( + OUString const & id, ::rtl::OUString const & fileName, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + lang::IllegalArgumentException, RuntimeException) +{ + check(); + Reference<XCommandEnvironment> xCmdEnv; + if (m_xLogFile.is()) + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); + else + xCmdEnv.set( xCmdEnv_ ); + + try { + const ::osl::MutexGuard guard( getMutex() ); + return getDeployedPackage_( id, fileName, xCmdEnv ); + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (lang::IllegalArgumentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (deployment::DeploymentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + logIntern( exc ); + throw deployment::DeploymentException( + // ought never occur... + OUSTR("error while accessing deployed package: ") + id, + static_cast<OWeakObject *>(this), exc ); + } +} + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackage> > +PackageManagerImpl::getDeployedPackages( + Reference<task::XAbortChannel> const &, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + CommandAbortedException, lang::IllegalArgumentException, + RuntimeException) +{ + check(); + Reference<XCommandEnvironment> xCmdEnv; + if (m_xLogFile.is()) + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); + else + xCmdEnv.set( xCmdEnv_ ); + + try { + const ::osl::MutexGuard guard( getMutex() ); + return getDeployedPackages_( xCmdEnv ); + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (CommandAbortedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (deployment::DeploymentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + logIntern( exc ); + throw deployment::DeploymentException( + // ought never occur... + OUSTR("error while getting all deployed packages: ") + m_context, + static_cast<OWeakObject *>(this), exc ); + } +} + +//______________________________________________________________________________ + + +//ToDo: the function must not call registerPackage, do this in +//XExtensionManager.reinstallDeployedExtensions +void PackageManagerImpl::reinstallDeployedPackages( + Reference<task::XAbortChannel> const & /*xAbortChannel*/, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, + CommandFailedException, CommandAbortedException, + lang::IllegalArgumentException, RuntimeException) +{ + check(); + if (office_is_running()) + throw RuntimeException( + OUSTR("You must close any running Office process before " + "reinstalling packages!"), static_cast<OWeakObject *>(this) ); + + Reference<XCommandEnvironment> xCmdEnv; + if (m_xLogFile.is()) + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); + else + xCmdEnv.set( xCmdEnv_ ); + + try { + ProgressLevel progress( + xCmdEnv, OUSTR("Reinstalling all deployed packages...") ); + + try_dispose( m_xRegistry ); + m_xRegistry.clear(); + if (m_registryCache.getLength() > 0) + erase_path( m_registryCache, xCmdEnv ); + initRegistryBackends(); + Reference<util::XUpdatable> xUpdatable( m_xRegistry, UNO_QUERY ); + if (xUpdatable.is()) + xUpdatable->update(); + + //registering is done by the ExtensionManager service. + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (CommandAbortedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (deployment::DeploymentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + logIntern( exc ); + throw deployment::DeploymentException( + OUSTR("Error while reinstalling all previously deployed " + "packages of context ") + m_context, + static_cast<OWeakObject *>(this), exc ); + } +} + + +::sal_Bool SAL_CALL PackageManagerImpl::isReadOnly( ) + throw (::com::sun::star::uno::RuntimeException) +{ + return m_readOnly; +} +bool PackageManagerImpl::synchronizeRemovedExtensions( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) +{ + + //find all which are in the extension data base but which + //are removed already. + OSL_ASSERT(!m_context.equals(OUSTR("user"))); + bool bModified = false; + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + + typedef ActivePackages::Entries::const_iterator ITActive; + bool bShared = m_context.equals(OUSTR("shared")); + + for (ITActive i = id2temp.begin(); i != id2temp.end(); ++i) + { + try + { + //Get the URL to the extensions folder, first make the url for the + //shared repository including the temporary name + OUString url = makeURL(m_activePackages, i->second.temporaryName); + if (bShared) + url = makeURLAppendSysPathSegment( url + OUSTR("_"), i->second.fileName); + + bool bRemoved = false; + //Check if the URL to the extension is still the same + ::ucbhelper::Content contentExtension; + + if (!create_ucb_content( + &contentExtension, url, + Reference<XCommandEnvironment>(), false)) + { + bRemoved = true; + } + + //The folder is in the extension database, but it can still be deleted. + //look for the xxx.tmpremoved file + //There can also be the case that a different extension was installed + //in a "temp" folder with name that is already used. + if (!bRemoved && bShared) + { + ::ucbhelper::Content contentRemoved; + + if (create_ucb_content( + &contentRemoved, + m_activePackages_expanded + OUSTR("/") + + i->second.temporaryName + OUSTR("removed"), + Reference<XCommandEnvironment>(), false)) + { + bRemoved = true; + } + } + + if (!bRemoved) + { + //There may be another extensions at the same place + dp_misc::DescriptionInfoset infoset = + dp_misc::getDescriptionInfoset(url); + OSL_ENSURE(infoset.hasDescription() && infoset.getIdentifier(), + "Extension Manager: bundled and shared extensions " + "must have an identifer and a version"); + if (infoset.hasDescription() && + infoset.getIdentifier() && + (! i->first.equals(*(infoset.getIdentifier())) + || ! i->second.version.equals(infoset.getVersion()))) + { + bRemoved = true; + } + + } + if (bRemoved) + { + Reference<deployment::XPackage> xPackage = m_xRegistry->bindPackage( + url, i->second.mediaType, true, i->first, xCmdEnv ); + OSL_ASSERT(xPackage.is()); //Even if the files are removed, we must get the object. + xPackage->revokePackage(xAbortChannel, xCmdEnv); + removePackage(xPackage->getIdentifier().Value, xPackage->getName(), + xAbortChannel, xCmdEnv); + bModified |= true; + } + } + catch( uno::Exception & ) + { + OSL_ASSERT(0); + } + } + return bModified; +} + + +bool PackageManagerImpl::synchronizeAddedExtensions( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) +{ + bool bModified = false; + OSL_ASSERT(!m_context.equals(OUSTR("user"))); + + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + //check if the folder exist at all. The shared extension folder + //may not exist for a normal user. + if (!create_ucb_content( + NULL, m_activePackages_expanded, Reference<css::ucb::XCommandEnvironment>(), false)) + return bModified; + ::ucbhelper::Content tempFolder( + m_activePackages_expanded, xCmdEnv ); + + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_FOLDERS_ONLY ) ); + + while (xResultSet->next()) + { + try + { + OUString title( + Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString( + 1 /* Title */ ) ); + //The temporary folders of user and shared have an '_' at then end. + //But the name in ActivePackages.temporaryName is saved without. + OUString title2 = title; + bool bShared = m_context.equals(OUSTR("shared")); + if (bShared) + { + OSL_ASSERT(title2[title2.getLength() -1] == '_'); + title2 = title2.copy(0, title2.getLength() -1); + } + OUString titleEncoded = ::rtl::Uri::encode( + title2, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8); + + //It it sufficient to check for the folder name, because when the administor + //installed the extension it was already checked if there is one with the + //same identifier. + const MatchTempDir match(titleEncoded); + if (::std::find_if( id2temp.begin(), id2temp.end(), match ) == + id2temp.end()) + { + + // The folder was not found in the data base, so it must be + // an added extension + OUString url(m_activePackages_expanded + OUSTR("/") + titleEncoded); + OUString sExtFolder; + if (bShared) //that is, shared + { + //Check if the extension was not "deleted" already which is indicated + //by a xxx.tmpremoved file + ::ucbhelper::Content contentRemoved; + if (create_ucb_content(&contentRemoved, url + OUSTR("removed"), + Reference<XCommandEnvironment>(), false)) + continue; + sExtFolder = getExtensionFolder( + m_activePackages_expanded + + OUString(OUSTR("/")) + titleEncoded + OUSTR("_"), xCmdEnv); + url = makeURLAppendSysPathSegment(m_activePackages_expanded, title); + url = makeURLAppendSysPathSegment(url, sExtFolder); + } + Reference<deployment::XPackage> xPackage = m_xRegistry->bindPackage( + url, OUString(), false, OUString(), xCmdEnv ); + if (xPackage.is()) + { + //Prepare the database entry + ActivePackages::Data dbData; + + dbData.temporaryName = titleEncoded; + if (bShared) + dbData.fileName = sExtFolder; + else + dbData.fileName = title; + dbData.mediaType = xPackage->getPackageType()->getMediaType(); + dbData.version = xPackage->getVersion(); + OSL_ENSURE(dbData.version.getLength() > 0, + "Extension Manager: bundled and shared extensions must have " + "an identifier and a version"); + + OUString id = dp_misc::getIdentifier( xPackage ); + + //We provide a special command environment that will prevent + //showing a license if simple-licens/@accept-by = "admin" + //It will also prevent showing the license for bundled extensions + //which is not supported. + OSL_ASSERT(!m_context.equals(OUSTR("user"))); + + // shall the license be suppressed? + DescriptionInfoset info = + dp_misc::getDescriptionInfoset(url); + ::boost::optional<dp_misc::SimpleLicenseAttributes> + attr = info.getSimpleLicenseAttributes(); + ExtensionProperties props(url,xCmdEnv); + bool bNoLicense = false; + if (attr && attr->suppressIfRequired && props.isSuppressedLicense()) + bNoLicense = true; + + Reference<ucb::XCommandEnvironment> licCmdEnv( + new LicenseCommandEnv(xCmdEnv->getInteractionHandler(), + bNoLicense, m_context)); + sal_Int32 failedPrereq = xPackage->checkPrerequisites( + xAbortChannel, licCmdEnv, false); + //Remember that this failed. For example, the user + //could have declined the license. Then the next time the + //extension folder is investigated we do not want to + //try to install the extension again. + dbData.failedPrerequisites = OUString::valueOf(failedPrereq); + insertToActivationLayerDB(id, dbData); + bModified |= true; + } + } + } + catch (uno::Exception &) + { + OSL_ASSERT(0); + } + } + return bModified; +} + +sal_Bool PackageManagerImpl::synchronize( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException) +{ + check(); + bool bModified = false; + if (m_context.equals(OUSTR("user"))) + return bModified; + bModified |= + synchronizeRemovedExtensions(xAbortChannel, xCmdEnv); + bModified |= synchronizeAddedExtensions(xAbortChannel, xCmdEnv); + + return bModified; +} + +Sequence< Reference<deployment::XPackage> > PackageManagerImpl::getExtensionsWithUnacceptedLicenses( + Reference<ucb::XCommandEnvironment> const & xCmdEnv) + throw (deployment::DeploymentException, RuntimeException) +{ + ::std::vector<Reference<deployment::XPackage> > vec; + + try + { + const ::osl::MutexGuard guard( getMutex() ); + // clean up activation layer, scan for zombie temp dirs: + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + + ActivePackages::Entries::const_iterator i = id2temp.begin(); + bool bShared = m_context.equals(OUSTR("shared")); + + for (; i != id2temp.end(); ++i ) + { + //Get the database entry + ActivePackages::Data const & dbData = i->second; + sal_Int32 failedPrereq = dbData.failedPrerequisites.toInt32(); + //If the installation failed for other reason then the license then we + //ignore it. + if (failedPrereq ^= deployment::Prerequisites::LICENSE) + continue; + + //Prepare the URL to the extension + OUString url = makeURL(m_activePackages, i->second.temporaryName); + if (bShared) + url = makeURLAppendSysPathSegment( url + OUSTR("_"), i->second.fileName); + + Reference<deployment::XPackage> p = m_xRegistry->bindPackage( + url, OUString(), false, OUString(), xCmdEnv ); + + if (p.is()) + vec.push_back(p); + + } + return ::comphelper::containerToSequence(vec); + } + catch (deployment::DeploymentException &) + { + throw; + } + catch (RuntimeException&) + { + throw; + } + catch (...) + { + Any exc = ::cppu::getCaughtException(); + deployment::DeploymentException de( + OUSTR("PackageManagerImpl::getExtensionsWithUnacceptedLicenses"), + static_cast<OWeakObject*>(this), exc); + exc <<= de; + ::cppu::throwException(exc); + } + + return ::comphelper::containerToSequence(vec); +} + +sal_Int32 PackageManagerImpl::checkPrerequisites( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException) +{ + try + { + if (!extension.is()) + return 0; + if (!m_context.equals(extension->getRepositoryName())) + throw lang::IllegalArgumentException( + OUSTR("PackageManagerImpl::checkPrerequisites: extension is not" + " from this repository."), 0, 0); + + ActivePackages::Data dbData; + OUString id = dp_misc::getIdentifier(extension); + if (m_activePackagesDB->get( &dbData, id, OUString())) + { + //If the license was already displayed, then do not show it again + Reference<ucb::XCommandEnvironment> _xCmdEnv = xCmdEnv; + sal_Int32 prereq = dbData.failedPrerequisites.toInt32(); + if ( !(prereq & deployment::Prerequisites::LICENSE)) + _xCmdEnv = new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler()); + + sal_Int32 failedPrereq = extension->checkPrerequisites( + xAbortChannel, _xCmdEnv, false); + dbData.failedPrerequisites = OUString::valueOf(failedPrereq); + insertToActivationLayerDB(id, dbData); + } + else + { + throw lang::IllegalArgumentException( + OUSTR("PackageManagerImpl::checkPrerequisites: unknown extension"), + 0, 0); + + } + return 0; + } + catch (deployment::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any excOccurred = ::cppu::getCaughtException(); + deployment::DeploymentException exc( + OUSTR("PackageManagerImpl::checkPrerequisites: exception "), + static_cast<OWeakObject*>(this), excOccurred); + throw exc; + } +} + + +//______________________________________________________________________________ +PackageManagerImpl::CmdEnvWrapperImpl::~CmdEnvWrapperImpl() +{ +} + +//______________________________________________________________________________ +PackageManagerImpl::CmdEnvWrapperImpl::CmdEnvWrapperImpl( + Reference<XCommandEnvironment> const & xUserCmdEnv, + Reference<XProgressHandler> const & xLogFile ) + : m_xLogFile( xLogFile ) +{ + if (xUserCmdEnv.is()) { + m_xUserProgress.set( xUserCmdEnv->getProgressHandler() ); + m_xUserInteractionHandler.set( xUserCmdEnv->getInteractionHandler() ); + } +} + +// XCommandEnvironment +//______________________________________________________________________________ +Reference<task::XInteractionHandler> +PackageManagerImpl::CmdEnvWrapperImpl::getInteractionHandler() + throw (RuntimeException) +{ + return m_xUserInteractionHandler; +} + +//______________________________________________________________________________ +Reference<XProgressHandler> +PackageManagerImpl::CmdEnvWrapperImpl::getProgressHandler() + throw (RuntimeException) +{ + return this; +} + +// XProgressHandler +//______________________________________________________________________________ +void PackageManagerImpl::CmdEnvWrapperImpl::push( Any const & Status ) + throw (RuntimeException) +{ + if (m_xLogFile.is()) + m_xLogFile->push( Status ); + if (m_xUserProgress.is()) + m_xUserProgress->push( Status ); +} + +//______________________________________________________________________________ +void PackageManagerImpl::CmdEnvWrapperImpl::update( Any const & Status ) + throw (RuntimeException) +{ + if (m_xLogFile.is()) + m_xLogFile->update( Status ); + if (m_xUserProgress.is()) + m_xUserProgress->update( Status ); +} + +//______________________________________________________________________________ +void PackageManagerImpl::CmdEnvWrapperImpl::pop() throw (RuntimeException) +{ + if (m_xLogFile.is()) + m_xLogFile->pop(); + if (m_xUserProgress.is()) + m_xUserProgress->pop(); +} + +} // namespace dp_manager + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_manager.h b/desktop/source/deployment/manager/dp_manager.h new file mode 100755 index 000000000000..3b335d7e2362 --- /dev/null +++ b/desktop/source/deployment/manager/dp_manager.h @@ -0,0 +1,296 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_MANAGER_H +#define INCLUDED_DP_MANAGER_H + +#include "dp_manager.hrc" +#include "dp_misc.h" +#include "dp_interact.h" +#include "dp_activepackages.hxx" +#include "rtl/ref.hxx" +#include "cppuhelper/compbase1.hxx" +#include "cppuhelper/implbase2.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/deployment/XPackageRegistry.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include <memory> + + +namespace css = ::com::sun::star; + +namespace dp_manager { + +typedef ::cppu::WeakComponentImplHelper1< + css::deployment::XPackageManager > t_pm_helper; + +//============================================================================== +class PackageManagerImpl : private ::dp_misc::MutexHolder, public t_pm_helper +{ + css::uno::Reference<css::uno::XComponentContext> m_xComponentContext; + ::rtl::OUString m_context; + ::rtl::OUString m_registrationData; + ::rtl::OUString m_registrationData_expanded; + ::rtl::OUString m_registryCache; + bool m_readOnly; + + ::rtl::OUString m_activePackages; + ::rtl::OUString m_activePackages_expanded; + ::std::auto_ptr< ActivePackages > m_activePackagesDB; + //This mutex is only used for synchronization in addPackage + ::osl::Mutex m_addMutex; + css::uno::Reference<css::ucb::XProgressHandler> m_xLogFile; + inline void logIntern( css::uno::Any const & status ); + void fireModified(); + + css::uno::Reference<css::deployment::XPackageRegistry> m_xRegistry; + + void initRegistryBackends(); + void initActivationLayer( + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ); + ::rtl::OUString detectMediaType( + ::ucbhelper::Content const & ucbContent, bool throw_exc = true ); + ::rtl::OUString insertToActivationLayer( + css::uno::Sequence<css::beans::NamedValue> const & properties, + ::rtl::OUString const & mediaType, + ::ucbhelper::Content const & sourceContent, + ::rtl::OUString const & title, ActivePackages::Data * dbData ); + void insertToActivationLayerDB( + ::rtl::OUString const & id, ActivePackages::Data const & dbData ); + + void deletePackageFromCache( + css::uno::Reference<css::deployment::XPackage> const & xPackage, + ::rtl::OUString const & destFolder ); + + bool isInstalled( + css::uno::Reference<css::deployment::XPackage> const & package); + + bool synchronizeRemovedExtensions( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + bool synchronizeAddedExtensions( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + class CmdEnvWrapperImpl + : public ::cppu::WeakImplHelper2< css::ucb::XCommandEnvironment, + css::ucb::XProgressHandler > + { + css::uno::Reference<css::ucb::XProgressHandler> m_xLogFile; + css::uno::Reference<css::ucb::XProgressHandler> m_xUserProgress; + css::uno::Reference<css::task::XInteractionHandler> + m_xUserInteractionHandler; + + public: + virtual ~CmdEnvWrapperImpl(); + CmdEnvWrapperImpl( + css::uno::Reference<css::ucb::XCommandEnvironment> + const & xUserCmdEnv, + css::uno::Reference<css::ucb::XProgressHandler> const & xLogFile ); + + // XCommandEnvironment + virtual css::uno::Reference<css::task::XInteractionHandler> SAL_CALL + getInteractionHandler() throw (css::uno::RuntimeException); + virtual css::uno::Reference<css::ucb::XProgressHandler> SAL_CALL + getProgressHandler() throw (css::uno::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( css::uno::Any const & Status ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL update( css::uno::Any const & Status ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL pop() throw (css::uno::RuntimeException); + }; + +protected: + inline void check(); + virtual void SAL_CALL disposing(); + + virtual ~PackageManagerImpl(); + inline PackageManagerImpl( + css::uno::Reference<css::uno::XComponentContext> + const & xComponentContext, ::rtl::OUString const & context ) + : t_pm_helper( getMutex() ), + m_xComponentContext( xComponentContext ), + m_context( context ), + m_readOnly( true ) + {} + +public: + static css::uno::Reference<css::deployment::XPackageManager> create( + css::uno::Reference<css::uno::XComponentContext> + const & xComponentContext, ::rtl::OUString const & context ); + + // XComponent + virtual void SAL_CALL dispose() throw (css::uno::RuntimeException); + virtual void SAL_CALL addEventListener( + css::uno::Reference<css::lang::XEventListener> const & xListener ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( + css::uno::Reference<css::lang::XEventListener> const & xListener ) + throw (css::uno::RuntimeException); + + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + + // XPackageManager + virtual ::rtl::OUString SAL_CALL getContext() + throw (css::uno::RuntimeException); + virtual css::uno::Sequence< + css::uno::Reference<css::deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::task::XAbortChannel> SAL_CALL + createAbortChannel() throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL addPackage( + ::rtl::OUString const & url, + css::uno::Sequence<css::beans::NamedValue> const & properties, + ::rtl::OUString const & mediaType, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL importExtension( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL removePackage( + ::rtl::OUString const & id, ::rtl::OUString const & fileName, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + ::rtl::OUString getDeployPath( ActivePackages::Data const & data ); + css::uno::Reference<css::deployment::XPackage> SAL_CALL getDeployedPackage_( + ::rtl::OUString const & id, ::rtl::OUString const & fileName, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ); + css::uno::Reference<css::deployment::XPackage> getDeployedPackage_( + ::rtl::OUString const & id, ActivePackages::Data const & data, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool ignoreAlienPlatforms = false ); + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL + getDeployedPackage( + ::rtl::OUString const & id, ::rtl::OUString const & fileName, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::lang::IllegalArgumentException, css::uno::RuntimeException); + + css::uno::Sequence< css::uno::Reference<css::deployment::XPackage> > + getDeployedPackages_( + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ); + virtual css::uno::Sequence< css::uno::Reference<css::deployment::XPackage> > + SAL_CALL getDeployedPackages( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL reinstallDeployedPackages( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual ::sal_Bool SAL_CALL isReadOnly( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::sal_Bool SAL_CALL synchronize( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException); + + virtual css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > SAL_CALL + getExtensionsWithUnacceptedLicenses( + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) + throw (css::deployment::DeploymentException, + css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL checkPrerequisites( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + }; + +//______________________________________________________________________________ +inline void PackageManagerImpl::check() +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) + throw css::lang::DisposedException( + OUSTR("PackageManager instance has already been disposed!"), + static_cast< ::cppu::OWeakObject * >(this) ); +} + +//______________________________________________________________________________ +inline void PackageManagerImpl::logIntern( css::uno::Any const & status ) +{ + if (m_xLogFile.is()) + m_xLogFile->update( status ); +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_manager.hrc b/desktop/source/deployment/manager/dp_manager.hrc new file mode 100755 index 000000000000..6131cc381abf --- /dev/null +++ b/desktop/source/deployment/manager/dp_manager.hrc @@ -0,0 +1,39 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_MANAGER_HRC +#define INCLUDED_DP_MANAGER_HRC + +#include "deployment.hrc" + +#define RID_STR_ERROR_WHILE_ADDING (RID_DEPLOYMENT_MANAGER_START+0) +#define RID_STR_ERROR_WHILE_REMOVING (RID_DEPLOYMENT_MANAGER_START+1) +#define RID_STR_PACKAGE_ALREADY_ADDED (RID_DEPLOYMENT_MANAGER_START+2) +#define RID_STR_COPYING_PACKAGE (RID_DEPLOYMENT_MANAGER_START+3) +#define RID_STR_NO_SUCH_PACKAGE (RID_DEPLOYMENT_MANAGER_START+4) +#define RID_STR_SYNCHRONIZING_REPOSITORY (RID_DEPLOYMENT_MANAGER_START+5) +#endif diff --git a/desktop/source/deployment/manager/dp_manager.src b/desktop/source/deployment/manager/dp_manager.src new file mode 100644 index 000000000000..7d38b880c37a --- /dev/null +++ b/desktop/source/deployment/manager/dp_manager.src @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_manager.hrc" + + +String RID_STR_COPYING_PACKAGE +{ + Text [ en-US ] = "Copying: "; +}; + +String RID_STR_ERROR_WHILE_ADDING +{ + Text [ en-US ] = "Error while adding: "; +}; + +String RID_STR_ERROR_WHILE_REMOVING +{ + Text [ en-US ] = "Error while removing: "; +}; + +String RID_STR_PACKAGE_ALREADY_ADDED +{ + Text [ en-US ] = "Extension has already been added: "; +}; + +String RID_STR_NO_SUCH_PACKAGE +{ + Text [ en-US ] = "There is no such extension deployed: "; +}; + +String RID_STR_SYNCHRONIZING_REPOSITORY +{ + Text [ en-US ] = "Synchronizing repository for %NAME extensions"; +}; diff --git a/desktop/source/deployment/manager/dp_managerfac.cxx b/desktop/source/deployment/manager/dp_managerfac.cxx new file mode 100644 index 000000000000..d84abbf0f926 --- /dev/null +++ b/desktop/source/deployment/manager/dp_managerfac.cxx @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_manager.h" +#include "dp_resource.h" +#include "cppuhelper/compbase1.hxx" +#include "comphelper/servicedecl.hxx" +#include "com/sun/star/deployment/thePackageManagerFactory.hpp" + + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace dp_manager { +namespace factory { + +typedef ::cppu::WeakComponentImplHelper1< + deployment::XPackageManagerFactory > t_pmfac_helper; + +//============================================================================== +class PackageManagerFactoryImpl : private MutexHolder, public t_pmfac_helper +{ + Reference<XComponentContext> m_xComponentContext; + + Reference<deployment::XPackageManager> m_xUserMgr; + Reference<deployment::XPackageManager> m_xSharedMgr; + Reference<deployment::XPackageManager> m_xBundledMgr; + typedef ::boost::unordered_map< + OUString, WeakReference<deployment::XPackageManager>, + ::rtl::OUStringHash > t_string2weakref; + t_string2weakref m_managers; + +protected: + inline void check(); + virtual void SAL_CALL disposing(); + +public: + virtual ~PackageManagerFactoryImpl(); + PackageManagerFactoryImpl( + Reference<XComponentContext> const & xComponentContext ); + + // XPackageManagerFactory + virtual Reference<deployment::XPackageManager> SAL_CALL getPackageManager( + OUString const & context ) throw (RuntimeException); +}; + +//============================================================================== +namespace sdecl = comphelper::service_decl; +sdecl::class_<PackageManagerFactoryImpl> servicePMFI; +extern sdecl::ServiceDecl const serviceDecl( + servicePMFI, + // a private one: + "com.sun.star.comp.deployment.PackageManagerFactory", + "com.sun.star.comp.deployment.PackageManagerFactory" ); + +//============================================================================== +bool singleton_entries( + Reference<registry::XRegistryKey> const & xRegistryKey ) +{ + try { + Reference<registry::XRegistryKey> xKey( + xRegistryKey->createKey( + serviceDecl.getImplementationName() + + // xxx todo: use future generated function to get singleton name + OUSTR("/UNO/SINGLETONS/" + "com.sun.star.deployment.thePackageManagerFactory") ) ); + xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] ); + return true; + } + catch (registry::InvalidRegistryException & exc) { + (void) exc; // avoid warnings + OSL_FAIL( ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + return false; + } +} + +//______________________________________________________________________________ +PackageManagerFactoryImpl::PackageManagerFactoryImpl( + Reference<XComponentContext> const & xComponentContext ) + : t_pmfac_helper( getMutex() ), + m_xComponentContext( xComponentContext ) +{ +} + +//______________________________________________________________________________ +PackageManagerFactoryImpl::~PackageManagerFactoryImpl() +{ +} + +//______________________________________________________________________________ +inline void PackageManagerFactoryImpl::check() +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) + { + throw lang::DisposedException( + OUSTR("PackageManagerFactory instance has already been disposed!"), + static_cast<OWeakObject *>(this) ); + } +} + +//______________________________________________________________________________ +void PackageManagerFactoryImpl::disposing() +{ + // dispose all managers: + ::osl::MutexGuard guard( getMutex() ); + t_string2weakref::const_iterator iPos( m_managers.begin() ); + t_string2weakref::const_iterator const iEnd( m_managers.end() ); + for ( ; iPos != iEnd; ++iPos ) + try_dispose( iPos->second ); + m_managers = t_string2weakref(); + // the below are already disposed: + m_xUserMgr.clear(); + m_xSharedMgr.clear(); + m_xBundledMgr.clear(); +} + +// XPackageManagerFactory +//______________________________________________________________________________ +Reference<deployment::XPackageManager> +PackageManagerFactoryImpl::getPackageManager( OUString const & context ) + throw (RuntimeException) +{ + Reference< deployment::XPackageManager > xRet; + ::osl::ResettableMutexGuard guard( getMutex() ); + check(); + t_string2weakref::const_iterator const iFind( m_managers.find( context ) ); + if (iFind != m_managers.end()) { + xRet = iFind->second; + if (xRet.is()) + return xRet; + } + + guard.clear(); + xRet.set( PackageManagerImpl::create( m_xComponentContext, context ) ); + guard.reset(); + ::std::pair< t_string2weakref::iterator, bool > insertion( + m_managers.insert( t_string2weakref::value_type( context, xRet ) ) ); + if (insertion.second) + { + OSL_ASSERT( insertion.first->second.get() == xRet ); + // hold user, shared mgrs for whole process: live deployment + if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("user") )) + m_xUserMgr = xRet; + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) + m_xSharedMgr = xRet; + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled") )) + m_xBundledMgr = xRet; + } + else + { + Reference< deployment::XPackageManager > xAlreadyIn( + insertion.first->second ); + if (xAlreadyIn.is()) + { + guard.clear(); + try_dispose( xRet ); + xRet = xAlreadyIn; + } + else + { + insertion.first->second = xRet; + } + } + return xRet; +} + +} // namespace factory +} // namespace dp_manager + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_properties.cxx b/desktop/source/deployment/manager/dp_properties.cxx new file mode 100644 index 000000000000..a2a568287f16 --- /dev/null +++ b/desktop/source/deployment/manager/dp_properties.cxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "xmlscript/xml_helper.hxx" +#include "ucbhelper/content.hxx" +#include <list> + +#include "dp_ucb.h" +#include "rtl/ustrbuf.hxx" +#include "dp_properties.hxx" + +namespace lang = com::sun::star::lang; +namespace task = com::sun::star::task; +namespace ucb = com::sun::star::ucb; +namespace uno = com::sun::star::uno; +namespace css = com::sun::star; + +#define OUSTR(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +#define PROP_SUPPRESS_LICENSE "SUPPRESS_LICENSE" +#define PROP_EXTENSION_UPDATE "EXTENSION_UPDATE" + +namespace dp_manager { + +//Reading the file +ExtensionProperties::ExtensionProperties( + OUString const & urlExtension, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) : + m_xCmdEnv(xCmdEnv) +{ + m_propFileUrl = urlExtension + OUSTR("properties"); + + ::std::list< ::std::pair< OUString, OUString> > props; + if (! dp_misc::create_ucb_content(NULL, m_propFileUrl, 0, false)) + return; + + ::ucbhelper::Content contentProps(m_propFileUrl, m_xCmdEnv); + dp_misc::readProperties(props, contentProps); + + typedef ::std::list< ::std::pair< OUString, OUString> >::const_iterator CI; + for (CI i = props.begin(); i != props.end(); i++) + { + if (i->first.equals(OUSTR(PROP_SUPPRESS_LICENSE))) + m_prop_suppress_license = i->second; + } +} + +//Writing the file +ExtensionProperties::ExtensionProperties( + OUString const & urlExtension, + uno::Sequence<css::beans::NamedValue> const & properties, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) : + m_xCmdEnv(xCmdEnv) +{ + m_propFileUrl = urlExtension + OUSTR("properties"); + + for (sal_Int32 i = 0; i < properties.getLength(); i++) + { + css::beans::NamedValue const & v = properties[i]; + if (v.Name.equals(OUSTR(PROP_SUPPRESS_LICENSE))) + { + m_prop_suppress_license = getPropertyValue(v); + } + else if (v.Name.equals(OUSTR(PROP_EXTENSION_UPDATE))) + { + m_prop_extension_update = getPropertyValue(v); + } + else + { + throw lang::IllegalArgumentException( + OUSTR("Extension Manager: unknown property"), 0, -1); + } + } +} + +OUString ExtensionProperties::getPropertyValue(css::beans::NamedValue const & v) +{ + OUString value(OUSTR("0")); + if (v.Value >>= value) + { + if (value.equals(OUSTR("1"))) + value = OUSTR("1"); + } + else + { + throw lang::IllegalArgumentException( + OUSTR("Extension Manager: wrong property value"), 0, -1); + } + return value; +} +void ExtensionProperties::write() +{ + ::ucbhelper::Content contentProps(m_propFileUrl, m_xCmdEnv); + ::rtl::OUStringBuffer buf; + + if (m_prop_suppress_license) + { + buf.append(OUSTR(PROP_SUPPRESS_LICENSE)); + buf.append(OUSTR("=")); + buf.append(*m_prop_suppress_license); + } + + ::rtl::OString stamp = ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_UTF8); + Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(stamp.getStr()), + stamp.getLength() ) ) ); + contentProps.writeStream( xData, true /* replace existing */ ); +} + +bool ExtensionProperties::isSuppressedLicense() +{ + bool ret = false; + if (m_prop_suppress_license) + { + if (m_prop_suppress_license->equals(OUSTR("1"))) + ret = true; + } + return ret; +} + +bool ExtensionProperties::isExtensionUpdate() +{ + bool ret = false; + if (m_prop_extension_update) + { + if (m_prop_extension_update->equals(OUSTR("1"))) + ret = true; + } + return ret; +} + +} // namespace dp_manager + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_properties.hxx b/desktop/source/deployment/manager/dp_properties.hxx new file mode 100644 index 000000000000..103227f29226 --- /dev/null +++ b/desktop/source/deployment/manager/dp_properties.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_PROPERTIES_HXX +#define INCLUDED_DP_PROPERTIES_HXX + + + +#include "com/sun/star/beans/NamedValue.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "boost/optional.hpp" + + +namespace css = ::com::sun::star; + +namespace dp_manager { + + + +/** + + */ +class ExtensionProperties +{ +protected: + ::rtl::OUString m_propFileUrl; + const css::uno::Reference<css::ucb::XCommandEnvironment> m_xCmdEnv; + ::boost::optional< ::rtl::OUString> m_prop_suppress_license; + ::boost::optional< ::rtl::OUString> m_prop_extension_update; + + ::rtl::OUString getPropertyValue(css::beans::NamedValue const & v); +public: + + virtual ~ExtensionProperties() {}; + ExtensionProperties(::rtl::OUString const & urlExtension, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + ExtensionProperties(::rtl::OUString const & urlExtension, + css::uno::Sequence<css::beans::NamedValue> const & properties, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + void write(); + + bool isSuppressedLicense(); + + bool isExtensionUpdate(); +}; +} + + + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/makefile.mk b/desktop/source/deployment/manager/makefile.mk new file mode 100755 index 000000000000..022f5e27e554 --- /dev/null +++ b/desktop/source/deployment/manager/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_manager +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +CFLAGS+= $(SYSTEM_DB_CFLAGS) + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_manager.src + +SLOFILES = \ + $(SLO)$/dp_activepackages.obj \ + $(SLO)$/dp_manager.obj \ + $(SLO)$/dp_managerfac.obj \ + $(SLO)$/dp_informationprovider.obj \ + $(SLO)$/dp_extensionmanager.obj \ + $(SLO)$/dp_commandenvironments.obj \ + $(SLO)$/dp_properties.obj + +.INCLUDE : ..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/misc/db.cxx b/desktop/source/deployment/misc/db.cxx new file mode 100644 index 000000000000..909f12f79e18 --- /dev/null +++ b/desktop/source/deployment/misc/db.cxx @@ -0,0 +1,273 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <db.hxx> + +#include <rtl/alloc.h> +#include <cstring> +#include <errno.h> + +namespace berkeleydbproxy { + +//---------------------------------------------------------------------------- + namespace db_internal + { + static void raise_error(int dberr, const char * where); + + static inline int check_error(int dberr, const char * where) + { + if (dberr) raise_error(dberr,where); + return dberr; + } + } + +//---------------------------------------------------------------------------- + +char *DbEnv::strerror(int error) { + return (db_strerror(error)); +} + +//---------------------------------------------------------------------------- + +Db::Db(DbEnv* pDbenv,u_int32_t flags) +: m_pDBP(0) +{ + db_internal::check_error( db_create(&m_pDBP,pDbenv ? pDbenv->m_pDBENV:0,flags),"Db::Db" ); +} + + +Db::~Db() +{ + if (m_pDBP) + { + // should not happen + // TODO: add assert + } + +} + + +int Db::close(u_int32_t flags) +{ + int error = m_pDBP->close(m_pDBP,flags); + m_pDBP = 0; + return db_internal::check_error(error,"Db::close"); +} + +int Db::open(DB_TXN *txnid, + const char *file, + const char *database, + DBTYPE type, + u_int32_t flags, + int mode) +{ + int err = m_pDBP->open(m_pDBP,txnid,file,database,type,flags,mode); + return db_internal::check_error( err,"Db::open" ); +} + + +int Db::get(DB_TXN *txnid, Dbt *key, Dbt *data, u_int32_t flags) +{ + int err = m_pDBP->get(m_pDBP,txnid,key,data,flags); + + // these are non-exceptional outcomes + if (err != DB_NOTFOUND && err != DB_KEYEMPTY) + db_internal::check_error( err,"Db::get" ); + + return err; +} + +int Db::put(DB_TXN* txnid, Dbt *key, Dbt *data, u_int32_t flags) +{ + int err = m_pDBP->put(m_pDBP,txnid,key,data,flags); + + if (err != DB_KEYEXIST) // this is a non-exceptional outcome + db_internal::check_error( err,"Db::put" ); + return err; +} + +int Db::cursor(DB_TXN *txnid, Dbc **cursorp, u_int32_t flags) +{ + DBC * dbc = 0; + int error = m_pDBP->cursor(m_pDBP,txnid,&dbc,flags); + + if (!db_internal::check_error(error,"Db::cursor")) + *cursorp = new Dbc(dbc); + + return error; +} + + +#define DB_INCOMPLETE (-30999)/* Sync didn't finish. */ + +int Db::sync(u_int32_t flags) +{ + int err; + DB *db = m_pDBP; + + if (!db) { + db_internal::check_error(EINVAL,"Db::sync"); + return (EINVAL); + } + if ((err = db->sync(db, flags)) != 0 && err != DB_INCOMPLETE) { + db_internal::check_error(err, "Db::sync"); + return (err); + } + return (err); +} + +int Db::del(Dbt *key, u_int32_t flags) +{ + DB *db = m_pDBP; + int err; + + if ((err = db->del(db, 0, key, flags)) != 0) { + // DB_NOTFOUND is a "normal" return, so should not be + // thrown as an error + if (err != DB_NOTFOUND) { + db_internal::check_error(err, "Db::del"); + return (err); + } + } + return (err); +} + +//---------------------------------------------------------------------------- + +Dbc::Dbc(DBC * dbc) +: m_pDBC(dbc) +{ +} + +Dbc::~Dbc() +{ +} + +int Dbc::close() +{ + int err = m_pDBC->c_close(m_pDBC); + delete this; + return db_internal::check_error( err,"Dbcursor::close" ); +} + +int Dbc::get(Dbt *key, Dbt *data, u_int32_t flags) +{ + int err = m_pDBC->c_get(m_pDBC,key,data,flags); + + // these are non-exceptional outcomes + if (err != DB_NOTFOUND && err != DB_KEYEMPTY) + db_internal::check_error( err, "Dbcursor::get" ); + + return err; +} + +//---------------------------------------------------------------------------- + +Dbt::Dbt() +{ + using namespace std; + DBT * thispod = this; + memset(thispod, 0, sizeof *thispod); +} + + +Dbt::Dbt(void *data_arg, u_int32_t size_arg) +{ + using namespace std; + DBT * thispod = this; + memset(thispod, 0, sizeof *thispod); + this->set_data(data_arg); + this->set_size(size_arg); +} + +Dbt::Dbt(const Dbt & other) +{ + using namespace std; + const DBT *otherpod = &other; + DBT *thispod = this; + memcpy(thispod, otherpod, sizeof *thispod); +} + +Dbt& Dbt::operator = (const Dbt & other) +{ + if (this != &other) + { + using namespace std; + const DBT *otherpod = &other; + DBT *thispod = this; + memcpy(thispod, otherpod, sizeof *thispod); + } + return *this; +} + +Dbt::~Dbt() +{ +} + +void * Dbt::get_data() const +{ + return this->data; +} + +void Dbt::set_data(void *value) +{ + this->data = value; +} + +u_int32_t Dbt::get_size() const +{ + return this->size; +} + +void Dbt::set_size(u_int32_t value) +{ + this->size = value; +} + +//---------------------------------------------------------------------------- +void db_internal::raise_error(int dberr, const char * where) +{ + if (!where) where = "<unknown>"; + + const char * dberrmsg = db_strerror(dberr); + if (!dberrmsg || !*dberrmsg) dberrmsg = "<unknown DB error>"; + + rtl::OString msg = where; + msg += ": "; + msg += dberrmsg; + + throw DbException(msg); +} + +//---------------------------------------------------------------------------- +} // namespace ecomp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_dependencies.cxx b/desktop/source/deployment/misc/dp_dependencies.cxx new file mode 100644 index 000000000000..6b937547ae93 --- /dev/null +++ b/desktop/source/deployment/misc/dp_dependencies.cxx @@ -0,0 +1,180 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "sal/config.h" + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/xml/dom/XElement.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" +#include "com/sun/star/xml/dom/XNodeList.hpp" +#include "rtl/bootstrap.hxx" +#include "rtl/string.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "tools/string.hxx" + +#include "deployment.hrc" +#include "dp_resource.h" + +#include "dp_dependencies.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_version.hxx" + +namespace { + +namespace css = ::com::sun::star; + +static char const xmlNamespace[] = + "http://openoffice.org/extensions/description/2006"; + +bool +lcl_versionIsNot(dp_misc::Order i_eOrder, ::rtl::OUString const& i_rVersion) +{ + ::rtl::OUString aVersion( + RTL_CONSTASCII_USTRINGPARAM( + "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") + ":Version:OOOPackageVersion}")); + ::rtl::Bootstrap::expandMacros(aVersion); + return ::dp_misc::compareVersions(aVersion, i_rVersion) != i_eOrder; +} + +bool satisfiesMinimalVersion(::rtl::OUString const& i_rVersion) +{ + return lcl_versionIsNot(dp_misc::LESS, i_rVersion); +} + +bool satisfiesMaximalVersion(::rtl::OUString const& i_rVersion) +{ + return lcl_versionIsNot(dp_misc::GREATER, i_rVersion); +} + +} + +namespace dp_misc { + +namespace Dependencies { + +css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > +check(::dp_misc::DescriptionInfoset const & infoset) { + css::uno::Reference< css::xml::dom::XNodeList > deps( + infoset.getDependencies()); + ::sal_Int32 n = deps->getLength(); + css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > + unsatisfied(n); + ::sal_Int32 unsat = 0; + for (::sal_Int32 i = 0; i < n; ++i) { + static rtl::OUString const minimalVersion( + RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org-minimal-version")); + css::uno::Reference< css::xml::dom::XElement > e( + deps->item(i), css::uno::UNO_QUERY_THROW); + bool sat = false; + if (e->getNamespaceURI().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(xmlNamespace)) + && (e->getTagName() == minimalVersion)) + { + sat = satisfiesMinimalVersion( + e->getAttribute( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("value")))); + } else if (e->getNamespaceURI().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(xmlNamespace)) + && e->getTagName().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "OpenOffice.org-maximal-version"))) + { + sat = satisfiesMaximalVersion( + e->getAttribute( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("value")))); + } else if (e->hasAttributeNS( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM(xmlNamespace)), + minimalVersion)) + { + sat = satisfiesMinimalVersion( + e->getAttributeNS( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(xmlNamespace)), + minimalVersion)); + } + if (!sat) { + unsatisfied[unsat++] = e; + } + } + unsatisfied.realloc(unsat); + return unsatisfied; +} + +::rtl::OUString getErrorText( css::uno::Reference< css::xml::dom::XElement > const & dependency ) +{ + ::rtl::OUString sReason; + ::rtl::OUString sValue; + ::rtl::OUString sVersion(RTL_CONSTASCII_USTRINGPARAM("%VERSION")); + ::rtl::OUString sProductName(RTL_CONSTASCII_USTRINGPARAM("%PRODUCTNAME")); + + if ( dependency->getNamespaceURI().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( xmlNamespace ) ) + && dependency->getTagName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OpenOffice.org-minimal-version" ) ) ) + { + sValue = dependency->getAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "value" ) ) ); + sReason = ::rtl::OUString( ::String(::dp_misc::getResId(RID_DEPLYOMENT_DEPENDENCIES_MIN)) ); + } + else if ( dependency->getNamespaceURI().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( xmlNamespace ) ) + && dependency->getTagName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OpenOffice.org-maximal-version" ) ) ) + { + sValue = dependency->getAttribute( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("value") ) ); + sReason = ::rtl::OUString( ::String(::dp_misc::getResId(RID_DEPLYOMENT_DEPENDENCIES_MAX)) ); + } + else if ( dependency->hasAttributeNS( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( xmlNamespace ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenOffice.org-minimal-version" )))) + { + sValue = dependency->getAttributeNS( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( xmlNamespace ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenOffice.org-minimal-version" ) ) ); + sReason = ::rtl::OUString( ::String(::dp_misc::getResId(RID_DEPLYOMENT_DEPENDENCIES_MIN)) ); + } + else + return ::rtl::OUString( ::String(::dp_misc::getResId(RID_DEPLYOMENT_DEPENDENCIES_UNKNOWN)) ); + + if ( sValue.getLength() == 0 ) + sValue = ::rtl::OUString( ::String(::dp_misc::getResId(RID_DEPLYOMENT_DEPENDENCIES_UNKNOWN)) ); + + sal_Int32 nPos = sReason.indexOf( sVersion ); + if ( nPos >= 0 ) + sReason = sReason.replaceAt( nPos, sVersion.getLength(), sValue ); + nPos = sReason.indexOf( sProductName ); + if ( nPos >= 0 ) + sReason = sReason.replaceAt( nPos, sProductName.getLength(), BrandName::get() ); + return sReason; +} + +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_descriptioninfoset.cxx b/desktop/source/deployment/misc/dp_descriptioninfoset.cxx new file mode 100644 index 000000000000..3c6d21fe6dc6 --- /dev/null +++ b/desktop/source/deployment/misc/dp_descriptioninfoset.cxx @@ -0,0 +1,866 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_descriptioninfoset.hxx" + +#include "dp_resource.h" +#include "sal/config.h" + +#include "comphelper/sequence.hxx" +#include "comphelper/makesequence.hxx" +#include "comphelper/processfactory.hxx" +#include "boost/optional.hpp" +#include "com/sun/star/beans/Optional.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/lang/Locale.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/xml/dom/DOMException.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" +#include "com/sun/star/xml/dom/XNodeList.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/weak.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "ucbhelper/content.hxx" + +namespace { + +namespace css = ::com::sun::star; +using css::uno::Reference; +using ::rtl::OUString; + +class EmptyNodeList: public ::cppu::WeakImplHelper1< css::xml::dom::XNodeList > +{ +public: + EmptyNodeList(); + + virtual ~EmptyNodeList(); + + virtual ::sal_Int32 SAL_CALL getLength() throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::xml::dom::XNode > SAL_CALL + item(::sal_Int32 index) throw (css::uno::RuntimeException); + +private: + EmptyNodeList(EmptyNodeList &); // not defined + void operator =(EmptyNodeList &); // not defined +}; + +EmptyNodeList::EmptyNodeList() {} + +EmptyNodeList::~EmptyNodeList() {} + +::sal_Int32 EmptyNodeList::getLength() throw (css::uno::RuntimeException) { + return 0; +} + +css::uno::Reference< css::xml::dom::XNode > EmptyNodeList::item(::sal_Int32) + throw (css::uno::RuntimeException) +{ + throw css::uno::RuntimeException( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "bad EmptyNodeList com.sun.star.xml.dom.XNodeList.item call")), + static_cast< ::cppu::OWeakObject * >(this)); +} + +::rtl::OUString getNodeValue( + css::uno::Reference< css::xml::dom::XNode > const & node) +{ + OSL_ASSERT(node.is()); + try { + return node->getNodeValue(); + } catch (css::xml::dom::DOMException & e) { + throw css::uno::RuntimeException( + (::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.xml.dom.DOMException: ")) + + e.Message), + css::uno::Reference< css::uno::XInterface >()); + } +} + +/**The class uses the UCB to access the description.xml file in an + extension. The UCB must have been initialized already. It also + requires that the extension has already be unzipped to a particular + location. + */ +class ExtensionDescription +{ +public: + /**throws an exception if the description.xml is not + available, cannot be read, does not contain the expected data, + or any other error occurred. Therefore it shoult only be used with + new extensions. + + Throws com::sun::star::uno::RuntimeException, + com::sun::star::deployment::DeploymentException, + dp_registry::backend::bundle::NoDescriptionException. + */ + ExtensionDescription( + const css::uno::Reference<css::uno::XComponentContext>& xContext, + const ::rtl::OUString& installDir, + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv); + + ~ExtensionDescription(); + + css::uno::Reference<css::xml::dom::XNode> getRootElement() const + { + return m_xRoot; + } + + ::rtl::OUString getExtensionRootUrl() const + { + return m_sExtensionRootUrl; + } + + +private: + css::uno::Reference<css::xml::dom::XNode> m_xRoot; + ::rtl::OUString m_sExtensionRootUrl; +}; + +class NoDescriptionException +{ +}; + +class FileDoesNotExistFilter + : public ::cppu::WeakImplHelper2< css::ucb::XCommandEnvironment, + css::task::XInteractionHandler > + +{ + bool m_bExist; + css::uno::Reference< css::ucb::XCommandEnvironment > m_xCommandEnv; + +public: + virtual ~FileDoesNotExistFilter(); + FileDoesNotExistFilter( + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv); + + bool exist(); + // XCommandEnvironment + virtual css::uno::Reference<css::task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (css::uno::RuntimeException); + virtual css::uno::Reference<css::ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (css::uno::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); +}; + +ExtensionDescription::ExtensionDescription( + const Reference<css::uno::XComponentContext>& xContext, + const OUString& installDir, + const Reference< css::ucb::XCommandEnvironment >& xCmdEnv) +{ + try { + m_sExtensionRootUrl = installDir; + //may throw ::com::sun::star::ucb::ContentCreationException + //If there is no description.xml then ucb will start an interaction which + //brings up a dialog.We want to prevent this. Therefore we wrap the xCmdEnv + //and filter the respective exception out. + OUString sDescriptionUri(installDir + OUSTR("/description.xml")); + Reference<css::ucb::XCommandEnvironment> xFilter = + static_cast<css::ucb::XCommandEnvironment*>( + new FileDoesNotExistFilter(xCmdEnv)); + ::ucbhelper::Content descContent(sDescriptionUri, xFilter); + + //throws an com::sun::star::uno::Exception if the file is not available + Reference<css::io::XInputStream> xIn; + try + { //throws com.sun.star.ucb.InteractiveAugmentedIOException + xIn = descContent.openStream(); + } + catch (css::uno::Exception& ) + { + if ( ! static_cast<FileDoesNotExistFilter*>(xFilter.get())->exist()) + throw NoDescriptionException(); + throw; + } + if (!xIn.is()) + { + throw css::uno::Exception( + OUSTR("Could not get XInputStream for description.xml of extension ") + + sDescriptionUri, 0); + } + + //get root node of description.xml + Reference<css::xml::dom::XDocumentBuilder> xDocBuilder( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.dom.DocumentBuilder"), + xContext ), css::uno::UNO_QUERY); + if (!xDocBuilder.is()) + throw css::uno::Exception(OUSTR(" Could not create service com.sun.star.xml.dom.DocumentBuilder"), 0); + + if (xDocBuilder->isNamespaceAware() == sal_False) + { + throw css::uno::Exception( + OUSTR("Service com.sun.star.xml.dom.DocumentBuilder is not namespace aware."), 0); + } + + Reference<css::xml::dom::XDocument> xDoc = xDocBuilder->parse(xIn); + if (!xDoc.is()) + { + throw css::uno::Exception(sDescriptionUri + OUSTR(" contains data which cannot be parsed. "), 0); + } + + //check for proper root element and namespace + Reference<css::xml::dom::XElement> xRoot = xDoc->getDocumentElement(); + if (!xRoot.is()) + { + throw css::uno::Exception( + sDescriptionUri + OUSTR(" contains no root element."), 0); + } + + if ( ! xRoot->getTagName().equals(OUSTR("description"))) + { + throw css::uno::Exception( + sDescriptionUri + OUSTR(" does not contain the root element <description>."), 0); + } + + m_xRoot = Reference<css::xml::dom::XNode>( + xRoot, css::uno::UNO_QUERY_THROW); + OUString nsDescription = xRoot->getNamespaceURI(); + + //check if this namespace is supported + if ( ! nsDescription.equals(OUSTR("http://openoffice.org/extensions/description/2006"))) + { + throw css::uno::Exception(sDescriptionUri + OUSTR(" contains a root element with an unsupported namespace. "), 0); + } + } catch (css::uno::RuntimeException &) { + throw; + } catch (css::deployment::DeploymentException &) { + throw; + } catch (css::uno::Exception & e) { + css::uno::Any a(cppu::getCaughtException()); + throw css::deployment::DeploymentException( + e.Message, Reference< css::uno::XInterface >(), a); + } +} + +ExtensionDescription::~ExtensionDescription() +{ +} + +//====================================================================== +FileDoesNotExistFilter::FileDoesNotExistFilter( + const Reference< css::ucb::XCommandEnvironment >& xCmdEnv): + m_bExist(true), m_xCommandEnv(xCmdEnv) +{} + +FileDoesNotExistFilter::~FileDoesNotExistFilter() +{ +}; + +bool FileDoesNotExistFilter::exist() +{ + return m_bExist; +} + // XCommandEnvironment +Reference<css::task::XInteractionHandler > + FileDoesNotExistFilter::getInteractionHandler() throw (css::uno::RuntimeException) +{ + return static_cast<css::task::XInteractionHandler*>(this); +} + +Reference<css::ucb::XProgressHandler > + FileDoesNotExistFilter::getProgressHandler() throw (css::uno::RuntimeException) +{ + return m_xCommandEnv.is() + ? m_xCommandEnv->getProgressHandler() + : Reference<css::ucb::XProgressHandler>(); +} + +// XInteractionHandler +//If the interaction was caused by a non-existing file which is specified in the ctor +//of FileDoesNotExistFilter, then we do nothing +void FileDoesNotExistFilter::handle( + Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException) +{ + css::uno::Any request( xRequest->getRequest() ); + + css::ucb::InteractiveAugmentedIOException ioexc; + if ((request>>= ioexc) && ioexc.Code == css::ucb::IOErrorCode_NOT_EXISTING ) + { + m_bExist = false; + return; + } + Reference<css::task::XInteractionHandler> xInteraction; + if (m_xCommandEnv.is()) { + xInteraction = m_xCommandEnv->getInteractionHandler(); + } + if (xInteraction.is()) { + xInteraction->handle(xRequest); + } +} + +} + +namespace dp_misc { + +DescriptionInfoset getDescriptionInfoset(OUString const & sExtensionFolderURL) +{ + Reference< css::xml::dom::XNode > root; + Reference<css::uno::XComponentContext> context = + comphelper_getProcessComponentContext(); + OSL_ASSERT(context.is()); + try { + root = + ExtensionDescription( + context, sExtensionFolderURL, + Reference< css::ucb::XCommandEnvironment >()). + getRootElement(); + } catch (NoDescriptionException &) { + } catch (css::deployment::DeploymentException & e) { + throw css::uno::RuntimeException( + (OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.deployment.DeploymentException: ")) + + e.Message), 0); + } + return DescriptionInfoset(context, root); +} + +DescriptionInfoset::DescriptionInfoset( + css::uno::Reference< css::uno::XComponentContext > const & context, + css::uno::Reference< css::xml::dom::XNode > const & element): + m_element(element) +{ + css::uno::Reference< css::lang::XMultiComponentFactory > manager( + context->getServiceManager(), css::uno::UNO_QUERY_THROW); + if (m_element.is()) { + m_xpath = css::uno::Reference< css::xml::xpath::XXPathAPI >( + manager->createInstanceWithContext( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.xml.xpath.XPathAPI")), + context), + css::uno::UNO_QUERY_THROW); + m_xpath->registerNS( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc")), + element->getNamespaceURI()); + m_xpath->registerNS( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xlink")), + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("http://www.w3.org/1999/xlink"))); + } +} + +DescriptionInfoset::~DescriptionInfoset() {} + +::boost::optional< ::rtl::OUString > DescriptionInfoset::getIdentifier() const { + return getOptionalValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:identifier/@value"))); +} + +::rtl::OUString DescriptionInfoset::getNodeValueFromExpression(::rtl::OUString const & expression) const +{ + css::uno::Reference< css::xml::dom::XNode > n; + if (m_element.is()) { + try { + n = m_xpath->selectSingleNode(m_element, expression); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + return n.is() ? getNodeValue(n) : ::rtl::OUString(); +} + + +::rtl::OUString DescriptionInfoset::getVersion() const +{ + return getNodeValueFromExpression( ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("desc:version/@value"))); +} + +css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getSupportedPlaforms() const +{ + //When there is no description.xml then we assume that we support all platforms + if (! m_element.is()) + { + return comphelper::makeSequence( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all"))); + } + + //Check if the <platform> element was provided. If not the default is "all" platforms + css::uno::Reference< css::xml::dom::XNode > nodePlatform( + m_xpath->selectSingleNode(m_element, ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("desc:platform")))); + if (!nodePlatform.is()) + { + return comphelper::makeSequence( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all"))); + } + + //There is a platform element. + const ::rtl::OUString value = getNodeValueFromExpression(::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("desc:platform/@value"))); + //parse the string, it can contained multiple strings separated by commas + ::std::vector< ::rtl::OUString> vec; + sal_Int32 nIndex = 0; + do + { + ::rtl::OUString aToken = value.getToken( 0, ',', nIndex ); + aToken = aToken.trim(); + if (aToken.getLength()) + vec.push_back(aToken); + + } + while (nIndex >= 0); + + return comphelper::containerToSequence(vec); +} + +css::uno::Reference< css::xml::dom::XNodeList > +DescriptionInfoset::getDependencies() const { + if (m_element.is()) { + try { + return m_xpath->selectNodeList(m_element, ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("desc:dependencies/*"))); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + return new EmptyNodeList; +} + +css::uno::Sequence< ::rtl::OUString > +DescriptionInfoset::getUpdateInformationUrls() const { + return getUrls( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "desc:update-information/desc:src/@xlink:href"))); +} + +css::uno::Sequence< ::rtl::OUString > +DescriptionInfoset::getUpdateDownloadUrls() const +{ + return getUrls( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "desc:update-download/desc:src/@xlink:href"))); +} + +::rtl::OUString DescriptionInfoset::getIconURL( sal_Bool bHighContrast ) const +{ + css::uno::Sequence< ::rtl::OUString > aStrList = getUrls( ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:default/@xlink:href"))); + css::uno::Sequence< ::rtl::OUString > aStrListHC = getUrls( ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:high-contrast/@xlink:href"))); + + if ( bHighContrast && aStrListHC.hasElements() && aStrListHC[0].getLength() ) + return aStrListHC[0]; + + if ( aStrList.hasElements() && aStrList[0].getLength() ) + return aStrList[0]; + + return ::rtl::OUString(); +} + +::boost::optional< ::rtl::OUString > DescriptionInfoset::getLocalizedUpdateWebsiteURL() + const +{ + bool bParentExists = false; + const ::rtl::OUString sURL (getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:update-website")), &bParentExists )); + + if (sURL.getLength() > 0) + return ::boost::optional< ::rtl::OUString >(sURL); + else + return bParentExists ? ::boost::optional< ::rtl::OUString >(::rtl::OUString()) : + ::boost::optional< ::rtl::OUString >(); +} + +::boost::optional< ::rtl::OUString > DescriptionInfoset::getOptionalValue( + ::rtl::OUString const & expression) const +{ + css::uno::Reference< css::xml::dom::XNode > n; + if (m_element.is()) { + try { + n = m_xpath->selectSingleNode(m_element, expression); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + return n.is() + ? ::boost::optional< ::rtl::OUString >(getNodeValue(n)) + : ::boost::optional< ::rtl::OUString >(); +} + +css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getUrls( + ::rtl::OUString const & expression) const +{ + css::uno::Reference< css::xml::dom::XNodeList > ns; + if (m_element.is()) { + try { + ns = m_xpath->selectNodeList(m_element, expression); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + css::uno::Sequence< ::rtl::OUString > urls(ns.is() ? ns->getLength() : 0); + for (::sal_Int32 i = 0; i < urls.getLength(); ++i) { + urls[i] = getNodeValue(ns->item(i)); + } + return urls; +} + +::std::pair< ::rtl::OUString, ::rtl::OUString > DescriptionInfoset::getLocalizedPublisherNameAndURL() const +{ + css::uno::Reference< css::xml::dom::XNode > node = + getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:publisher"))); + + ::rtl::OUString sPublisherName; + ::rtl::OUString sURL; + if (node.is()) + { + const ::rtl::OUString exp1(RTL_CONSTASCII_USTRINGPARAM("text()")); + css::uno::Reference< css::xml::dom::XNode > xPathName; + try { + xPathName = m_xpath->selectSingleNode(node, exp1); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + OSL_ASSERT(xPathName.is()); + if (xPathName.is()) + sPublisherName = xPathName->getNodeValue(); + + const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("@xlink:href")); + css::uno::Reference< css::xml::dom::XNode > xURL; + try { + xURL = m_xpath->selectSingleNode(node, exp2); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + OSL_ASSERT(xURL.is()); + if (xURL.is()) + sURL = xURL->getNodeValue(); + } + return ::std::make_pair(sPublisherName, sURL); +} + +::rtl::OUString DescriptionInfoset::getLocalizedReleaseNotesURL() const +{ + return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:release-notes")), NULL); +} + +::rtl::OUString DescriptionInfoset::getLocalizedDisplayName() const +{ + css::uno::Reference< css::xml::dom::XNode > node = + getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:display-name"))); + if (node.is()) + { + const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("text()")); + css::uno::Reference< css::xml::dom::XNode > xtext; + try { + xtext = m_xpath->selectSingleNode(node, exp); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + if (xtext.is()) + return xtext->getNodeValue(); + } + return ::rtl::OUString(); +} + +::rtl::OUString DescriptionInfoset::getLocalizedLicenseURL() const +{ + return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:registration/desc:simple-license")), NULL); + +} + +::boost::optional<SimpleLicenseAttributes> +DescriptionInfoset::getSimpleLicenseAttributes() const +{ + //Check if the node exist + css::uno::Reference< css::xml::dom::XNode > n; + if (m_element.is()) { + try { + n = m_xpath->selectSingleNode(m_element, + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:registration/desc:simple-license/@accept-by"))); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + if (n.is()) + { + SimpleLicenseAttributes attributes; + attributes.acceptBy = + getNodeValueFromExpression(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:registration/desc:simple-license/@accept-by"))); + + ::boost::optional< ::rtl::OUString > suppressOnUpdate = getOptionalValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:registration/desc:simple-license/@suppress-on-update"))); + if (suppressOnUpdate) + attributes.suppressOnUpdate = (*suppressOnUpdate).trim().equalsIgnoreAsciiCase( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true"))); + else + attributes.suppressOnUpdate = false; + + ::boost::optional< ::rtl::OUString > suppressIfRequired = getOptionalValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:registration/desc:simple-license/@suppress-if-required"))); + if (suppressIfRequired) + attributes.suppressIfRequired = (*suppressIfRequired).trim().equalsIgnoreAsciiCase( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true"))); + else + attributes.suppressIfRequired = false; + + return ::boost::optional<SimpleLicenseAttributes>(attributes); + } + } + return ::boost::optional<SimpleLicenseAttributes>(); +} + +::rtl::OUString DescriptionInfoset::getLocalizedDescriptionURL() const +{ + return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:extension-description")), NULL); +} + +css::uno::Reference< css::xml::dom::XNode > +DescriptionInfoset::getLocalizedChild( const ::rtl::OUString & sParent) const +{ + if ( ! m_element.is() || !sParent.getLength()) + return css::uno::Reference< css::xml::dom::XNode > (); + + css::uno::Reference< css::xml::dom::XNode > xParent; + try { + xParent = m_xpath->selectSingleNode(m_element, sParent); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + css::uno::Reference<css::xml::dom::XNode> nodeMatch; + if (xParent.is()) + { + const ::rtl::OUString sLocale = getOfficeLocaleString(); + nodeMatch = matchFullLocale(xParent, sLocale); + + //office: en-DE, en, en-DE-altmark + if (! nodeMatch.is()) + { + const css::lang::Locale officeLocale = getOfficeLocale(); + nodeMatch = matchCountryAndLanguage(xParent, officeLocale); + if ( ! nodeMatch.is()) + { + nodeMatch = matchLanguage(xParent, officeLocale); + if (! nodeMatch.is()) + nodeMatch = getChildWithDefaultLocale(xParent); + } + } + } + + return nodeMatch; +} + +css::uno::Reference<css::xml::dom::XNode> +DescriptionInfoset::matchFullLocale(css::uno::Reference< css::xml::dom::XNode > + const & xParent, ::rtl::OUString const & sLocale) const +{ + OSL_ASSERT(xParent.is()); + const ::rtl::OUString exp1( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\"")) + + sLocale + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]"))); + try { + return m_xpath->selectSingleNode(xParent, exp1); + } catch (css::xml::xpath::XPathException &) { + // ignore + return 0; + } +} + +css::uno::Reference<css::xml::dom::XNode> +DescriptionInfoset::matchCountryAndLanguage( + css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const +{ + OSL_ASSERT(xParent.is()); + css::uno::Reference<css::xml::dom::XNode> nodeMatch; + + if (officeLocale.Country.getLength()) + { + const ::rtl::OUString sLangCountry(officeLocale.Language + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-")) + + officeLocale.Country); + //first try exact match for lang-country + const ::rtl::OUString exp1( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\"")) + + sLangCountry + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]"))); + try { + nodeMatch = m_xpath->selectSingleNode(xParent, exp1); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + + //try to match in strings that also have a variant, for example en-US matches in + //en-US-montana + if (!nodeMatch.is()) + { + const ::rtl::OUString exp2( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\"")) + + sLangCountry + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]"))); + try { + nodeMatch = m_xpath->selectSingleNode(xParent, exp2); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + } + + return nodeMatch; +} + + +css::uno::Reference<css::xml::dom::XNode> +DescriptionInfoset::matchLanguage( + css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const +{ + OSL_ASSERT(xParent.is()); + css::uno::Reference<css::xml::dom::XNode> nodeMatch; + + //first try exact match for lang + const ::rtl::OUString exp1( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\"")) + + officeLocale.Language + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]"))); + try { + nodeMatch = m_xpath->selectSingleNode(xParent, exp1); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + + //try to match in strings that also have a country and/orvariant, for example en matches in + //en-US-montana, en-US, en-montana + if (!nodeMatch.is()) + { + const ::rtl::OUString exp2( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\"")) + + officeLocale.Language + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]"))); + try { + nodeMatch = m_xpath->selectSingleNode(xParent, exp2); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + return nodeMatch; +} + +css::uno::Reference<css::xml::dom::XNode> +DescriptionInfoset::getChildWithDefaultLocale(css::uno::Reference< css::xml::dom::XNode > + const & xParent) const +{ + OSL_ASSERT(xParent.is()); + if (xParent->getNodeName().equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("simple-license")))) + { + css::uno::Reference<css::xml::dom::XNode> nodeDefault; + try { + nodeDefault = m_xpath->selectSingleNode(xParent, ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("@default-license-id"))); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + if (nodeDefault.is()) + { + //The old way + const ::rtl::OUString exp1( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:license-text[@license-id = \"")) + + nodeDefault->getNodeValue() + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]"))); + try { + return m_xpath->selectSingleNode(xParent, exp1); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + } + + const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("*[1]")); + try { + return m_xpath->selectSingleNode(xParent, exp2); + } catch (css::xml::xpath::XPathException &) { + // ignore + return 0; + } +} + +::rtl::OUString DescriptionInfoset::getLocalizedHREFAttrFromChild( + ::rtl::OUString const & sXPathParent, bool * out_bParentExists) + const +{ + css::uno::Reference< css::xml::dom::XNode > node = + getLocalizedChild(sXPathParent); + + ::rtl::OUString sURL; + if (node.is()) + { + if (out_bParentExists) + *out_bParentExists = true; + const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("@xlink:href")); + css::uno::Reference< css::xml::dom::XNode > xURL; + try { + xURL = m_xpath->selectSingleNode(node, exp); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + OSL_ASSERT(xURL.is()); + if (xURL.is()) + sURL = xURL->getNodeValue(); + } + else + { + if (out_bParentExists) + *out_bParentExists = false; + } + return sURL; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_identifier.cxx b/desktop/source/deployment/misc/dp_identifier.cxx new file mode 100644 index 000000000000..b24ccd7def52 --- /dev/null +++ b/desktop/source/deployment/misc/dp_identifier.cxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "sal/config.h" + +#include "boost/optional.hpp" +#include "com/sun/star/beans/Optional.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "osl/diagnose.h" +#include "rtl/string.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.hxx" + +#include "dp_identifier.hxx" + +namespace { + namespace css = ::com::sun::star; +} + +namespace dp_misc { + +::rtl::OUString generateIdentifier( + ::boost::optional< ::rtl::OUString > const & optional, + ::rtl::OUString const & fileName) +{ + return optional ? *optional : generateLegacyIdentifier(fileName); +} + +::rtl::OUString getIdentifier( + css::uno::Reference< css::deployment::XPackage > const & package) +{ + OSL_ASSERT(package.is()); + css::beans::Optional< ::rtl::OUString > id(package->getIdentifier()); + return id.IsPresent + ? id.Value : generateLegacyIdentifier(package->getName()); +} + +::rtl::OUString generateLegacyIdentifier(::rtl::OUString const & fileName) { + rtl::OUStringBuffer b; + b.appendAscii(RTL_CONSTASCII_STRINGPARAM("org.openoffice.legacy.")); + b.append(fileName); + return b.makeStringAndClear(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_interact.cxx b/desktop/source/deployment/misc/dp_interact.cxx new file mode 100644 index 000000000000..c42ccd249cb7 --- /dev/null +++ b/desktop/source/deployment/misc/dp_interact.cxx @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_interact.h" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase1.hxx" +#include "com/sun/star/task/XInteractionAbort.hpp" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_misc { +namespace { + +//============================================================================== +class InteractionContinuationImpl : public ::cppu::OWeakObject, + public task::XInteractionContinuation +{ + const Type m_type; + bool * m_pselect; + +public: + inline InteractionContinuationImpl( Type const & type, bool * pselect ) + : m_type( type ), + m_pselect( pselect ) + { OSL_ASSERT( + ::getCppuType( + static_cast< Reference<task::XInteractionContinuation> + const *>(0) ).isAssignableFrom(m_type) ); } + + // XInterface + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + virtual Any SAL_CALL queryInterface( Type const & type ) + throw (RuntimeException); + + // XInteractionContinuation + virtual void SAL_CALL select() throw (RuntimeException); +}; + +// XInterface +//______________________________________________________________________________ +void InteractionContinuationImpl::acquire() throw () +{ + OWeakObject::acquire(); +} + +//______________________________________________________________________________ +void InteractionContinuationImpl::release() throw () +{ + OWeakObject::release(); +} + +//______________________________________________________________________________ +Any InteractionContinuationImpl::queryInterface( Type const & type ) + throw (RuntimeException) +{ + if (type.isAssignableFrom( m_type )) { + Reference<task::XInteractionContinuation> xThis(this); + return Any( &xThis, type ); + } + else + return OWeakObject::queryInterface(type); +} + +// XInteractionContinuation +//______________________________________________________________________________ +void InteractionContinuationImpl::select() throw (RuntimeException) +{ + *m_pselect = true; +} + +//============================================================================== +class InteractionRequest : + public ::cppu::WeakImplHelper1<task::XInteractionRequest> +{ + Any m_request; + Sequence< Reference<task::XInteractionContinuation> > m_conts; + +public: + inline InteractionRequest( + Any const & request, + Sequence< Reference<task::XInteractionContinuation> > const & conts ) + : m_request( request ), + m_conts( conts ) + {} + + // XInteractionRequest + virtual Any SAL_CALL getRequest() + throw (RuntimeException); + virtual Sequence< Reference<task::XInteractionContinuation> > + SAL_CALL getContinuations() throw (RuntimeException); +}; + +// XInteractionRequest +//______________________________________________________________________________ +Any InteractionRequest::getRequest() throw (RuntimeException) +{ + return m_request; +} + +//______________________________________________________________________________ +Sequence< Reference< task::XInteractionContinuation > > +InteractionRequest::getContinuations() throw (RuntimeException) +{ + return m_conts; +} + +} // anon namespace + +//============================================================================== +bool interactContinuation( Any const & request, + Type const & continuation, + Reference<XCommandEnvironment> const & xCmdEnv, + bool * pcont, bool * pabort ) +{ + OSL_ASSERT( + task::XInteractionContinuation::static_type().isAssignableFrom( + continuation ) ); + if (xCmdEnv.is()) { + Reference<task::XInteractionHandler> xInteractionHandler( + xCmdEnv->getInteractionHandler() ); + if (xInteractionHandler.is()) { + bool cont = false; + bool abort = false; + Sequence< Reference<task::XInteractionContinuation> > conts( 2 ); + conts[ 0 ] = new InteractionContinuationImpl( + continuation, &cont ); + conts[ 1 ] = new InteractionContinuationImpl( + task::XInteractionAbort::static_type(), &abort ); + xInteractionHandler->handle( + new InteractionRequest( request, conts ) ); + if (cont || abort) { + if (pcont != 0) + *pcont = cont; + if (pabort != 0) + *pabort = abort; + return true; + } + } + } + return false; +} + +// XAbortChannel +//______________________________________________________________________________ +void AbortChannel::sendAbort() throw (RuntimeException) +{ + m_aborted = true; + if (m_xNext.is()) + m_xNext->sendAbort(); +} + +} // dp_misc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_misc.cxx b/desktop/source/deployment/misc/dp_misc.cxx new file mode 100644 index 000000000000..2bd02540a8d3 --- /dev/null +++ b/desktop/source/deployment/misc/dp_misc.cxx @@ -0,0 +1,643 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_misc.h" +#include "dp_version.hxx" +#include "dp_interact.h" +#include "rtl/uri.hxx" +#include "rtl/digest.h" +#include "rtl/random.h" +#include "rtl/bootstrap.hxx" +#include "unotools/bootstrap.hxx" +#include "osl/file.hxx" +#include "osl/pipe.hxx" +#include "osl/security.hxx" +#include "osl/thread.hxx" +#include "osl/mutex.hxx" +#include "com/sun/star/ucb/CommandAbortedException.hpp" +#include "com/sun/star/task/XInteractionHandler.hpp" +#include "com/sun/star/bridge/UnoUrlResolver.hpp" +#include "com/sun/star/bridge/XUnoUrlResolver.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/task/XRestartManager.hpp" +#include "boost/scoped_array.hpp" +#include "boost/shared_ptr.hpp" +#include <comphelper/processfactory.hxx> +#include <salhelper/linkhelper.hxx> + +#ifdef WNT +#define UNICODE +#define _UNICODE +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; +using ::rtl::OString; + + +#define SOFFICE1 "soffice.exe" +#define SOFFICE2 "soffice.bin" +#define SBASE "sbase.exe" +#define SCALC "scalc.exe" +#define SDRAW "sdraw.exe" +#define SIMPRESS "simpress.exe" +#define SWRITER "swriter.exe" + +namespace dp_misc { +namespace { + +struct UnoRc : public rtl::StaticWithInit< + boost::shared_ptr<rtl::Bootstrap>, UnoRc> { + const boost::shared_ptr<rtl::Bootstrap> operator () () { + OUString unorc( RTL_CONSTASCII_USTRINGPARAM( + "$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")) ); + ::rtl::Bootstrap::expandMacros( unorc ); + ::boost::shared_ptr< ::rtl::Bootstrap > ret( + new ::rtl::Bootstrap( unorc ) ); + OSL_ASSERT( ret->getHandle() != 0 ); + return ret; + } +}; + +struct OfficePipeId : public rtl::StaticWithInit<OUString, OfficePipeId> { + const OUString operator () (); +}; + +const OUString OfficePipeId::operator () () +{ + OUString userPath; + ::utl::Bootstrap::PathStatus aLocateResult = + ::utl::Bootstrap::locateUserInstallation( userPath ); + if (!(aLocateResult == ::utl::Bootstrap::PATH_EXISTS || + aLocateResult == ::utl::Bootstrap::PATH_VALID)) + { + throw Exception(OUSTR("Extension Manager: Could not obtain path for UserInstallation."), 0); + } + + rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 ); + if (digest <= 0) { + throw RuntimeException( + OUSTR("cannot get digest rtl_Digest_AlgorithmMD5!"), 0 ); + } + + sal_uInt8 const * data = + reinterpret_cast<sal_uInt8 const *>(userPath.getStr()); + sal_Size size = (userPath.getLength() * sizeof (sal_Unicode)); + sal_uInt32 md5_key_len = rtl_digest_queryLength( digest ); + ::boost::scoped_array<sal_uInt8> md5_buf( new sal_uInt8 [ md5_key_len ] ); + + rtl_digest_init( digest, data, static_cast<sal_uInt32>(size) ); + rtl_digest_update( digest, data, static_cast<sal_uInt32>(size) ); + rtl_digest_get( digest, md5_buf.get(), md5_key_len ); + rtl_digest_destroy( digest ); + + // create hex-value string from the MD5 value to keep + // the string size minimal + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("SingleOfficeIPC_") ); + for ( sal_uInt32 i = 0; i < md5_key_len; ++i ) { + buf.append( static_cast<sal_Int32>(md5_buf[ i ]), 0x10 ); + } + return buf.makeStringAndClear(); +} + +bool existsOfficePipe() +{ + OUString const & pipeId = OfficePipeId::get(); + if (pipeId.getLength() == 0) + return false; + ::osl::Security sec; + ::osl::Pipe pipe( pipeId, osl_Pipe_OPEN, sec ); + return pipe.is(); +} + +//get modification time +static bool getModifyTimeTargetFile(const OUString &rFileURL, TimeValue &rTime) +{ + salhelper::LinkResolver aResolver(osl_FileStatus_Mask_ModifyTime); + + if (aResolver.fetchFileStatus(rFileURL) != osl::FileBase::E_None) + return false; + + rTime = aResolver.m_aStatus.getModifyTime(); + + return true; +} + +//Returns true if the Folder was more recently modified then +//the lastsynchronized file. That is the repository needs to +//be synchronized. +bool compareExtensionFolderWithLastSynchronizedFile( + OUString const & folderURL, OUString const & fileURL) +{ + bool bNeedsSync = false; + ::osl::DirectoryItem itemExtFolder; + ::osl::File::RC err1 = + ::osl::DirectoryItem::get(folderURL, itemExtFolder); + //If it does not exist, then there is nothing to be done + if (err1 == ::osl::File::E_NOENT) + { + return false; + } + else if (err1 != ::osl::File::E_None) + { + OSL_FAIL("Cannot access extension folder"); + return true; //sync just in case + } + + //If last synchronized does not exist, then OOo is started for the first time + ::osl::DirectoryItem itemFile; + ::osl::File::RC err2 = ::osl::DirectoryItem::get(fileURL, itemFile); + if (err2 == ::osl::File::E_NOENT) + { + return true; + + } + else if (err2 != ::osl::File::E_None) + { + OSL_FAIL("Cannot access file lastsynchronized"); + return true; //sync just in case + } + + //compare the modification time of the extension folder and the last + //modified file + TimeValue timeFolder; + if (getModifyTimeTargetFile(folderURL, timeFolder)) + { + TimeValue timeFile; + if (getModifyTimeTargetFile(fileURL, timeFile)) + { + if (timeFile.Seconds < timeFolder.Seconds) + bNeedsSync = true; + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + + return bNeedsSync; +} + +bool needToSyncRepostitory(OUString const & name) +{ + OUString folder; + OUString file; + if (name.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("bundled")))) + { + folder = OUString( + RTL_CONSTASCII_USTRINGPARAM("$BUNDLED_EXTENSIONS")); + file = OUString ( + RTL_CONSTASCII_USTRINGPARAM( + "$BUNDLED_EXTENSIONS_USER/lastsynchronized")); + } + else if (name.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("shared")))) + { + folder = OUString( + RTL_CONSTASCII_USTRINGPARAM( + "$UNO_SHARED_PACKAGES_CACHE/uno_packages")); + file = OUString ( + RTL_CONSTASCII_USTRINGPARAM( + "$SHARED_EXTENSIONS_USER/lastsynchronized")); + } + else + { + OSL_ASSERT(0); + return true; + } + ::rtl::Bootstrap::expandMacros(folder); + ::rtl::Bootstrap::expandMacros(file); + return compareExtensionFolderWithLastSynchronizedFile( + folder, file); +} + + +} // anon namespace + +//============================================================================== + +namespace { +inline OUString encodeForRcFile( OUString const & str ) +{ + // escape $\{} (=> rtl bootstrap files) + ::rtl::OUStringBuffer buf; + sal_Int32 pos = 0; + const sal_Int32 len = str.getLength(); + for ( ; pos < len; ++pos ) { + sal_Unicode c = str[ pos ]; + switch (c) { + case '$': + case '\\': + case '{': + case '}': + buf.append( static_cast<sal_Unicode>('\\') ); + break; + } + buf.append( c ); + } + return buf.makeStringAndClear(); +} +} + +//============================================================================== +OUString makeURL( OUString const & baseURL, OUString const & relPath_ ) +{ + ::rtl::OUStringBuffer buf; + if (baseURL.getLength() > 1 && baseURL[ baseURL.getLength() - 1 ] == '/') + buf.append( baseURL.copy( 0, baseURL.getLength() - 1 ) ); + else + buf.append( baseURL ); + OUString relPath(relPath_); + if (relPath.getLength() > 0 && relPath[ 0 ] == '/') + relPath = relPath.copy( 1 ); + if (relPath.getLength() > 0) + { + buf.append( static_cast<sal_Unicode>('/') ); + if (baseURL.matchAsciiL( + RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) { + // encode for macro expansion: relPath is supposed to have no + // macros, so encode $, {} \ (bootstrap mimic) + relPath = encodeForRcFile(relPath); + + // encode once more for vnd.sun.star.expand schema: + // vnd.sun.star.expand:$UNO_... + // will expand to file-url + relPath = ::rtl::Uri::encode( relPath, rtl_UriCharClassUric, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + } + buf.append( relPath ); + } + return buf.makeStringAndClear(); +} + +OUString makeURLAppendSysPathSegment( OUString const & baseURL, OUString const & relPath_ ) +{ + OUString segment = relPath_; + OSL_ASSERT(segment.indexOf(static_cast<sal_Unicode>('/')) == -1); + + ::rtl::Uri::encode( + segment, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8); + return makeURL(baseURL, segment); +} + + + +//============================================================================== +OUString expandUnoRcTerm( OUString const & term_ ) +{ + OUString term(term_); + UnoRc::get()->expandMacrosFrom( term ); + return term; +} + +OUString makeRcTerm( OUString const & url ) +{ + OSL_ASSERT( url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( + "vnd.sun.star.expand:") ) ); + if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) { + // cut protocol: + OUString rcterm( url.copy( sizeof ("vnd.sun.star.expand:") - 1 ) ); + // decode uric class chars: + rcterm = ::rtl::Uri::decode( + rcterm, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + return rcterm; + } + else + return url; +} + +//============================================================================== +OUString expandUnoRcUrl( OUString const & url ) +{ + if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) { + // cut protocol: + OUString rcurl( url.copy( sizeof ("vnd.sun.star.expand:") - 1 ) ); + // decode uric class chars: + rcurl = ::rtl::Uri::decode( + rcurl, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + // expand macro string: + UnoRc::get()->expandMacrosFrom( rcurl ); + return rcurl; + } + else { + return url; + } +} + +//============================================================================== +bool office_is_running() +{ + //We need to check if we run within the office process. Then we must not use the pipe, because + //this could cause a deadlock. This is actually a workaround for i82778 + OUString sFile; + oslProcessError err = osl_getExecutableFile(& sFile.pData); + bool ret = false; + if (osl_Process_E_None == err) + { + sFile = sFile.copy(sFile.lastIndexOf('/') + 1); + if ( +#if defined UNIX + sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE2))) +#elif defined WNT + //osl_getExecutableFile should deliver "soffice.bin" on windows + //even if swriter.exe, scalc.exe etc. was started. This is a bug + //in osl_getExecutableFile + sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE1))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE2))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SBASE))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SCALC))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SDRAW))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SIMPRESS))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SWRITER))) +#else +#error "Unsupported platform" +#endif + + ) + ret = true; + else + ret = existsOfficePipe(); + } + else + { + OSL_FAIL("NOT osl_Process_E_None "); + //if osl_getExecutable file than we take the risk of creating a pipe + ret = existsOfficePipe(); + } + return ret; +} + +//============================================================================== +oslProcess raiseProcess( + OUString const & appURL, Sequence<OUString> const & args ) +{ + ::osl::Security sec; + oslProcess hProcess = 0; + oslProcessError rc = osl_executeProcess( + appURL.pData, + reinterpret_cast<rtl_uString **>( + const_cast<OUString *>(args.getConstArray()) ), + args.getLength(), + osl_Process_DETACHED, + sec.getHandle(), + 0, // => current working dir + 0, 0, // => no env vars + &hProcess ); + + switch (rc) { + case osl_Process_E_None: + break; + case osl_Process_E_NotFound: + throw RuntimeException( OUSTR("image not found!"), 0 ); + case osl_Process_E_TimedOut: + throw RuntimeException( OUSTR("timout occurred!"), 0 ); + case osl_Process_E_NoPermission: + throw RuntimeException( OUSTR("permission denied!"), 0 ); + case osl_Process_E_Unknown: + throw RuntimeException( OUSTR("unknown error!"), 0 ); + case osl_Process_E_InvalidError: + default: + throw RuntimeException( OUSTR("unmapped error!"), 0 ); + } + + return hProcess; +} + +//============================================================================== +OUString generateRandomPipeId() +{ + // compute some good pipe id: + static rtlRandomPool s_hPool = rtl_random_createPool(); + if (s_hPool == 0) + throw RuntimeException( OUSTR("cannot create random pool!?"), 0 ); + sal_uInt8 bytes[ 32 ]; + if (rtl_random_getBytes( + s_hPool, bytes, ARLEN(bytes) ) != rtl_Random_E_None) { + throw RuntimeException( OUSTR("random pool error!?"), 0 ); + } + ::rtl::OUStringBuffer buf; + for ( sal_uInt32 i = 0; i < ARLEN(bytes); ++i ) { + buf.append( static_cast<sal_Int32>(bytes[ i ]), 0x10 ); + } + return buf.makeStringAndClear(); +} + +//============================================================================== +Reference<XInterface> resolveUnoURL( + OUString const & connectString, + Reference<XComponentContext> const & xLocalContext, + AbortChannel * abortChannel ) +{ + Reference<bridge::XUnoUrlResolver> xUnoUrlResolver( + bridge::UnoUrlResolver::create( xLocalContext ) ); + + for (;;) + { + if (abortChannel != 0 && abortChannel->isAborted()) { + throw ucb::CommandAbortedException( + OUSTR("abort!"), Reference<XInterface>() ); + } + try { + return xUnoUrlResolver->resolve( connectString ); + } + catch (connection::NoConnectException &) { + TimeValue tv = { 0 /* secs */, 500000000 /* nanosecs */ }; + ::osl::Thread::wait( tv ); + } + } +} + +#ifdef WNT +void writeConsoleWithStream(::rtl::OUString const & sText, HANDLE stream) +{ + DWORD nWrittenChars = 0; + WriteFile(stream, sText.getStr(), + sText.getLength() * 2, &nWrittenChars, NULL); +} +#else +void writeConsoleWithStream(::rtl::OUString const & sText, FILE * stream) +{ + OString s = OUStringToOString(sText, osl_getThreadTextEncoding()); + fprintf(stream, "%s", s.getStr()); + fflush(stream); +} +#endif + +#ifdef WNT +void writeConsoleWithStream(::rtl::OString const & sText, HANDLE stream) +{ + writeConsoleWithStream(OStringToOUString( + sText, RTL_TEXTENCODING_UTF8), stream); +} +#else +void writeConsoleWithStream(::rtl::OString const & sText, FILE * stream) +{ + fprintf(stream, "%s", sText.getStr()); + fflush(stream); +} +#endif + +void writeConsole(::rtl::OUString const & sText) +{ +#ifdef WNT + writeConsoleWithStream(sText, GetStdHandle(STD_OUTPUT_HANDLE)); +#else + writeConsoleWithStream(sText, stdout); +#endif +} + +void writeConsole(::rtl::OString const & sText) +{ +#ifdef WNT + writeConsoleWithStream(sText, GetStdHandle(STD_OUTPUT_HANDLE)); +#else + writeConsoleWithStream(sText, stdout); +#endif +} + +void writeConsoleError(::rtl::OUString const & sText) +{ +#ifdef WNT + writeConsoleWithStream(sText, GetStdHandle(STD_ERROR_HANDLE)); +#else + writeConsoleWithStream(sText, stderr); +#endif +} + + +void writeConsoleError(::rtl::OString const & sText) +{ +#ifdef WNT + writeConsoleWithStream(sText, GetStdHandle(STD_ERROR_HANDLE)); +#else + writeConsoleWithStream(sText, stderr); +#endif +} + + + +OUString readConsole() +{ +#ifdef WNT + sal_Unicode aBuffer[1024]; + DWORD dwRead = 0; + //unopkg.com feeds unopkg.exe with wchar_t|s + if (ReadFile( GetStdHandle(STD_INPUT_HANDLE), &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) + { + OSL_ASSERT((dwRead % 2) == 0); + OUString value( aBuffer, dwRead / 2); + return value.trim(); + } +#else + char buf[1024]; + rtl_zeroMemory(buf, 1024); + // read one char less so that the last char in buf is always zero + if (fgets(buf, 1024, stdin) != NULL) + { + OUString value = ::rtl::OStringToOUString(::rtl::OString(buf), osl_getThreadTextEncoding()); + return value.trim(); + } +#endif + return OUString(); +} + +void TRACE(::rtl::OUString const & sText) +{ + (void) sText; +#if OSL_DEBUG_LEVEL > 1 + writeConsole(sText); +#endif +} + +void TRACE(::rtl::OString const & sText) +{ + (void) sText; +#if OSL_DEBUG_LEVEL > 1 + writeConsole(sText); +#endif +} + +void syncRepositories(Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + OUString sDisable; + ::rtl::Bootstrap::get( OUSTR( "DISABLE_EXTENSION_SYNCHRONIZATION" ), sDisable, OUString() ); + if (sDisable.getLength() > 0) + return; + + Reference<deployment::XExtensionManager> xExtensionManager; + //synchronize shared before bundled otherewise there are + //more revoke and registration calls. + sal_Bool bModified = false; + if (needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("shared"))) + || needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("bundled")))) + { + xExtensionManager = + deployment::ExtensionManager::get( + comphelper_getProcessComponentContext()); + + if (xExtensionManager.is()) + { + bModified = xExtensionManager->synchronize( + Reference<task::XAbortChannel>(), xCmdEnv); + } + } + + if (bModified) + { + Reference<task::XRestartManager> restarter( + comphelper_getProcessComponentContext()->getValueByName( + OUSTR( "/singletons/com.sun.star.task.OfficeRestartManager") ), UNO_QUERY ); + if (restarter.is()) + { + OSL_TRACE( "Request restart for modified extensions manager" ); + restarter->requestRestart(xCmdEnv.is() == sal_True ? xCmdEnv->getInteractionHandler() : + Reference<task::XInteractionHandler>()); + } + } +} + + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_misc.hrc b/desktop/source/deployment/misc/dp_misc.hrc new file mode 100755 index 000000000000..55fabac5c5b5 --- /dev/null +++ b/desktop/source/deployment/misc/dp_misc.hrc @@ -0,0 +1,33 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_MISC_HRC +#define INCLUDED_DP_MISC_HRC + +#include "deployment.hrc" + +#endif diff --git a/desktop/source/deployment/misc/dp_misc.src b/desktop/source/deployment/misc/dp_misc.src new file mode 100644 index 000000000000..d18fc4c45f16 --- /dev/null +++ b/desktop/source/deployment/misc/dp_misc.src @@ -0,0 +1,40 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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.hrc" + +String RID_DEPLYOMENT_DEPENDENCIES_UNKNOWN { + Text[en-US] = "Unknown"; +}; + +String RID_DEPLYOMENT_DEPENDENCIES_MIN { + Text[en-US] = "Extension requires at least %PRODUCTNAME %VERSION"; +}; + +String RID_DEPLYOMENT_DEPENDENCIES_MAX { + Text[en-US] = "Extension doesn't support versions greater than: %PRODUCTNAME %VERSION"; +}; diff --git a/desktop/source/deployment/misc/dp_platform.cxx b/desktop/source/deployment/misc/dp_platform.cxx new file mode 100644 index 000000000000..3caf1196df95 --- /dev/null +++ b/desktop/source/deployment/misc/dp_platform.cxx @@ -0,0 +1,253 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_misc.h" +#include "dp_platform.hxx" +#include "rtl/ustring.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/instance.hxx" +#include "rtl/bootstrap.hxx" + +#define PLATFORM_ALL "all" +#define PLATFORM_WIN_X86 "windows_x86" +#define PLATFORM_WIN_X86_64 "windows_x86_64" +#define PLATFORM_LINUX_X86 "linux_x86" +#define PLATFORM_LINUX_X86_64 "linux_x86_64" +#define PLATFORM_KFREEBSD_X86 "kfreebsd_x86" +#define PLATFORM_KFREEBSD_X86_64 "kfreebsd_x86_64" +#define PLATFORM_LINUX_SPARC "linux_sparc" +#define PLATFORM_LINUX_POWERPC "linux_powerpc" +#define PLATFORM_LINUX_POWERPC64 "linux_powerpc64" +#define PLATFORM_LINUX_ARM_EABI "linux_arm_eabi" +#define PLATFORM_LINUX_ARM_OABI "linux_arm_oabi" +#define PLATFORM_LINUX_MIPS_EL "linux_mips_el" +#define PLATFORM_LINUX_MIPS_EB "linux_mips_eb" +#define PLATFORM_LINUX_IA64 "linux_ia64" +#define PLATFORM_LINUX_M68K "linux_m68k" +#define PLATFORM_LINUX_S390 "linux_s390" +#define PLATFORM_LINUX_S390x "linux_s390x" +#define PLATFORM_LINUX_HPPA "linux_hppa" +#define PLATFORM_LINUX_ALPHA "linux_alpha" + + + +#define PLATFORM_SOLARIS_SPARC "solaris_sparc" +#define PLATFORM_SOLARIS_SPARC64 "solaris_sparc64" +#define PLATFORM_SOLARIS_X86 "solaris_x86" +#define PLATFORM_FREEBSD_X86 "freebsd_x86" +#define PLATFORM_FREEBSD_X86_64 "freebsd_x86_64" +#define PLATFORM_NETBSD_X86 "netbsd_x86" +#define PLATFORM_NETBSD_X86_64 "netbsd_x86_64" +#define PLATFORM_MACOSX_X86 "macosx_x86" +#define PLATFORM_MACOSX_PPC "macosx_powerpc" +#define PLATFORM_OPENBSD_X86 "openbsd_x86" +#define PLATFORM_OPENBSD_X86_64 "openbsd_x86_64" +#define PLATFORM_DRAGONFLY_X86 "dragonfly_x86" +#define PLATFORM_DRAGONFLY_X86_64 "dragonfly_x86_64" + + +#define PLATFORM_AIX_POWERPC "aix_powerpc" + + + + + + + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) +using ::rtl::OUString; +namespace css = ::com::sun::star; + +namespace dp_misc +{ +namespace +{ + struct StrOperatingSystem : + public rtl::StaticWithInit<OUString, StrOperatingSystem> { + const OUString operator () () { + OUString os( RTL_CONSTASCII_USTRINGPARAM("$_OS") ); + ::rtl::Bootstrap::expandMacros( os ); + return os; + } + }; + + struct StrCPU : + public rtl::StaticWithInit<OUString, StrCPU> { + const OUString operator () () { + OUString arch( RTL_CONSTASCII_USTRINGPARAM("$_ARCH") ); + ::rtl::Bootstrap::expandMacros( arch ); + return arch; + } + }; + + + struct StrPlatform : public rtl::StaticWithInit< + OUString, StrPlatform> { + const OUString operator () () { + ::rtl::OUStringBuffer buf; + buf.append( StrOperatingSystem::get() ); + buf.append( static_cast<sal_Unicode>('_') ); + buf.append( StrCPU::get() ); + return buf.makeStringAndClear(); + } + }; + + bool checkOSandCPU(OUString const & os, OUString const & cpu) + { + return os.equals(StrOperatingSystem::get()) + && cpu.equals(StrCPU::get()); + } + + bool isValidPlatform(OUString const & token ) + { + bool ret = false; + if (token.equals(OUSTR(PLATFORM_ALL))) + ret = true; + else if (token.equals(OUSTR(PLATFORM_WIN_X86))) + ret = checkOSandCPU(OUSTR("Windows"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_WIN_X86_64))) + ret = checkOSandCPU(OUSTR("Windows"), OUSTR("x86_64")); + else if (token.equals(OUSTR(PLATFORM_LINUX_X86))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_LINUX_X86_64))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("X86_64")); + else if (token.equals(OUSTR(PLATFORM_KFREEBSD_X86))) + ret = checkOSandCPU(OUSTR("kFreeBSD"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_KFREEBSD_X86_64))) + ret = checkOSandCPU(OUSTR("kFreeBSD"), OUSTR("X86_64")); + else if (token.equals(OUSTR(PLATFORM_LINUX_SPARC))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("SPARC")); + else if (token.equals(OUSTR(PLATFORM_LINUX_POWERPC))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("PowerPC")); + else if (token.equals(OUSTR(PLATFORM_LINUX_POWERPC64))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("PowerPC_64")); + else if (token.equals(OUSTR(PLATFORM_LINUX_ARM_EABI))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("ARM_EABI")); + else if (token.equals(OUSTR(PLATFORM_LINUX_ARM_OABI))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("ARM_OABI")); + else if (token.equals(OUSTR(PLATFORM_LINUX_MIPS_EL))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("MIPS_EL")); + else if (token.equals(OUSTR(PLATFORM_LINUX_MIPS_EB))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("MIPS_EB")); + else if (token.equals(OUSTR(PLATFORM_LINUX_IA64))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("IA64")); + else if (token.equals(OUSTR(PLATFORM_LINUX_M68K))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("M68K")); + else if (token.equals(OUSTR(PLATFORM_LINUX_S390))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("S390")); + else if (token.equals(OUSTR(PLATFORM_LINUX_S390x))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("S390x")); + else if (token.equals(OUSTR(PLATFORM_LINUX_HPPA))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("HPPA")); + else if (token.equals(OUSTR(PLATFORM_LINUX_ALPHA))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("ALPHA")); + else if (token.equals(OUSTR(PLATFORM_SOLARIS_SPARC))) + ret = checkOSandCPU(OUSTR("Solaris"), OUSTR("SPARC")); + else if (token.equals(OUSTR(PLATFORM_SOLARIS_SPARC64))) + ret = checkOSandCPU(OUSTR("Solaris"), OUSTR("SPARC64")); + else if (token.equals(OUSTR(PLATFORM_SOLARIS_X86))) + ret = checkOSandCPU(OUSTR("Solaris"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_FREEBSD_X86))) + ret = checkOSandCPU(OUSTR("FreeBSD"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_FREEBSD_X86_64))) + ret = checkOSandCPU(OUSTR("FreeBSD"), OUSTR("X86_64")); + else if (token.equals(OUSTR(PLATFORM_NETBSD_X86))) + ret = checkOSandCPU(OUSTR("NetBSD"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_NETBSD_X86_64))) + ret = checkOSandCPU(OUSTR("NetBSD"), OUSTR("X86_64")); + else if (token.equals(OUSTR(PLATFORM_MACOSX_X86))) + ret = checkOSandCPU(OUSTR("MacOSX"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_MACOSX_PPC))) + ret = checkOSandCPU(OUSTR("MacOSX"), OUSTR("PowerPC")); + else if (token.equals(OUSTR(PLATFORM_AIX_POWERPC))) + ret = checkOSandCPU(OUSTR("AIX"), OUSTR("PowerPC")); + else if (token.equals(OUSTR(PLATFORM_OPENBSD_X86))) + ret = checkOSandCPU(OUSTR("OpenBSD"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_OPENBSD_X86_64))) + ret = checkOSandCPU(OUSTR("OpenBSD"), OUSTR("X86_64")); + else if (token.equals(OUSTR(PLATFORM_DRAGONFLY_X86))) + ret = checkOSandCPU(OUSTR("DragonFly"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_DRAGONFLY_X86_64))) + ret = checkOSandCPU(OUSTR("DragonFly"), OUSTR("X86_64")); + else + { + OSL_FAIL("Extension Manager: The extension supports an unknown platform. " + "Check the platform element in the description.xml"); + ret = false; + } + return ret; + } + +} // anon namespace +//============================================================================= + +OUString const & getPlatformString() +{ + return StrPlatform::get(); +} + +bool platform_fits( OUString const & platform_string ) +{ + sal_Int32 index = 0; + for (;;) + { + const OUString token( + platform_string.getToken( 0, ',', index ).trim() ); + // check if this platform: + if (token.equalsIgnoreAsciiCase( StrPlatform::get() ) || + (token.indexOf( '_' ) < 0 && /* check OS part only */ + token.equalsIgnoreAsciiCase( StrOperatingSystem::get() ))) + { + return true; + } + if (index < 0) + break; + } + return false; +} + +bool hasValidPlatform( css::uno::Sequence<OUString> const & platformStrings) +{ + bool ret = false; + for (sal_Int32 i = 0; i < platformStrings.getLength(); i++) + { + if (isValidPlatform(platformStrings[i])) + { + ret = true; + break; + } + } + return ret; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_resource.cxx b/desktop/source/deployment/misc/dp_resource.cxx new file mode 100644 index 000000000000..a20f1b3c56d8 --- /dev/null +++ b/desktop/source/deployment/misc/dp_resource.cxx @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_misc.h" +#include "dp_resource.h" +#include "osl/module.hxx" +#include "osl/mutex.hxx" +#include "rtl/ustring.h" +#include "cppuhelper/implbase1.hxx" +#include "unotools/configmgr.hxx" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace dp_misc { +namespace { + +struct OfficeLocale : + public rtl::StaticWithInit<OUString, OfficeLocale> { + const OUString operator () () { + OUString slang; + if (! (::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::LOCALE ) >>= slang)) + throw RuntimeException( OUSTR("Cannot determine language!"), 0 ); + //fallback, the locale is currently only set when the user starts the + //office for the first time. + if (slang.getLength() == 0) + slang = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en-US")); + return slang; + } +}; + +struct DeploymentResMgr : public rtl::StaticWithInit< + ResMgr *, DeploymentResMgr> { + ResMgr * operator () () { + return ResMgr::CreateResMgr( "deployment", getOfficeLocale() ); + } +}; + +osl::Mutex s_mutex; + +} // anon namespace + +//============================================================================== +ResId getResId( sal_uInt16 id ) +{ + const osl::MutexGuard guard( s_mutex ); + return ResId( id, *DeploymentResMgr::get() ); +} + +//============================================================================== +String getResourceString( sal_uInt16 id ) +{ + const osl::MutexGuard guard( s_mutex ); + String ret( ResId( id, *DeploymentResMgr::get() ) ); + if (ret.SearchAscii( "%PRODUCTNAME" ) != STRING_NOTFOUND) { + static String s_brandName; + if (s_brandName.Len() == 0) { + OUString brandName( + ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTNAME ).get<OUString>() ); + s_brandName = brandName; + } + ret.SearchAndReplaceAllAscii( "%PRODUCTNAME", s_brandName ); + } + return ret; +} + +//throws an Exception on failure +//primary subtag 2 or three letters(A-Z, a-z), i or x +void checkPrimarySubtag(::rtl::OUString const & tag) +{ + sal_Int32 len = tag.getLength(); + sal_Unicode const * arLang = tag.getStr(); + if (len < 1 || len > 3) + throw Exception(OUSTR("Invalid language string."), 0); + + if (len == 1 + && (arLang[0] != 'i' && arLang[0] != 'x')) + throw Exception(OUSTR("Invalid language string."), 0); + + if (len == 2 || len == 3) + { + for (sal_Int32 i = 0; i < len; i++) + { + if ( !((arLang[i] >= 'A' && arLang[i] <= 'Z') + || (arLang[i] >= 'a' && arLang[i] <= 'z'))) + { + throw Exception(OUSTR("Invalid language string."), 0); + } + } + } +} + +//throws an Exception on failure +//second subtag 2 letter country code or 3-8 letter other code(A-Z, a-z, 0-9) +void checkSecondSubtag(::rtl::OUString const & tag, bool & bIsCountry) +{ + sal_Int32 len = tag.getLength(); + sal_Unicode const * arLang = tag.getStr(); + if (len < 2 || len > 8) + throw Exception(OUSTR("Invalid language string."), 0); + //country code + bIsCountry = false; + if (len == 2) + { + for (sal_Int32 i = 0; i < 2; i++) + { + if (!( (arLang[i] >= 'A' && arLang[i] <= 'Z') + || (arLang[i] >= 'a' && arLang[i] <= 'z'))) + { + throw Exception(OUSTR("Invalid language string."), 0); + } + } + bIsCountry = true; + } + + if (len > 2) + { + for (sal_Int32 i = 0; i < len; i++) + { + if (!( (arLang[i] >= 'A' && arLang[i] <= 'Z') + || (arLang[i] >= 'a' && arLang[i] <= 'z') + || (arLang[i] >= '0' && arLang[i] <= '9') )) + { + throw Exception(OUSTR("Invalid language string."), 0); + } + } + } +} + +void checkThirdSubtag(::rtl::OUString const & tag) +{ + sal_Int32 len = tag.getLength(); + sal_Unicode const * arLang = tag.getStr(); + if (len < 1 || len > 8) + throw Exception(OUSTR("Invalid language string."), 0); + + for (sal_Int32 i = 0; i < len; i++) + { + if (!( (arLang[i] >= 'A' && arLang[i] <= 'Z') + || (arLang[i] >= 'a' && arLang[i] <= 'z') + || (arLang[i] >= '0' && arLang[i] <= '9') )) + { + throw Exception(OUSTR("Invalid language string."), 0); + } + } +} + +//============================================================================= + +//We parse the string acording to RFC 3066 +//We only use the primary sub-tag and two subtags. That is lang-country-variant +//We do some simple tests if the string is correct. Actually this should do a +//validating parser +//We may have the case that there is no country tag, for example en-welsh +::com::sun::star::lang::Locale toLocale( ::rtl::OUString const & slang ) +{ + OUString _sLang = slang.trim(); + ::com::sun::star::lang::Locale locale; + sal_Int32 nIndex = 0; + OUString lang = _sLang.getToken( 0, '-', nIndex ); + checkPrimarySubtag(lang); + locale.Language = lang; + OUString country = _sLang.getToken( 0, '-', nIndex ); + if (country.getLength() > 0) + { + bool bIsCountry = false; + checkSecondSubtag(country, bIsCountry); + if (bIsCountry) + { + locale.Country = country; + } + else + { + locale.Variant = country; + } + } + if (locale.Variant.getLength() == 0) + { + OUString variant = _sLang.getToken( 0, '-', nIndex ); + if (variant.getLength() > 0) + { + checkThirdSubtag(variant); + locale.Variant = variant; + } + } + + return locale; +} + +//============================================================================== +lang::Locale getOfficeLocale() +{ + return toLocale(OfficeLocale::get()); +} + +::rtl::OUString getOfficeLocaleString() +{ + return OfficeLocale::get(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_ucb.cxx b/desktop/source/deployment/misc/dp_ucb.cxx new file mode 100644 index 000000000000..fa3896aab8c4 --- /dev/null +++ b/desktop/source/deployment/misc/dp_ucb.cxx @@ -0,0 +1,323 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_misc.hrc" +#include "dp_misc.h" +#include "dp_ucb.h" +#include "rtl/uri.hxx" +#include "rtl/ustrbuf.hxx" +#include "ucbhelper/content.hxx" +#include "xmlscript/xml_helper.hxx" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/ucb/CommandFailedException.hpp" +#include "com/sun/star/ucb/ContentInfo.hpp" +#include "com/sun/star/ucb/ContentInfoAttribute.hpp" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_misc +{ + +const OUString StrTitle::operator () () +{ + return OUSTR("Title"); +} + +//============================================================================== +bool create_ucb_content( + ::ucbhelper::Content * ret_ucbContent, OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv, + bool throw_exc ) +{ + try { + // Existense check... + // content ctor/isFolder() will throw exception in case the resource + // does not exist. + + // dilemma: no chance to use the given iahandler here, because it would + // raise no such file dialogs, else no interaction for + // passwords, ...? xxx todo + ::ucbhelper::Content ucbContent( + url, Reference<XCommandEnvironment>() ); + + ucbContent.isFolder(); + + if (ret_ucbContent != 0) + { + ucbContent.setCommandEnvironment( xCmdEnv ); + *ret_ucbContent = ucbContent; + } + return true; + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + if (throw_exc) + throw; + } + return false; +} + +//============================================================================== +bool create_folder( + ::ucbhelper::Content * ret_ucb_content, OUString const & url_, + Reference<XCommandEnvironment> const & xCmdEnv, bool throw_exc ) +{ + ::ucbhelper::Content ucb_content; + if (create_ucb_content( + &ucb_content, url_, xCmdEnv, false /* no throw */ )) + { + if (ucb_content.isFolder()) { + if (ret_ucb_content != 0) + *ret_ucb_content = ucb_content; + return true; + } + } + + OUString url( url_ ); + // xxx todo: find parent + sal_Int32 slash = url.lastIndexOf( '/' ); + if (slash < 0) { + // fallback: + url = expandUnoRcUrl( url ); + slash = url.lastIndexOf( '/' ); + } + if (slash < 0) { + // invalid: has to be at least "auth:/..." + if (throw_exc) + throw ContentCreationException( + OUSTR("Cannot create folder (invalid path): ") + url, + Reference<XInterface>(), ContentCreationError_UNKNOWN ); + return false; + } + ::ucbhelper::Content parentContent; + if (! create_folder( + &parentContent, url.copy( 0, slash ), xCmdEnv, throw_exc )) + return false; + const Any title( ::rtl::Uri::decode( url.copy( slash + 1 ), + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8 ) ); + const Sequence<ContentInfo> infos( + parentContent.queryCreatableContentsInfo() ); + for ( sal_Int32 pos = 0; pos < infos.getLength(); ++pos ) + { + // look KIND_FOLDER: + ContentInfo const & info = infos[ pos ]; + if ((info.Attributes & ContentInfoAttribute::KIND_FOLDER) != 0) + { + // make sure the only required bootstrap property is "Title": + Sequence<beans::Property> const & rProps = info.Properties; + if (rProps.getLength() != 1 || + !rProps[ 0 ].Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("Title") )) + continue; + + try { + if (parentContent.insertNewContent( + info.Type, + Sequence<OUString>( &StrTitle::get(), 1 ), + Sequence<Any>( &title, 1 ), + ucb_content )) { + if (ret_ucb_content != 0) + *ret_ucb_content = ucb_content; + return true; + } + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException &) { + // Interaction Handler already handled the error + // that has occurred... + } + catch (Exception &) { + if (throw_exc) + throw; + return false; + } + } + } + if (throw_exc) + throw ContentCreationException( + OUSTR("Cannot create folder: ") + url, + Reference<XInterface>(), ContentCreationError_UNKNOWN ); + return false; +} + +//============================================================================== +bool erase_path( OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv, + bool throw_exc ) +{ + ::ucbhelper::Content ucb_content; + if (create_ucb_content( &ucb_content, url, xCmdEnv, false /* no throw */ )) + { + try { + ucb_content.executeCommand( + OUSTR("delete"), Any( true /* delete physically */ ) ); + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + if (throw_exc) + throw; + return false; + } + } + return true; +} + +//============================================================================== +::rtl::ByteSequence readFile( ::ucbhelper::Content & ucb_content ) +{ + ::rtl::ByteSequence bytes; + Reference<io::XOutputStream> xStream( + ::xmlscript::createOutputStream( &bytes ) ); + if (! ucb_content.openStream( xStream )) + throw RuntimeException( + OUSTR( + "::ucbhelper::Content::openStream( XOutputStream ) failed!"), + 0 ); + return bytes; +} + +//============================================================================== +bool readLine( OUString * res, OUString const & startingWith, + ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc ) +{ + // read whole file: + ::rtl::ByteSequence bytes( readFile( ucb_content ) ); + OUString file( reinterpret_cast<sal_Char const *>(bytes.getConstArray()), + bytes.getLength(), textenc ); + sal_Int32 pos = 0; + for (;;) + { + if (file.match( startingWith, pos )) + { + ::rtl::OUStringBuffer buf; + sal_Int32 start = pos; + pos += startingWith.getLength(); + for (;;) + { + pos = file.indexOf( LF, pos ); + if (pos < 0) { // EOF + buf.append( file.copy( start ) ); + } + else + { + if (pos > 0 && file[ pos - 1 ] == CR) + { + // consume extra CR + buf.append( file.copy( start, pos - start - 1 ) ); + ++pos; + } + else + buf.append( file.copy( start, pos - start ) ); + ++pos; // consume LF + // check next line: + if (pos < file.getLength() && + (file[ pos ] == ' ' || file[ pos ] == '\t')) + { + buf.append( static_cast<sal_Unicode>(' ') ); + ++pos; + start = pos; + continue; + } + } + break; + } + *res = buf.makeStringAndClear(); + return true; + } + // next line: + sal_Int32 next_lf = file.indexOf( LF, pos ); + if (next_lf < 0) // EOF + break; + pos = next_lf + 1; + } + return false; +} + +bool readProperties( ::std::list< ::std::pair< ::rtl::OUString, ::rtl::OUString> > & out_result, + ::ucbhelper::Content & ucb_content ) +{ + // read whole file: + ::rtl::ByteSequence bytes( readFile( ucb_content ) ); + OUString file( reinterpret_cast<sal_Char const *>(bytes.getConstArray()), + bytes.getLength(), RTL_TEXTENCODING_UTF8); + sal_Int32 pos = 0; + + for (;;) + { + + ::rtl::OUStringBuffer buf; + sal_Int32 start = pos; + + bool bEOF = false; + pos = file.indexOf( LF, pos ); + if (pos < 0) { // EOF + buf.append( file.copy( start ) ); + bEOF = true; + } + else + { + if (pos > 0 && file[ pos - 1 ] == CR) + // consume extra CR + buf.append( file.copy( start, pos - start - 1 ) ); + else + buf.append( file.copy( start, pos - start ) ); + pos++; + } + OUString aLine = buf.makeStringAndClear(); + + sal_Int32 posEqual = aLine.indexOf('='); + if (posEqual > 0 && (posEqual + 1) < aLine.getLength()) + { + OUString name = aLine.copy(0, posEqual); + OUString value = aLine.copy(posEqual + 1); + out_result.push_back(::std::make_pair(name, value)); + } + + if (bEOF) + break; + } + return false; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_update.cxx b/desktop/source/deployment/misc/dp_update.cxx new file mode 100644 index 000000000000..8aee216e44cc --- /dev/null +++ b/desktop/source/deployment/misc/dp_update.cxx @@ -0,0 +1,425 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_update.hxx" +#include "dp_version.hxx" +#include "dp_identifier.hxx" +#include "dp_descriptioninfoset.hxx" + +#include "rtl/bootstrap.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; +using ::rtl::OString; + + +namespace dp_misc { +namespace { + +int determineHighestVersion( + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + int index = 0; + OUString greatest = userVersion; + if (dp_misc::compareVersions(sharedVersion, greatest) == dp_misc::GREATER) + { + index = 1; + greatest = sharedVersion; + } + if (dp_misc::compareVersions(bundledVersion, greatest) == dp_misc::GREATER) + { + index = 2; + greatest = bundledVersion; + } + if (dp_misc::compareVersions(onlineVersion, greatest) == dp_misc::GREATER) + { + index = 3; + } + return index; +} + +Sequence< Reference< xml::dom::XElement > > +getUpdateInformation( Reference<deployment::XUpdateInformationProvider > const & updateInformation, + Sequence< OUString > const & urls, + OUString const & identifier, + uno::Any & out_error) +{ + try { + return updateInformation->getUpdateInformation(urls, identifier); + } catch (uno::RuntimeException &) { + throw; + } catch (ucb::CommandFailedException & e) { + out_error = e.Reason; + } catch (ucb::CommandAbortedException &) { + } catch (uno::Exception & e) { + out_error = uno::makeAny(e); + } + return + Sequence<Reference< xml::dom::XElement > >(); +} + +void getOwnUpdateInfos( + Reference<uno::XComponentContext> const & xContext, + Reference<deployment::XUpdateInformationProvider > const & updateInformation, + UpdateInfoMap& inout_map, std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors, + bool & out_allFound) +{ + bool allHaveOwnUpdateInformation = true; + for (UpdateInfoMap::iterator i = inout_map.begin(); i != inout_map.end(); ++i) + { + OSL_ASSERT(i->second.extension.is()); + Sequence<OUString> urls(i->second.extension->getUpdateInformationURLs()); + if (urls.getLength()) + { + const OUString id = dp_misc::getIdentifier(i->second.extension); + uno::Any anyError; + //It is unclear from the idl if there can be a null reference returned. + //However all valid information should be the same + Sequence<Reference< xml::dom::XElement > > + infos(getUpdateInformation(updateInformation, urls, id, anyError)); + if (anyError.hasValue()) + out_errors.push_back(std::make_pair(i->second.extension, anyError)); + + for (sal_Int32 j = 0; j < infos.getLength(); ++j) + { + dp_misc::DescriptionInfoset infoset( + xContext, + Reference< xml::dom::XNode >(infos[j], UNO_QUERY_THROW)); + if (!infoset.hasDescription()) + continue; + boost::optional< OUString > id2(infoset.getIdentifier()); + if (!id2) + continue; + OSL_ASSERT(*id2 == id); + if (*id2 == id) + { + i->second.version = infoset.getVersion(); + i->second.info = Reference< xml::dom::XNode >( + infos[j], UNO_QUERY_THROW); + } + break; + } + } + else + { + allHaveOwnUpdateInformation &= false; + } + } + out_allFound = allHaveOwnUpdateInformation; +} + +void getDefaultUpdateInfos( + Reference<uno::XComponentContext> const & xContext, + Reference<deployment::XUpdateInformationProvider > const & updateInformation, + UpdateInfoMap& inout_map, + std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors) +{ + const rtl::OUString sDefaultURL(dp_misc::getExtensionDefaultUpdateURL()); + OSL_ASSERT(sDefaultURL.getLength()); + + Any anyError; + Sequence< Reference< xml::dom::XElement > > + infos( + getUpdateInformation( + updateInformation, + Sequence< OUString >(&sDefaultURL, 1), OUString(), anyError)); + if (anyError.hasValue()) + out_errors.push_back(std::make_pair(Reference<deployment::XPackage>(), anyError)); + for (sal_Int32 i = 0; i < infos.getLength(); ++i) + { + Reference< xml::dom::XNode > node(infos[i], UNO_QUERY_THROW); + dp_misc::DescriptionInfoset infoset(xContext, node); + boost::optional< OUString > id(infoset.getIdentifier()); + if (!id) { + continue; + } + UpdateInfoMap::iterator j = inout_map.find(*id); + if (j != inout_map.end()) + { + //skip those extension which provide its own update urls + if (j->second.extension->getUpdateInformationURLs().getLength()) + continue; + OUString v(infoset.getVersion()); + //look for the highest version in the online repository + if (dp_misc::compareVersions(v, j->second.version) == + dp_misc::GREATER) + { + j->second.version = v; + j->second.info = node; + } + } + } +} + +bool containsBundledOnly(Sequence<Reference<deployment::XPackage> > const & sameIdExtensions) +{ + OSL_ASSERT(sameIdExtensions.getLength() == 3); + return !sameIdExtensions[0].is() && !sameIdExtensions[1].is() && sameIdExtensions[2].is(); +} + +/** Returns true if the list of extensions are bundled extensions and there are no + other extensions with the same identifier in the shared or user repository. + If extensionList is NULL, then it is checked if there are only bundled extensions. +*/ +bool onlyBundledExtensions( + Reference<deployment::XExtensionManager> const & xExtMgr, + std::vector< Reference<deployment::XPackage > > const * extensionList) +{ + OSL_ASSERT(xExtMgr.is()); + bool onlyBundled = true; + if (extensionList) + { + typedef std::vector<Reference<deployment::XPackage > >::const_iterator CIT; + for (CIT i(extensionList->begin()), aEnd(extensionList->end()); onlyBundled && i != aEnd; ++i) + { + Sequence<Reference<deployment::XPackage> > seqExt = xExtMgr->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(*i), (*i)->getName(), Reference<ucb::XCommandEnvironment>()); + + onlyBundled = containsBundledOnly(seqExt); + } + } + else + { + const uno::Sequence< uno::Sequence< Reference<deployment::XPackage > > > seqAllExt = + xExtMgr->getAllExtensions(Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>()); + + for (int pos(0), nLen(seqAllExt.getLength()); onlyBundled && pos != nLen; ++pos) + { + onlyBundled = containsBundledOnly(seqAllExt[pos]); + } + } + return onlyBundled; +} + +} // anon namespace + + +OUString getExtensionDefaultUpdateURL() +{ + ::rtl::OUString sUrl( + RTL_CONSTASCII_USTRINGPARAM( + "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") + ":Version:ExtensionUpdateURL}")); + ::rtl::Bootstrap::expandMacros(sUrl); + return sUrl; +} + +/* returns the index of the greatest version, starting with 0 + + */ +UPDATE_SOURCE isUpdateUserExtension( + bool bReadOnlyShared, + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE; + if (bReadOnlyShared) + { + if (userVersion.getLength()) + { + int index = determineHighestVersion( + userVersion, sharedVersion, bundledVersion, onlineVersion); + if (index == 1) + retVal = UPDATE_SOURCE_SHARED; + else if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + else if (sharedVersion.getLength()) + { + int index = determineHighestVersion( + OUString(), sharedVersion, bundledVersion, onlineVersion); + if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + + } + } + else + { + if (userVersion.getLength()) + { + int index = determineHighestVersion( + userVersion, sharedVersion, bundledVersion, onlineVersion); + if (index == 1) + retVal = UPDATE_SOURCE_SHARED; + else if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + } + + return retVal; +} + +UPDATE_SOURCE isUpdateSharedExtension( + bool bReadOnlyShared, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + if (bReadOnlyShared) + return UPDATE_SOURCE_NONE; + UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE; + + if (sharedVersion.getLength()) + { + int index = determineHighestVersion( + OUString(), sharedVersion, bundledVersion, onlineVersion); + if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + return retVal; +} + +Reference<deployment::XPackage> +getExtensionWithHighestVersion( + Sequence<Reference<deployment::XPackage> > const & seqExt) +{ + if (seqExt.getLength() == 0) + return Reference<deployment::XPackage>(); + + Reference<deployment::XPackage> greatest; + sal_Int32 len = seqExt.getLength(); + + for (sal_Int32 i = 0; i < len; i++) + { + if (!greatest.is()) + { + greatest = seqExt[i]; + continue; + } + Reference<deployment::XPackage> const & current = seqExt[i]; + //greatest has a value + if (! current.is()) + continue; + + if (dp_misc::compareVersions(current->getVersion(), greatest->getVersion()) == dp_misc::GREATER) + greatest = current; + } + return greatest; +} + +UpdateInfo::UpdateInfo( Reference< deployment::XPackage> const & ext): +extension(ext) +{ +} + + + +UpdateInfoMap getOnlineUpdateInfos( + Reference<uno::XComponentContext> const &xContext, + Reference<deployment::XExtensionManager> const & xExtMgr, + Reference<deployment::XUpdateInformationProvider > const & updateInformation, + std::vector<Reference<deployment::XPackage > > const * extensionList, + std::vector<std::pair< Reference<deployment::XPackage>, uno::Any> > & out_errors) +{ + OSL_ASSERT(xExtMgr.is()); + UpdateInfoMap infoMap; + if (!xExtMgr.is() || onlyBundledExtensions(xExtMgr, extensionList)) + return infoMap; + + if (!extensionList) + { + const uno::Sequence< uno::Sequence< Reference<deployment::XPackage > > > seqAllExt = xExtMgr->getAllExtensions( + Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>()); + + //fill the UpdateInfoMap. key = extension identifier, value = UpdateInfo + for (int pos = seqAllExt.getLength(); pos --; ) + { + uno::Sequence<Reference<deployment::XPackage> > const & seqExt = seqAllExt[pos]; + + Reference<deployment::XPackage> extension = getExtensionWithHighestVersion(seqExt); + OSL_ASSERT(extension.is()); + + std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.insert( + UpdateInfoMap::value_type( + dp_misc::getIdentifier(extension), UpdateInfo(extension))); + OSL_ASSERT(insertRet.second == true); + (void)insertRet; + } + } + else + { + typedef std::vector<Reference<deployment::XPackage > >::const_iterator CIT; + for (CIT i = extensionList->begin(); i != extensionList->end(); ++i) + { + OSL_ASSERT(i->is()); + std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.insert( + UpdateInfoMap::value_type( + dp_misc::getIdentifier(*i), UpdateInfo(*i))); + OSL_ASSERT(insertRet.second == true); + (void)insertRet; + } + } + + //Now find the update information for the extensions which provide their own + //URLs to update information. + bool allInfosObtained = false; + getOwnUpdateInfos(xContext, updateInformation, infoMap, out_errors, allInfosObtained); + + if (!allInfosObtained) + getDefaultUpdateInfos(xContext, updateInformation, infoMap, out_errors); + return infoMap; +} +OUString getHighestVersion( + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + int index = determineHighestVersion(userVersion, sharedVersion, bundledVersion, onlineVersion); + switch (index) + { + case 0: return userVersion; + case 1: return sharedVersion; + case 2: return bundledVersion; + case 3: return onlineVersion; + default: OSL_ASSERT(0); + } + + return OUString(); +} +} //namespace dp_misc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_version.cxx b/desktop/source/deployment/misc/dp_version.cxx new file mode 100644 index 000000000000..5c563b7dafb7 --- /dev/null +++ b/desktop/source/deployment/misc/dp_version.cxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "sal/config.h" + +#include "com/sun/star/deployment/XPackage.hpp" +#include "rtl/ustring.hxx" + +#include "dp_version.hxx" + +namespace { + +namespace css = ::com::sun::star; + +::rtl::OUString getElement(::rtl::OUString const & version, ::sal_Int32 * index) +{ + while (*index < version.getLength() && version[*index] == '0') { + ++*index; + } + return version.getToken(0, '.', *index); +} + +} + +namespace dp_misc { + +::dp_misc::Order compareVersions( + ::rtl::OUString const & version1, ::rtl::OUString const & version2) +{ + for (::sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0;) { + ::rtl::OUString e1(getElement(version1, &i1)); + ::rtl::OUString e2(getElement(version2, &i2)); + if (e1.getLength() < e2.getLength()) { + return ::dp_misc::LESS; + } else if (e1.getLength() > e2.getLength()) { + return ::dp_misc::GREATER; + } else if (e1 < e2) { + return ::dp_misc::LESS; + } else if (e1 > e2) { + return ::dp_misc::GREATER; + } + } + return ::dp_misc::EQUAL; +} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/makefile.mk b/desktop/source/deployment/misc/makefile.mk new file mode 100755 index 000000000000..9c0b33d36698 --- /dev/null +++ b/desktop/source/deployment/misc/makefile.mk @@ -0,0 +1,78 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_misc +USE_DEFFILE = TRUE +ENABLE_EXCEPTIONS = TRUE +VISIBILITY_HIDDEN=TRUE + +.INCLUDE : settings.mk + +# Reduction of exported symbols: +CDEFS += -DDESKTOP_DEPLOYMENTMISC_DLLIMPLEMENTATION + +CFLAGS+= $(SYSTEM_DB_CFLAGS) + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_misc.src + +SHL1TARGET = deploymentmisc$(DLLPOSTFIX) +SHL1OBJS = \ + $(SLO)$/dp_misc.obj \ + $(SLO)$/dp_resource.obj \ + $(SLO)$/dp_identifier.obj \ + $(SLO)$/dp_interact.obj \ + $(SLO)$/dp_ucb.obj \ + $(SLO)$/db.obj \ + $(SLO)$/dp_version.obj \ + $(SLO)$/dp_descriptioninfoset.obj \ + $(SLO)$/dp_dependencies.obj \ + $(SLO)$/dp_platform.obj \ + $(SLO)$/dp_update.obj + +SHL1STDLIBS = \ + $(BERKELEYLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(TOOLSLIB) \ + $(UCBHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(XMLSCRIPTLIB) \ + $(COMPHELPERLIB) +SHL1IMPLIB = i$(SHL1TARGET) +DEF1NAME = $(SHL1TARGET) + +SLOFILES = $(SHL1OBJS) + +.INCLUDE : ..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/component/dp_compbackenddb.cxx b/desktop/source/deployment/registry/component/dp_compbackenddb.cxx new file mode 100644 index 000000000000..749ec3896e16 --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_compbackenddb.cxx @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "rtl/string.h" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" + +#include "dp_compbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/component-registry/2010" +#define NS_PREFIX "comp" +#define ROOT_ELEMENT_NAME "component-backend-db" +#define KEY_ELEMENT_NAME "component" + +namespace dp_registry { +namespace backend { +namespace component { + +ComponentBackendDb::ComponentBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +OUString ComponentBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ComponentBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString ComponentBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString ComponentBackendDb::getKeyElementName() +{ + return OUSTR(KEY_ELEMENT_NAME); +} + +void ComponentBackendDb::addEntry(::rtl::OUString const & url, Data const & data) +{ + try{ + if (!activateEntry(url)) + { + Reference<css::xml::dom::XNode> componentNode = writeKeyElement(url); + writeSimpleElement(OUSTR("java-type-library"), + OUString::valueOf((sal_Bool) data.javaTypeLibrary), + componentNode); + + writeSimpleList( + data.implementationNames, + OUSTR("implementation-names"), + OUSTR("name"), + componentNode); + + writeVectorOfPair( + data.singletons, + OUSTR("singletons"), + OUSTR("item"), + OUSTR("key"), + OUSTR("value"), + componentNode); + + save(); + } + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +ComponentBackendDb::Data ComponentBackendDb::getEntry(::rtl::OUString const & url) +{ + try + { + ComponentBackendDb::Data retData; + Reference<css::xml::dom::XNode> aNode = getKeyElement(url); + if (aNode.is()) + { + bool bJava = readSimpleElement(OUSTR("java-type-library"), aNode) + .equals(OUSTR("true")) ? true : false; + retData.javaTypeLibrary = bJava; + + retData.implementationNames = + readList( + aNode, + OUSTR("implementation-names"), + OUSTR("name")); + + retData.singletons = + readVectorOfPair( + aNode, + OUSTR("singletons"), + OUSTR("item"), + OUSTR("key"), + OUSTR("value")); + } + return retData; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + + +} // namespace bundle +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/component/dp_compbackenddb.hxx b/desktop/source/deployment/registry/component/dp_compbackenddb.hxx new file mode 100644 index 000000000000..2e0e39eea29c --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_compbackenddb.hxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_COMPBACKENDDB_HXX +#define INCLUDED_DP_COMPBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "rtl/string.hxx" +#include <vector> +#include <list> +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace xml { namespace dom { + class XDocument; + class XNode; + }} + namespace xml { namespace xpath { + class XXPathAPI; + }} +}}} + +namespace dp_registry { +namespace backend { +namespace component { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + The format looks like this: + +<?xml version="1.0"?> +<component-backend-db xmlns="http://openoffice.org/extensionmanager/component-registry/2010"> + <component url="vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages/5CD5.tmp_/leaves1.oxt/extensionoptions.jar"> + <name>FileName</name> + <java-type-library>true</java-type-library> + <implementation-names> + <name>com.sun.star.comp.extensionoptions.OptionsEventHandler$_OptionsEventHandler</name> + ... + </implementation-names> + <singletons> + <item> + <key>com.sun.star.java.theJavaVirtualMachine</key> + <value>com.sun.star.java.JavaVirtualMachine</value> + </item> + ... + </singletons> + </component> + + <component ...> + ... +</component-backend-db> + */ +class ComponentBackendDb: public dp_registry::backend::BackendDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + virtual ::rtl::OUString getNSPrefix(); + virtual ::rtl::OUString getRootElementName(); + virtual ::rtl::OUString getKeyElementName(); + +public: + struct Data + { + Data(): javaTypeLibrary(false) {}; + + ::std::list< ::rtl::OUString> implementationNames; + /* every singleton has a key and a value + */ + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString> >singletons; + bool javaTypeLibrary; + }; + +public: + + ComponentBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + + void addEntry(::rtl::OUString const & url, Data const & data); + + Data getEntry(::rtl::OUString const & url); + + +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/component/dp_component.cxx b/desktop/source/deployment/registry/component/dp_component.cxx new file mode 100644 index 000000000000..6bf37364803f --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_component.cxx @@ -0,0 +1,1999 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_component.hrc" +#include "dp_backend.h" +#include "dp_platform.hxx" +#include "dp_ucb.h" +#include "rtl/string.hxx" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/uri.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "ucbhelper/content.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/sequence.hxx" +#include "xmlscript/xml_helper.hxx" +#include "svl/inettype.hxx" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/container/XNameContainer.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XSet.hpp" +#include "com/sun/star/registry/XSimpleRegistry.hpp" +#include "com/sun/star/registry/XImplementationRegistration.hpp" +#include "com/sun/star/loader/XImplementationLoader.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/util/XMacroExpander.hpp" +#include <list> +#include <boost/unordered_map.hpp> +#include <vector> +#include <memory> +#include <algorithm> +#include "dp_compbackenddb.hxx" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; +namespace css = com::sun::star; + +namespace dp_registry { +namespace backend { +namespace component { +namespace { + +typedef ::std::list<OUString> t_stringlist; +typedef ::std::vector< ::std::pair<OUString, OUString> > t_stringpairvec; + +#define IMPLEMENTATION_NAME "com.sun.star.comp.deployment.component.PackageRegistryBackend" + +/** return a vector of bootstrap variables which have been provided + as command arguments. +*/ +::std::vector<OUString> getCmdBootstrapVariables() +{ + ::std::vector<OUString> ret; + sal_uInt32 count = osl_getCommandArgCount(); + for (sal_uInt32 i = 0; i < count; i++) + { + OUString arg; + osl_getCommandArg(i, &arg.pData); + if (arg.matchAsciiL("-env:", 5)) + ret.push_back(arg); + } + return ret; +} + +bool jarManifestHeaderPresent( + OUString const & url, OUString const & name, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.zip://") ); + buf.append( + ::rtl::Uri::encode( + url, rtl_UriCharClassRegName, rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/META-INF/MANIFEST.MF") ); + ::ucbhelper::Content manifestContent; + OUString line; + return + create_ucb_content( + &manifestContent, buf.makeStringAndClear(), xCmdEnv, + false /* no throw */ ) + && readLine( &line, name, manifestContent, RTL_TEXTENCODING_ASCII_US ); +} + +//============================================================================== +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + class ComponentPackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + const OUString m_loader; + + enum reg { + REG_UNINIT, REG_VOID, REG_REGISTERED, REG_NOT_REGISTERED, REG_MAYBE_REGISTERED + } m_registered; + + void getComponentInfo( + ComponentBackendDb::Data * data, + std::vector< css::uno::Reference< css::uno::XInterface > > * + factories, + Reference<XComponentContext> const & xContext ); + + virtual void SAL_CALL disposing(); + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + const Reference<registry::XSimpleRegistry> getRDB() const; + + //Provides the read-only registry (e.g. not the one based on the duplicated + //rdb files + const Reference<registry::XSimpleRegistry> getRDB_RO() const; + + public: + ComponentPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + OUString const & loader, bool bRemoved, + OUString const & identifier); + }; + friend class ComponentPackageImpl; + + class ComponentsPackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + public: + ComponentsPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, OUString const & identifier); + }; + friend class ComponentsPackageImpl; + + class TypelibraryPackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + const bool m_jarFile; + Reference<container::XHierarchicalNameAccess> m_xTDprov; + + virtual void SAL_CALL disposing(); + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + public: + TypelibraryPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool jarFile, bool bRemoved, + OUString const & identifier); + }; + friend class TypelibraryPackageImpl; + + /** Serves for unregistering packages that were registered on a + different platform. This can happen if one has remotely mounted + /home, for example. + */ + class OtherPlatformPackageImpl : public ::dp_registry::backend::Package + { + public: + OtherPlatformPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, OUString const & identifier, OUString const& rPlatform); + + private: + BackendImpl * getMyBackend() const; + + const Reference<registry::XSimpleRegistry> impl_openRDB() const; + const Reference<XInterface> impl_createInstance(OUString const& rService) const; + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + private: + OUString const m_aPlatform; + }; + friend class OtherPlatformPackageImpl; + + t_stringlist m_jar_typelibs; + t_stringlist m_rdb_typelibs; + t_stringlist m_components; + + enum RcItem { RCITEM_JAR_TYPELIB, RCITEM_RDB_TYPELIB, RCITEM_COMPONENTS }; + + t_stringlist & getRcItemList( RcItem kind ) { + switch (kind) + { + case RCITEM_JAR_TYPELIB: + return m_jar_typelibs; + case RCITEM_RDB_TYPELIB: + return m_rdb_typelibs; + default: // case RCITEM_COMPONENTS + return m_components; + } + } + + bool m_unorc_inited; + bool m_unorc_modified; + bool bSwitchedRdbFiles; + + typedef ::boost::unordered_map< OUString, Reference<XInterface>, + ::rtl::OUStringHash > t_string2object; + t_string2object m_backendObjects; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ); + + virtual void SAL_CALL disposing(); + + const Reference<deployment::XPackageTypeInfo> m_xDynComponentTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xJavaComponentTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xPythonComponentTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xComponentsTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xRDBTypelibTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xJavaTypelibTypeInfo; + Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + + OUString m_commonRDB; + OUString m_nativeRDB; + + //URLs of the read-only rdbs (e.g. not the ones of the duplicated files) + OUString m_commonRDB_RO; + OUString m_nativeRDB_RO; + + std::auto_ptr<ComponentBackendDb> m_backendDb; + + void addDataToDb(OUString const & url, ComponentBackendDb::Data const & data); + ComponentBackendDb::Data readDataFromDb(OUString const & url); + void revokeEntryFromDb(OUString const & url); + + + //These rdbs are for writing new service entries. The rdb files are copies + //which are created when services are added or removed. + Reference<registry::XSimpleRegistry> m_xCommonRDB; + Reference<registry::XSimpleRegistry> m_xNativeRDB; + + //These rdbs are created on the read-only rdbs which are already used + //by UNO since the startup of the current session. + Reference<registry::XSimpleRegistry> m_xCommonRDB_RO; + Reference<registry::XSimpleRegistry> m_xNativeRDB_RO; + + + void unorc_verify_init( Reference<XCommandEnvironment> const & xCmdEnv ); + void unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv ); + + Reference<XInterface> getObject( OUString const & id ); + Reference<XInterface> insertObject( + OUString const & id, Reference<XInterface> const & xObject ); + void releaseObject( OUString const & id ); + + bool addToUnoRc( RcItem kind, OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv ); + bool removeFromUnoRc( RcItem kind, OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv ); + bool hasInUnoRc( RcItem kind, OUString const & url ); + + css::uno::Reference< css::registry::XRegistryKey > openRegistryKey( + css::uno::Reference< css::registry::XRegistryKey > const & base, + rtl::OUString const & path); + + void extractComponentData( + css::uno::Reference< css::uno::XComponentContext > const & context, + css::uno::Reference< css::registry::XRegistryKey > const & registry, + ComponentBackendDb::Data * data, + std::vector< css::uno::Reference< css::uno::XInterface > > * factories, + css::uno::Reference< css::loader::XImplementationLoader > const * + componentLoader, + rtl::OUString const * componentUrl); + + void componentLiveInsertion( + ComponentBackendDb::Data const & data, + std::vector< css::uno::Reference< css::uno::XInterface > > const & + factories); + + void componentLiveRemoval(ComponentBackendDb::Data const & data); + +public: + BackendImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + + virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) + throw (deployment::DeploymentException, + uno::RuntimeException); + + using PackageRegistryBackend::disposing; + + //Will be called from ComponentPackageImpl + void initServiceRdbFiles(); + + //Creates the READ ONLY registries (m_xCommonRDB_RO,m_xNativeRDB_RO) + void initServiceRdbFiles_RO(); +}; + +//______________________________________________________________________________ + +BackendImpl::ComponentPackageImpl::ComponentPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + OUString const & loader, bool bRemoved, + OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier), + m_loader( loader ), + m_registered( REG_UNINIT ) +{} + +const Reference<registry::XSimpleRegistry> +BackendImpl::ComponentPackageImpl::getRDB() const +{ + BackendImpl * that = getMyBackend(); + + //Late "initialization" of the services rdb files + //This is to prevent problems when running several + //instances of OOo with root rights in parallel. This + //would otherwise cause problems when copying the rdbs. + //See http://qa.openoffice.org/issues/show_bug.cgi?id=99257 + { + const ::osl::MutexGuard guard( getMutex() ); + if (!that->bSwitchedRdbFiles) + { + that->bSwitchedRdbFiles = true; + that->initServiceRdbFiles(); + } + } + if (m_loader.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.loader.SharedLibrary") )) + return that->m_xNativeRDB; + else + return that->m_xCommonRDB; +} + +//Returns the read only RDB. +const Reference<registry::XSimpleRegistry> +BackendImpl::ComponentPackageImpl::getRDB_RO() const +{ + BackendImpl * that = getMyBackend(); + + if (m_loader.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.loader.SharedLibrary") )) + return that->m_xNativeRDB_RO; + else + return that->m_xCommonRDB_RO; +} + +BackendImpl * BackendImpl::ComponentPackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //Throws a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<ComponentPackageImpl *>(this))); + } + return pBackend; +} + + +//______________________________________________________________________________ +void BackendImpl::ComponentPackageImpl::disposing() +{ + Package::disposing(); +} + +//______________________________________________________________________________ +void BackendImpl::TypelibraryPackageImpl::disposing() +{ + m_xTDprov.clear(); + Package::disposing(); +} + +//______________________________________________________________________________ +void BackendImpl::disposing() +{ + try { + m_backendObjects = t_string2object(); + if (m_xNativeRDB.is()) { + m_xNativeRDB->close(); + m_xNativeRDB.clear(); + } + if (m_xCommonRDB.is()) { + m_xCommonRDB->close(); + m_xCommonRDB.clear(); + } + unorc_flush( Reference<XCommandEnvironment>() ); + + PackageRegistryBackend::disposing(); + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( + OUSTR("caught unexpected exception while disposing..."), + static_cast<OWeakObject *>(this), exc ); + } +} + + +void BackendImpl::initServiceRdbFiles() +{ + const Reference<XCommandEnvironment> xCmdEnv; + + ::ucbhelper::Content cacheDir( getCachePath(), xCmdEnv ); + ::ucbhelper::Content oldRDB; + // switch common rdb: + if (m_commonRDB_RO.getLength() > 0) + { + create_ucb_content( + &oldRDB, makeURL( getCachePath(), m_commonRDB_RO), + xCmdEnv, false /* no throw */ ); + } + m_commonRDB = m_commonRDB_RO.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("common.rdb") ) + ? OUSTR("common_.rdb") : OUSTR("common.rdb"); + if (oldRDB.get().is()) + { + if (! cacheDir.transferContent( + oldRDB, ::ucbhelper::InsertOperation_COPY, + m_commonRDB, NameClash::OVERWRITE )) + { + + throw RuntimeException( + OUSTR("UCB transferContent() failed!"), 0 ); + } + oldRDB = ::ucbhelper::Content(); + } + // switch native rdb: + if (m_nativeRDB_RO.getLength() > 0) + { + create_ucb_content( + &oldRDB, makeURL(getCachePath(), m_nativeRDB_RO), + xCmdEnv, false /* no throw */ ); + } + const OUString plt_rdb( getPlatformString() + OUSTR(".rdb") ); + const OUString plt_rdb_( getPlatformString() + OUSTR("_.rdb") ); + m_nativeRDB = m_nativeRDB_RO.equals( plt_rdb ) ? plt_rdb_ : plt_rdb; + if (oldRDB.get().is()) + { + if (! cacheDir.transferContent( + oldRDB, ::ucbhelper::InsertOperation_COPY, + m_nativeRDB, NameClash::OVERWRITE )) + throw RuntimeException( + OUSTR("UCB transferContent() failed!"), 0 ); + } + + // UNO is bootstrapped, flush for next process start: + m_unorc_modified = true; + unorc_flush( Reference<XCommandEnvironment>() ); + + + // common rdb for java, native rdb for shared lib components + if (m_commonRDB.getLength() > 0) { + m_xCommonRDB.set( + m_xComponentContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + m_xComponentContext ), UNO_QUERY_THROW ); + m_xCommonRDB->open( + makeURL( expandUnoRcUrl(getCachePath()), m_commonRDB ), + false, true); + } + if (m_nativeRDB.getLength() > 0) { + m_xNativeRDB.set( + m_xComponentContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + m_xComponentContext ), UNO_QUERY_THROW ); + m_xNativeRDB->open( + makeURL( expandUnoRcUrl(getCachePath()), m_nativeRDB ), + false, true); + } +} + +void BackendImpl::initServiceRdbFiles_RO() +{ + const Reference<XCommandEnvironment> xCmdEnv; + + // common rdb for java, native rdb for shared lib components + if (m_commonRDB_RO.getLength() > 0) + { + m_xCommonRDB_RO.set( + m_xComponentContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + m_xComponentContext), UNO_QUERY_THROW); + m_xCommonRDB_RO->open( + makeURL(expandUnoRcUrl(getCachePath()), m_commonRDB_RO), + sal_True, //read-only + sal_True); // create data source if necessary + } + if (m_nativeRDB_RO.getLength() > 0) + { + m_xNativeRDB_RO.set( + m_xComponentContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + m_xComponentContext), UNO_QUERY_THROW); + m_xNativeRDB_RO->open( + makeURL(expandUnoRcUrl(getCachePath()), m_nativeRDB_RO), + sal_True, //read-only + sal_True); // create data source if necessary + } +} + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : PackageRegistryBackend( args, xComponentContext ), + m_unorc_inited( false ), + m_unorc_modified( false ), + bSwitchedRdbFiles(false), + m_xDynComponentTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-component;" + "type=native;platform=") + + getPlatformString(), + OUSTR("*" SAL_DLLEXTENSION), + getResourceString(RID_STR_DYN_COMPONENT), + RID_IMG_COMPONENT) ), + m_xJavaComponentTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-component;" + "type=Java"), + OUSTR("*.jar"), + getResourceString(RID_STR_JAVA_COMPONENT), + RID_IMG_JAVA_COMPONENT) ), + m_xPythonComponentTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-component;" + "type=Python"), + OUSTR("*.py"), + getResourceString( + RID_STR_PYTHON_COMPONENT), + RID_IMG_COMPONENT ) ), + m_xComponentsTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-components"), + OUSTR("*.components"), + getResourceString(RID_STR_COMPONENTS), + RID_IMG_COMPONENT ) ), + m_xRDBTypelibTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-typelibrary;" + "type=RDB"), + OUSTR("*.rdb"), + getResourceString(RID_STR_RDB_TYPELIB), + RID_IMG_TYPELIB ) ), + m_xJavaTypelibTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-typelibrary;" + "type=Java"), + OUSTR("*.jar"), + getResourceString(RID_STR_JAVA_TYPELIB), + RID_IMG_JAVA_TYPELIB ) ), + m_typeInfos( 6 ) +{ + m_typeInfos[ 0 ] = m_xDynComponentTypeInfo; + m_typeInfos[ 1 ] = m_xJavaComponentTypeInfo; + m_typeInfos[ 2 ] = m_xPythonComponentTypeInfo; + m_typeInfos[ 3 ] = m_xComponentsTypeInfo; + m_typeInfos[ 4 ] = m_xRDBTypelibTypeInfo; + m_typeInfos[ 5 ] = m_xJavaTypelibTypeInfo; + + const Reference<XCommandEnvironment> xCmdEnv; + + if (transientMode()) + { + // in-mem rdbs: + // common rdb for java, native rdb for shared lib components + m_xCommonRDB.set( + xComponentContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + xComponentContext ), UNO_QUERY_THROW ); + m_xCommonRDB->open( OUString() /* in-mem */, + false /* ! read-only */, true /* create */ ); + m_xNativeRDB.set( + xComponentContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + xComponentContext ), UNO_QUERY_THROW ); + m_xNativeRDB->open( OUString() /* in-mem */, + false /* ! read-only */, true /* create */ ); + } + else + { + //do this before initServiceRdbFiles_RO, because it determines + //m_commonRDB and m_nativeRDB + unorc_verify_init( xCmdEnv ); + + initServiceRdbFiles_RO(); + + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new ComponentBackendDb(getComponentContext(), dbFile)); + } +} + +void BackendImpl::addDataToDb( + OUString const & url, ComponentBackendDb::Data const & data) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url, data); +} + +ComponentBackendDb::Data BackendImpl::readDataFromDb(OUString const & url) +{ + ComponentBackendDb::Data data; + if (m_backendDb.get()) + data = m_backendDb->getEntry(url); + return data; +} + +void BackendImpl::revokeEntryFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->revokeEntry(url); +} + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return m_typeInfos; +} + +void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/) + throw (deployment::DeploymentException, + uno::RuntimeException) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + OUString mediaType(mediaType_); + if (mediaType.getLength() == 0 || + mediaType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.uno-component") ) || + mediaType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.uno-typelibrary") )) + { + // detect exact media-type: + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, url, xCmdEnv )) { + const OUString title( ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(SAL_DLLEXTENSION) )) + { + mediaType = OUSTR("application/vnd.sun.star.uno-component;" + "type=native;platform=") + + getPlatformString(); + } + else if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".jar") )) + { + if (jarManifestHeaderPresent( + url, OUSTR("RegistrationClassName"), xCmdEnv )) + mediaType = OUSTR( + "application/vnd.sun.star.uno-component;type=Java"); + if (mediaType.getLength() == 0) + mediaType = OUSTR( + "application/vnd.sun.star.uno-typelibrary;type=Java"); + } + else if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".py") )) + mediaType = + OUSTR("application/vnd.sun.star.uno-component;type=Python"); + else if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".rdb") )) + mediaType = + OUSTR("application/vnd.sun.star.uno-typelibrary;type=RDB"); + } + if (mediaType.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + OUString name; + if (!bRemoved) + { + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + name = ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>(); + } + + if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.uno-component")) + { + // xxx todo: probe and evaluate component xml description + + INetContentTypeParameter const * param = params.find( + ByteString("platform") ); + bool bPlatformFits(param == 0); + String aPlatform; + if (!bPlatformFits) // platform is specified, we have to check + { + aPlatform = param->m_sValue; + bPlatformFits = platform_fits(aPlatform); + } + // If the package is being removed, do not care whether + // platform fits. We won't be using it anyway. + if (bPlatformFits || bRemoved) { + param = params.find( ByteString("type") ); + if (param != 0) + { + String const & value = param->m_sValue; + if (value.EqualsIgnoreCaseAscii("native")) { + if (bPlatformFits) + return new BackendImpl::ComponentPackageImpl( + this, url, name, m_xDynComponentTypeInfo, + OUSTR("com.sun.star.loader.SharedLibrary"), + bRemoved, identifier); + else + return new BackendImpl::OtherPlatformPackageImpl( + this, url, name, m_xDynComponentTypeInfo, + bRemoved, identifier, aPlatform); + } + if (value.EqualsIgnoreCaseAscii("Java")) { + return new BackendImpl::ComponentPackageImpl( + this, url, name, m_xJavaComponentTypeInfo, + OUSTR("com.sun.star.loader.Java2"), + bRemoved, identifier); + } + if (value.EqualsIgnoreCaseAscii("Python")) { + return new BackendImpl::ComponentPackageImpl( + this, url, name, m_xPythonComponentTypeInfo, + OUSTR("com.sun.star.loader.Python"), + bRemoved, identifier); + } + } + } + } + else if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.uno-components")) + { + INetContentTypeParameter const * param = params.find( + ByteString("platform") ); + if (param == 0 || platform_fits( param->m_sValue )) { + return new BackendImpl::ComponentsPackageImpl( + this, url, name, m_xComponentsTypeInfo, bRemoved, + identifier); + } + } + else if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.uno-typelibrary")) + { + INetContentTypeParameter const * param = params.find( + ByteString("type") ); + if (param != 0) { + String const & value = param->m_sValue; + if (value.EqualsIgnoreCaseAscii("RDB")) + { + return new BackendImpl::TypelibraryPackageImpl( + this, url, name, m_xRDBTypelibTypeInfo, + false /* rdb */, bRemoved, identifier); + } + if (value.EqualsIgnoreCaseAscii("Java")) { + return new BackendImpl::TypelibraryPackageImpl( + this, url, name, m_xJavaTypelibTypeInfo, + true /* jar */, bRemoved, identifier); + } + } + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + + +//______________________________________________________________________________ +void BackendImpl::unorc_verify_init( + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (transientMode()) + return; + const ::osl::MutexGuard guard( getMutex() ); + if (! m_unorc_inited) + { + // common rc: + ::ucbhelper::Content ucb_content; + if (create_ucb_content( + &ucb_content, + makeURL( getCachePath(), OUSTR("unorc") ), + xCmdEnv, false /* no throw */ )) + { + OUString line; + if (readLine( &line, OUSTR("UNO_JAVA_CLASSPATH="), ucb_content, + RTL_TEXTENCODING_UTF8 )) + { + sal_Int32 index = sizeof ("UNO_JAVA_CLASSPATH=") - 1; + do { + OUString token( line.getToken( 0, ' ', index ).trim() ); + if (token.getLength() > 0) + { + if (create_ucb_content( + 0, expandUnoRcTerm(token), xCmdEnv, + false /* no throw */ )) + { + //The jar file may not exist anymore if a shared or bundled + //extension was removed, but it can still be in the unorc + //After running XExtensionManager::synchronize, the unorc is + //cleaned up + m_jar_typelibs.push_back( token ); + } + } + } + while (index >= 0); + } + if (readLine( &line, OUSTR("UNO_TYPES="), ucb_content, + RTL_TEXTENCODING_UTF8 )) { + sal_Int32 index = sizeof ("UNO_TYPES=") - 1; + do { + OUString token( line.getToken( 0, ' ', index ).trim() ); + if (token.getLength() > 0) + { + if (token[ 0 ] == '?') + token = token.copy( 1 ); + if (create_ucb_content( + 0, expandUnoRcTerm(token), xCmdEnv, + false /* no throw */ )) + { + //The RDB file may not exist anymore if a shared or bundled + //extension was removed, but it can still be in the unorc. + //After running XExtensionManager::synchronize, the unorc is + //cleaned up + m_rdb_typelibs.push_back( token ); + } + } + } + while (index >= 0); + } + if (readLine( &line, OUSTR("UNO_SERVICES="), ucb_content, + RTL_TEXTENCODING_UTF8 )) + { + // The UNO_SERVICES line always has the BNF form + // "UNO_SERVICES=" + // ("?$ORIGIN/" <common-rdb>)? -- first + // "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}"? -- second + // ("?" ("BUNDLED_EXTENSIONS" | -- third + // "UNO_SHARED_PACKAGES_CACHE" | "UNO_USER_PACKAGES_CACHE") + // ...)* + // so can unambiguously be split into its thre parts: + int state = 1; + for (sal_Int32 i = RTL_CONSTASCII_LENGTH("UNO_SERVICES="); + i >= 0;) + { + rtl::OUString token(line.getToken(0, ' ', i)); + if (token.getLength() != 0) + { + if (state == 1 && + token.matchAsciiL( + RTL_CONSTASCII_STRINGPARAM("?$ORIGIN/"))) + { + m_commonRDB_RO = token.copy( + RTL_CONSTASCII_LENGTH("?$ORIGIN/")); + state = 2; + } + else if (state <= 2 && + token.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "${$ORIGIN/${_OS}_${_ARCH}rc:" + "UNO_SERVICES}"))) + { + state = 3; + } + else + { + if (token[0] == '?') + { + token = token.copy(1); + } + m_components.push_back(token); + state = 3; + } + } + } + } + + // native rc: + if (create_ucb_content( + &ucb_content, + makeURL( getCachePath(), getPlatformString() + OUSTR("rc")), + xCmdEnv, false /* no throw */ )) { + if (readLine( &line, OUSTR("UNO_SERVICES="), ucb_content, + RTL_TEXTENCODING_UTF8 )) { + m_nativeRDB_RO = line.copy( + sizeof ("UNO_SERVICES=?$ORIGIN/") - 1 ); + } + } + } + m_unorc_modified = false; + m_unorc_inited = true; + } +} + +//______________________________________________________________________________ +void BackendImpl::unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (transientMode()) + return; + if (!m_unorc_inited || !m_unorc_modified) + return; + + ::rtl::OStringBuffer buf; + + buf.append(RTL_CONSTASCII_STRINGPARAM("ORIGIN=")); + OUString sOrigin = dp_misc::makeRcTerm(m_cachePath); + ::rtl::OString osOrigin = ::rtl::OUStringToOString(sOrigin, RTL_TEXTENCODING_UTF8); + buf.append(osOrigin); + buf.append(LF); + + if (! m_jar_typelibs.empty()) + { + t_stringlist::const_iterator iPos( m_jar_typelibs.begin() ); + t_stringlist::const_iterator const iEnd( m_jar_typelibs.end() ); + buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_JAVA_CLASSPATH=") ); + while (iPos != iEnd) { + // encoded ASCII file-urls: + const ::rtl::OString item( + ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( item ); + ++iPos; + if (iPos != iEnd) + buf.append( ' ' ); + } + buf.append(LF); + } + if (! m_rdb_typelibs.empty()) + { + t_stringlist::const_iterator iPos( m_rdb_typelibs.begin() ); + t_stringlist::const_iterator const iEnd( m_rdb_typelibs.end() ); + buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_TYPES=") ); + while (iPos != iEnd) { + buf.append( '?' ); + // encoded ASCII file-urls: + const ::rtl::OString item( + ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( item ); + ++iPos; + if (iPos != iEnd) + buf.append( ' ' ); + } + buf.append(LF); + } + + // If we duplicated the common or native rdb then we must use those urls + //otherwise we use those of the original files. That is, m_commonRDB_RO and + //m_nativeRDB_RO; + OUString sCommonRDB(m_commonRDB.getLength() > 0 ? m_commonRDB : m_commonRDB_RO); + OUString sNativeRDB(m_nativeRDB.getLength() > 0 ? m_nativeRDB : m_nativeRDB_RO); + + if (sCommonRDB.getLength() > 0 || sNativeRDB.getLength() > 0 || + !m_components.empty()) + { + buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_SERVICES=") ); + bool space = false; + if (sCommonRDB.getLength() > 0) + { + buf.append( RTL_CONSTASCII_STRINGPARAM("?$ORIGIN/") ); + buf.append( ::rtl::OUStringToOString( + sCommonRDB, RTL_TEXTENCODING_ASCII_US ) ); + space = true; + } + if (sNativeRDB.getLength() > 0) + { + if (space) + { + buf.append(' '); + } + buf.append( RTL_CONSTASCII_STRINGPARAM( + "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}") ); + space = true; + + // write native rc: + ::rtl::OStringBuffer buf2; + buf2.append(RTL_CONSTASCII_STRINGPARAM("ORIGIN=")); + buf2.append(osOrigin); + buf2.append(LF); + buf2.append( RTL_CONSTASCII_STRINGPARAM("UNO_SERVICES=?$ORIGIN/") ); + buf2.append( ::rtl::OUStringToOString( + sNativeRDB, RTL_TEXTENCODING_ASCII_US ) ); + buf2.append(LF); + + const Reference<io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(buf2.getStr()), + buf2.getLength() ) ) ); + ::ucbhelper::Content ucb_content( + makeURL( getCachePath(), getPlatformString() + OUSTR("rc") ), + xCmdEnv ); + ucb_content.writeStream( xData, true /* replace existing */ ); + } + for (t_stringlist::iterator i(m_components.begin()); + i != m_components.end(); ++i) + { + if (space) + { + buf.append(' '); + } + buf.append('?'); + buf.append(rtl::OUStringToOString(*i, RTL_TEXTENCODING_UTF8)); + space = true; + } + buf.append(LF); + } + + // write unorc: + const Reference<io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(buf.getStr()), + buf.getLength() ) ) ); + ::ucbhelper::Content ucb_content( + makeURL( getCachePath(), OUSTR("unorc") ), xCmdEnv ); + ucb_content.writeStream( xData, true /* replace existing */ ); + + m_unorc_modified = false; +} + +//______________________________________________________________________________ +bool BackendImpl::addToUnoRc( RcItem kind, OUString const & url_, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + const OUString rcterm( dp_misc::makeRcTerm(url_) ); + const ::osl::MutexGuard guard( getMutex() ); + unorc_verify_init( xCmdEnv ); + t_stringlist & rSet = getRcItemList(kind); + if (::std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) { + rSet.push_front( rcterm ); // prepend to list, thus overriding + // write immediately: + m_unorc_modified = true; + unorc_flush( xCmdEnv ); + return true; + } + else + return false; +} + +//______________________________________________________________________________ +bool BackendImpl::removeFromUnoRc( + RcItem kind, OUString const & url_, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + const OUString rcterm( dp_misc::makeRcTerm(url_) ); + const ::osl::MutexGuard guard( getMutex() ); + unorc_verify_init( xCmdEnv ); + getRcItemList(kind).remove( rcterm ); + // write immediately: + m_unorc_modified = true; + unorc_flush( xCmdEnv ); + return true; +} + +//______________________________________________________________________________ +bool BackendImpl::hasInUnoRc( + RcItem kind, OUString const & url_ ) +{ + const OUString rcterm( dp_misc::makeRcTerm(url_) ); + const ::osl::MutexGuard guard( getMutex() ); + t_stringlist const & rSet = getRcItemList(kind); + return ::std::find( rSet.begin(), rSet.end(), rcterm ) != rSet.end(); +} + +css::uno::Reference< css::registry::XRegistryKey > BackendImpl::openRegistryKey( + css::uno::Reference< css::registry::XRegistryKey > const & base, + rtl::OUString const & path) +{ + OSL_ASSERT(base.is()); + css::uno::Reference< css::registry::XRegistryKey > key(base->openKey(path)); + if (!key.is()) { + throw css::deployment::DeploymentException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("missing registry entry ")) + + path + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" under ")) + + base->getKeyName()), + static_cast< OWeakObject * >(this), Any()); + } + return key; +} + +void BackendImpl::extractComponentData( + css::uno::Reference< css::uno::XComponentContext > const & context, + css::uno::Reference< css::registry::XRegistryKey > const & registry, + ComponentBackendDb::Data * data, + std::vector< css::uno::Reference< css::uno::XInterface > > * factories, + css::uno::Reference< css::loader::XImplementationLoader > const * + componentLoader, + rtl::OUString const * componentUrl) +{ + OSL_ASSERT(context.is() && registry.is() && data != 0 && factories != 0); + rtl::OUString registryName(registry->getKeyName()); + sal_Int32 prefix = registryName.getLength(); + if (!registryName.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM("/"))) { + prefix += RTL_CONSTASCII_LENGTH("/"); + } + css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > > + keys(registry->openKeys()); + css::uno::Reference< css::lang::XMultiComponentFactory > smgr( + context->getServiceManager(), css::uno::UNO_QUERY_THROW); + for (sal_Int32 i = 0; i < keys.getLength(); ++i) { + rtl::OUString name(keys[i]->getKeyName().copy(prefix)); + data->implementationNames.push_back(name); + css::uno::Reference< css::registry::XRegistryKey > singletons( + keys[i]->openKey( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UNO/SINGLETONS")))); + if (singletons.is()) { + sal_Int32 prefix2 = keys[i]->getKeyName().getLength() + + RTL_CONSTASCII_LENGTH("/UNO/SINGLETONS/"); + css::uno::Sequence< + css::uno::Reference< css::registry::XRegistryKey > > + singletonKeys(singletons->openKeys()); + for (sal_Int32 j = 0; j < singletonKeys.getLength(); ++j) { + data->singletons.push_back( + std::pair< rtl::OUString, rtl::OUString >( + singletonKeys[j]->getKeyName().copy(prefix2), name)); + } + } + css::uno::Reference< css::loader::XImplementationLoader > loader; + if (componentLoader == 0) { + rtl::OUString activator( + openRegistryKey( + keys[i], + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("UNO/ACTIVATOR")))-> + getAsciiValue()); + loader.set( + smgr->createInstanceWithContext(activator, context), + css::uno::UNO_QUERY); + if (!loader.is()) { + throw css::deployment::DeploymentException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "cannot instantiate loader ")) + + activator), + static_cast< OWeakObject * >(this), Any()); + } + } else { + OSL_ASSERT(componentLoader->is()); + loader = *componentLoader; + } + factories->push_back( + loader->activate( + name, rtl::OUString(), + (componentUrl == 0 + ? (openRegistryKey( + keys[i], + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("UNO/LOCATION")))-> + getAsciiValue()) + : *componentUrl), + keys[i])); + } +} + +void BackendImpl::componentLiveInsertion( + ComponentBackendDb::Data const & data, + std::vector< css::uno::Reference< css::uno::XInterface > > const & + factories) +{ + css::uno::Reference< css::container::XSet > set( + getComponentContext()->getServiceManager(), css::uno::UNO_QUERY_THROW); + std::vector< css::uno::Reference< css::uno::XInterface > >::const_iterator + factory(factories.begin()); + for (t_stringlist::const_iterator i(data.implementationNames.begin()); + i != data.implementationNames.end(); ++i) + { + try { + set->insert(css::uno::Any(*factory++)); + } catch (container::ElementExistException &) { + OSL_TRACE( + "implementation %s already registered", + rtl::OUStringToOString(*i, RTL_TEXTENCODING_UTF8).getStr()); + } + } + if (!data.singletons.empty()) { + css::uno::Reference< css::container::XNameContainer > + rootContext( + getComponentContext()->getValueByName( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_root"))), + css::uno::UNO_QUERY); + if (rootContext.is()) { + for (t_stringpairvec::const_iterator i(data.singletons.begin()); + i != data.singletons.end(); ++i) + { + rtl::OUString name( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/singletons/")) + + i->first); + try { + rootContext->removeByName( + name + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("/arguments"))); + } catch (container::NoSuchElementException &) {} + try { + rootContext->insertByName( + (name + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("/service"))), + css::uno::Any(i->second)); + } catch (container::ElementExistException &) { + rootContext->replaceByName( + (name + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("/service"))), + css::uno::Any(i->second)); + } + try { + rootContext->insertByName(name, css::uno::Any()); + } catch (container::ElementExistException &) { + OSL_TRACE( + "singleton %s already registered", + rtl::OUStringToOString( + i->first, RTL_TEXTENCODING_UTF8).getStr()); + rootContext->replaceByName(name, css::uno::Any()); + } + } + } + } +} + +void BackendImpl::componentLiveRemoval(ComponentBackendDb::Data const & data) { + css::uno::Reference< css::container::XSet > set( + getComponentContext()->getServiceManager(), css::uno::UNO_QUERY_THROW); + for (t_stringlist::const_iterator i(data.implementationNames.begin()); + i != data.implementationNames.end(); ++i) + { + try { + set->remove(css::uno::Any(*i)); + } catch (css::container::NoSuchElementException &) { + // ignore if factory has not been live deployed + } + } + if (!data.singletons.empty()) { + css::uno::Reference< css::container::XNameContainer > rootContext( + getComponentContext()->getValueByName( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_root"))), + css::uno::UNO_QUERY); + if (rootContext.is()) { + for (t_stringpairvec::const_iterator i(data.singletons.begin()); + i != data.singletons.end(); ++i) + { + rtl::OUString name( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/singletons/")) + + i->first); + try { + rootContext->removeByName( + name + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("/arguments"))); + rootContext->removeByName( + name + + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/service"))); + rootContext->removeByName(name); + } catch (container::NoSuchElementException &) {} + } + } + } +} + +//______________________________________________________________________________ +void BackendImpl::releaseObject( OUString const & id ) +{ + const ::osl::MutexGuard guard( getMutex() ); + m_backendObjects.erase( id ); +} + +//______________________________________________________________________________ +Reference<XInterface> BackendImpl::getObject( OUString const & id ) +{ + const ::osl::MutexGuard guard( getMutex() ); + const t_string2object::const_iterator iFind( m_backendObjects.find( id ) ); + if (iFind == m_backendObjects.end()) + return Reference<XInterface>(); + else + return iFind->second; +} + +//______________________________________________________________________________ +Reference<XInterface> BackendImpl::insertObject( + OUString const & id, Reference<XInterface> const & xObject ) +{ + const ::osl::MutexGuard guard( getMutex() ); + const ::std::pair<t_string2object::iterator, bool> insertion( + m_backendObjects.insert( t_string2object::value_type( + id, xObject ) ) ); + return insertion.first->second; +} + +//------------------------------------------------------------------------------ +Reference<XComponentContext> raise_uno_process( + Reference<XComponentContext> const & xContext, + ::rtl::Reference<AbortChannel> const & abortChannel ) +{ + OSL_ASSERT( xContext.is() ); + + ::rtl::OUString url( + Reference<util::XMacroExpander>( + xContext->getValueByName( + OUSTR("/singletons/com.sun.star.util.theMacroExpander") ), + UNO_QUERY_THROW )-> + expandMacros( OUSTR("$URE_BIN_DIR/uno") ) ); + + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno:pipe,name=") ); + OUString pipeId( generateRandomPipeId() ); + buf.append( pipeId ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM(";urp;uno.ComponentContext") ); + const OUString connectStr( buf.makeStringAndClear() ); + + // raise core UNO process to register/run a component, + // javavm service uses unorc next to executable to retrieve deployed + // jar typelibs + + ::std::vector<OUString> args; +#if OSL_DEBUG_LEVEL <= 1 + args.push_back( OUSTR("--quiet") ); +#endif + args.push_back( OUSTR("--singleaccept") ); + args.push_back( OUSTR("-u") ); + args.push_back( connectStr ); + // don't inherit from unorc: + args.push_back( OUSTR("-env:INIFILENAME=") ); + + //now add the bootstrap variables which were supplied on the command line + ::std::vector<OUString> bootvars = getCmdBootstrapVariables(); + args.insert(args.end(), bootvars.begin(), bootvars.end()); + + oslProcess hProcess = raiseProcess( + url, comphelper::containerToSequence(args) ); + try { + return Reference<XComponentContext>( + resolveUnoURL( connectStr, xContext, abortChannel.get() ), + UNO_QUERY_THROW ); + } + catch (...) { + // try to terminate process: + if ( osl_terminateProcess( hProcess ) != osl_Process_E_None ) + { + OSL_ASSERT( false ); + } + throw; + } +} + +//------------------------------------------------------------------------------ +void BackendImpl::ComponentPackageImpl::getComponentInfo( + ComponentBackendDb::Data * data, + std::vector< css::uno::Reference< css::uno::XInterface > > * factories, + Reference<XComponentContext> const & xContext ) +{ + const Reference<loader::XImplementationLoader> xLoader( + xContext->getServiceManager()->createInstanceWithContext( + m_loader, xContext ), UNO_QUERY ); + if (! xLoader.is()) + { + throw css::deployment::DeploymentException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("cannot instantiate loader ")) + + m_loader), + static_cast< OWeakObject * >(this), Any()); + } + + // HACK: highly dependent on stoc/source/servicemanager + // and stoc/source/implreg implementation which rely on the same + // services.rdb format! + // .../UNO/LOCATION and .../UNO/ACTIVATOR appear not to be written by + // writeRegistryInfo, however, but are knwon, fixed values here, so + // can be passed into extractComponentData + rtl::OUString url(getURL()); + const Reference<registry::XSimpleRegistry> xMemReg( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), xContext ), + UNO_QUERY_THROW ); + xMemReg->open( OUString() /* in mem */, false, true ); + xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), url ); + getMyBackend()->extractComponentData( + xContext, xMemReg->getRootKey(), data, factories, &xLoader, &url); +} + +// Package +//______________________________________________________________________________ +//We could use here BackendImpl::hasActiveEntry. However, this check is just as well. +//And it also shows the problem if another extension has overwritten an implementation +//entry, because it contains the same service implementation +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::ComponentPackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & ) +{ + if (m_registered == REG_UNINIT) + { + m_registered = REG_NOT_REGISTERED; + bool bAmbiguousComponentName = false; + const Reference<registry::XSimpleRegistry> xRDB( getRDB_RO() ); + if (xRDB.is()) + { + // lookup rdb for location URL: + const Reference<registry::XRegistryKey> xRootKey( + xRDB->getRootKey() ); + const Reference<registry::XRegistryKey> xImplKey( + xRootKey->openKey( OUSTR("IMPLEMENTATIONS") ) ); + Sequence<OUString> implNames; + if (xImplKey.is() && xImplKey->isValid()) + implNames = xImplKey->getKeyNames(); + OUString const * pImplNames = implNames.getConstArray(); + sal_Int32 pos = implNames.getLength(); + for ( ; pos--; ) + { + checkAborted( abortChannel ); + const OUString key( + pImplNames[ pos ] + OUSTR("/UNO/LOCATION") ); + const Reference<registry::XRegistryKey> xKey( + xRootKey->openKey(key) ); + if (xKey.is() && xKey->isValid()) + { + const OUString location( xKey->getAsciiValue() ); + if (location.equalsIgnoreAsciiCase( getURL() )) + { + break; + } + else + { + //try to match only the file name + OUString thisUrl(getURL()); + OUString thisFileName(thisUrl.copy(thisUrl.lastIndexOf('/'))); + + OUString locationFileName(location.copy(location.lastIndexOf('/'))); + if (locationFileName.equalsIgnoreAsciiCase(thisFileName)) + bAmbiguousComponentName = true; + } + } + } + if (pos >= 0) + m_registered = REG_REGISTERED; + else if (bAmbiguousComponentName) + m_registered = REG_MAYBE_REGISTERED; + } + } + + //Different extensions can use the same service implementations. Then the extensions + //which was installed last will overwrite the one from the other extension. That is + //the registry will contain the path (the location) of the library or jar of the + //second extension. In this case isRegistered called for the lib of the first extension + //would return "not registered". That would mean that during uninstallation + //XPackage::registerPackage is not called, because it just was not registered. This is, + //however, necessary for jar files. Registering and unregistering update + //uno_packages/cache/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc + //Therefore, we will return always "is ambiguous" if the path of this component cannot + //be found in the registry and if there is another path and both have the same file name (but + //the rest of the path is different). + //If the caller cannot precisely determine that this package was registered, then it must + //call registerPackage. + sal_Bool bAmbiguous = m_registered == REG_VOID // REG_VOID == we are in the progress of unregistration + || m_registered == REG_MAYBE_REGISTERED; + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true /* IsPresent */, + beans::Ambiguous<sal_Bool>( + m_registered == REG_REGISTERED, bAmbiguous) ); +} + +//______________________________________________________________________________ +void BackendImpl::ComponentPackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + rtl::OUString url(getURL()); + if (doRegisterPackage) { + ComponentBackendDb::Data data; + css::uno::Reference< css::uno::XComponentContext > context; + if (startup) { + context = that->getComponentContext(); + } else { + context.set(that->getObject(url), css::uno::UNO_QUERY); + if (!context.is()) { + context.set( + that->insertObject( + url, + raise_uno_process( + that->getComponentContext(), abortChannel)), + css::uno::UNO_QUERY_THROW); + } + } + css::uno::Reference< css::registry::XImplementationRegistration>( + context->getServiceManager()->createInstanceWithContext( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.ImplementationRegistration")), + context), + css::uno::UNO_QUERY_THROW)->registerImplementation( + m_loader, url, getRDB()); + // Only write to unorc after successful registration; it may fail if + // there is no suitable java + if (m_loader.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.loader.Java2")) && + !jarManifestHeaderPresent(url, OUSTR("UNO-Type-Path"), xCmdEnv)) + { + that->addToUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv); + data.javaTypeLibrary = true; + } + std::vector< css::uno::Reference< css::uno::XInterface > > factories; + getComponentInfo(&data, &factories, context); + if (!startup) { + that->componentLiveInsertion(data, factories); + } + m_registered = REG_REGISTERED; + that->addDataToDb(url, data); + } else { // revoke + m_registered = REG_VOID; + ComponentBackendDb::Data data(that->readDataFromDb(url)); + css::uno::Reference< css::uno::XComponentContext > context( + that->getObject(url), css::uno::UNO_QUERY); + bool remoteContext = context.is(); + if (!remoteContext) { + context = that->getComponentContext(); + } + if (!startup) { + that->componentLiveRemoval(data); + } + css::uno::Reference< css::registry::XImplementationRegistration >( + context->getServiceManager()->createInstanceWithContext( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.ImplementationRegistration")), + context), + css::uno::UNO_QUERY_THROW)->revokeImplementation(url, getRDB()); + if (data.javaTypeLibrary) { + that->removeFromUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv); + } + if (remoteContext) { + that->releaseObject(url); + } + m_registered = REG_NOT_REGISTERED; + getMyBackend()->revokeEntryFromDb(url); + } +} + +BackendImpl::TypelibraryPackageImpl::TypelibraryPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool jarFile, bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier), + m_jarFile( jarFile ) +{ +} + +// Package +BackendImpl * BackendImpl::TypelibraryPackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<TypelibraryPackageImpl *>(this))); + } + return pBackend; +} +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::TypelibraryPackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + BackendImpl * that = getMyBackend(); + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true /* IsPresent */, + beans::Ambiguous<sal_Bool>( + that->hasInUnoRc( + m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, getURL() ), + false /* IsAmbiguous */ ) ); +} + +//______________________________________________________________________________ +void BackendImpl::TypelibraryPackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool /*startup*/, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + const OUString url( getURL() ); + + if (doRegisterPackage) + { + // live insertion: + if (m_jarFile) { + // xxx todo add to classpath at runtime: ??? + //SB: It is probably not worth it to add the live inserted type + // library JAR to the UnoClassLoader in the soffice process. Any + // live inserted component JAR that might reference this type + // library JAR runs in its own uno process, so there is probably no + // Java code in the soffice process that would see any UNO types + // introduced by this type library JAR. + } + else // RDB: + { + Reference<XComponentContext> const & xContext = + that->getComponentContext(); + if (! m_xTDprov.is()) + { + m_xTDprov.set( that->getObject( url ), UNO_QUERY ); + if (! m_xTDprov.is()) + { + const Reference<registry::XSimpleRegistry> xReg( + xContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + xContext ), UNO_QUERY_THROW ); + xReg->open( expandUnoRcUrl(url), + true /* read-only */, false /* ! create */ ); + const Any arg(xReg); + Reference<container::XHierarchicalNameAccess> xTDprov( + xContext->getServiceManager() + ->createInstanceWithArgumentsAndContext( + OUSTR("com.sun.star.comp.stoc." + "RegistryTypeDescriptionProvider"), + Sequence<Any>( &arg, 1 ), xContext ), UNO_QUERY ); + OSL_ASSERT( xTDprov.is() ); + if (xTDprov.is()) + m_xTDprov.set( that->insertObject( url, xTDprov ), + UNO_QUERY_THROW ); + } + } + if (m_xTDprov.is()) { + Reference<container::XSet> xSet( + xContext->getValueByName( + OUSTR("/singletons/com.sun.star." + "reflection.theTypeDescriptionManager") ), + UNO_QUERY_THROW ); + xSet->insert( Any(m_xTDprov) ); + } + } + + that->addToUnoRc( m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, + url, xCmdEnv ); + } + else // revokePackage() + { + that->removeFromUnoRc( + m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, url, xCmdEnv ); + + // revoking types at runtime, possible, sensible? + if (!m_xTDprov.is()) + m_xTDprov.set( that->getObject( url ), UNO_QUERY ); + if (m_xTDprov.is()) { + // remove live: + const Reference<container::XSet> xSet( + that->getComponentContext()->getValueByName( + OUSTR("/singletons/com.sun.star." + "reflection.theTypeDescriptionManager") ), + UNO_QUERY_THROW ); + xSet->remove( Any(m_xTDprov) ); + + that->releaseObject( url ); + m_xTDprov.clear(); + } + } +} + +BackendImpl::OtherPlatformPackageImpl::OtherPlatformPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, OUString const & identifier, OUString const& rPlatform) + : Package(myBackend, url, name, name, xPackageType, bRemoved, identifier) + , m_aPlatform(rPlatform) +{ + OSL_PRECOND(bRemoved, "this class can only be used for removing packages!"); +} + +BackendImpl * +BackendImpl::OtherPlatformPackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //Throws a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<OtherPlatformPackageImpl*>(this))); + } + return pBackend; +} + +Reference<registry::XSimpleRegistry> const +BackendImpl::OtherPlatformPackageImpl::impl_openRDB() const +{ + OUString const aRDB(m_aPlatform + OUString(RTL_CONSTASCII_USTRINGPARAM(".rdb"))); + OUString const aRDBPath(makeURL(getMyBackend()->getCachePath(), aRDB)); + + Reference<registry::XSimpleRegistry> xRegistry; + + try + { + xRegistry.set( + impl_createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.SimpleRegistry"))), + UNO_QUERY) + ; + if (xRegistry.is()) + xRegistry->open(expandUnoRcUrl(aRDBPath), false, false); + } + catch (registry::InvalidRegistryException const&) + { + // If the registry does not exist, we do not need to bother at all + xRegistry.set(0); + } + + OSL_POSTCOND(xRegistry.is(), "could not create registry for the package's platform"); + return xRegistry; +} + +Reference<XInterface> const +BackendImpl::OtherPlatformPackageImpl::impl_createInstance(OUString const& rService) +const +{ + Reference<XComponentContext> const xContext(getMyBackend()->getComponentContext()); + OSL_ASSERT(xContext.is()); + Reference<XInterface> xService; + if (xContext.is()) + xService.set(xContext->getServiceManager()->createInstanceWithContext(rService, xContext)); + return xService; +} + +beans::Optional<beans::Ambiguous<sal_Bool> > +BackendImpl::OtherPlatformPackageImpl::isRegistered_( + ::osl::ResettableMutexGuard& /* guard */, + ::rtl::Reference<AbortChannel> const& /* abortChannel */, + Reference<XCommandEnvironment> const& /* xCmdEnv */ ) +{ + return beans::Optional<beans::Ambiguous<sal_Bool> >(sal_True, + beans::Ambiguous<sal_Bool>(sal_True, sal_False)); +} + +void +BackendImpl::OtherPlatformPackageImpl::processPackage_( + ::osl::ResettableMutexGuard& /* guard */, + bool bRegisterPackage, + bool /* bStartup */, + ::rtl::Reference<AbortChannel> const& /* abortChannel */, + Reference<XCommandEnvironment> const& /* xCmdEnv */) +{ + OSL_PRECOND(!bRegisterPackage, "this class can only be used for removing packages!"); + (void) bRegisterPackage; + + OUString const aURL(getURL()); + + Reference<registry::XSimpleRegistry> const xServicesRDB(impl_openRDB()); + Reference<registry::XImplementationRegistration> const xImplReg( + impl_createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.ImplementationRegistration"))), + UNO_QUERY) + ; + if (xImplReg.is() && xServicesRDB.is()) + xImplReg->revokeImplementation(aURL, xServicesRDB); + if (xServicesRDB.is()) + xServicesRDB->close(); + + getMyBackend()->revokeEntryFromDb(aURL); +} + +BackendImpl * BackendImpl::ComponentsPackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //Throws a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<ComponentsPackageImpl *>(this))); + } + return pBackend; +} + +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::ComponentsPackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true, + beans::Ambiguous<sal_Bool>( + getMyBackend()->hasInUnoRc(RCITEM_COMPONENTS, getURL()), false)); +} + +void BackendImpl::ComponentsPackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + rtl::OUString url(getURL()); + if (doRegisterPackage) { + ComponentBackendDb::Data data; + data.javaTypeLibrary = false; + css::uno::Reference< css::uno::XComponentContext > context; + if (startup) { + context = that->getComponentContext(); + } else { + context.set(that->getObject(url), css::uno::UNO_QUERY); + if (!context.is()) { + context.set( + that->insertObject( + url, + raise_uno_process( + that->getComponentContext(), abortChannel)), + css::uno::UNO_QUERY_THROW); + } + } + + std::vector< css::uno::Reference< css::uno::XInterface > > factories; + + css::uno::Reference< css::registry::XSimpleRegistry > registry( + css::uno::Reference< css::lang::XMultiComponentFactory >( + that->getComponentContext()->getServiceManager(), + css::uno::UNO_SET_THROW)->createInstanceWithContext( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry")), + that->getComponentContext()), + css::uno::UNO_QUERY_THROW); + registry->open(expandUnoRcUrl(url), true, false); + getMyBackend()->extractComponentData( + context, + that->openRegistryKey( + registry->getRootKey(), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IMPLEMENTATIONS"))), + &data, &factories, 0, 0); + registry->close(); + if (!startup) { + that->componentLiveInsertion(data, factories); + } + that->addDataToDb(url, data); + that->addToUnoRc(RCITEM_COMPONENTS, url, xCmdEnv); + } else { // revoke + that->removeFromUnoRc(RCITEM_COMPONENTS, url, xCmdEnv); + if (!startup) { + that->componentLiveRemoval(that->readDataFromDb(url)); + } + that->releaseObject(url); + that->revokeEntryFromDb(url); + } +} + +BackendImpl::ComponentsPackageImpl::ComponentsPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier) +{} + +} // anon namespace + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + IMPLEMENTATION_NAME, + BACKEND_SERVICE_NAME ); + +} // namespace component +} // namespace backend +} // namespace dp_registry + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/component/dp_component.hrc b/desktop/source/deployment/registry/component/dp_component.hrc new file mode 100755 index 000000000000..4a8c4184a994 --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_component.hrc @@ -0,0 +1,40 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_COMPONENT_HRC +#define INCLUDED_DP_COMPONENT_HRC + +#include "deployment.hrc" + +#define RID_STR_DYN_COMPONENT (RID_DEPLOYMENT_COMPONENT_START+10) +#define RID_STR_JAVA_COMPONENT (RID_DEPLOYMENT_COMPONENT_START+11) +#define RID_STR_PYTHON_COMPONENT (RID_DEPLOYMENT_COMPONENT_START+12) +#define RID_STR_COMPONENTS (RID_DEPLOYMENT_COMPONENT_START+13) +#define RID_STR_RDB_TYPELIB (RID_DEPLOYMENT_COMPONENT_START+20) +#define RID_STR_JAVA_TYPELIB (RID_DEPLOYMENT_COMPONENT_START+21) + +#endif diff --git a/desktop/source/deployment/registry/component/dp_component.src b/desktop/source/deployment/registry/component/dp_component.src new file mode 100644 index 000000000000..9e9ab1a82bbf --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_component.src @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_component.hrc" + +String RID_STR_DYN_COMPONENT +{ + Text [ en-US ] = "UNO Dynamic Library Component"; +}; + +String RID_STR_JAVA_COMPONENT +{ + Text [ en-US ] = "UNO Java Component"; +}; + +String RID_STR_PYTHON_COMPONENT +{ + Text [ en-US ] = "UNO Python Component"; +}; + +String RID_STR_COMPONENTS +{ + Text [ en-US ] = "UNO Components"; +}; + +String RID_STR_RDB_TYPELIB +{ + Text [ en-US ] = "UNO RDB Type Library"; +}; + +String RID_STR_JAVA_TYPELIB +{ + Text [ en-US ] = "UNO Java Type Library"; +}; + diff --git a/desktop/source/deployment/registry/component/makefile.mk b/desktop/source/deployment/registry/component/makefile.mk new file mode 100755 index 000000000000..b7ee5c203cd5 --- /dev/null +++ b/desktop/source/deployment/registry/component/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_registry_component +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_component.src + +INCPRE += ..$/..$/inc + +SLOFILES = \ + $(SLO)$/dp_component.obj \ + $(SLO)$/dp_compbackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/configuration/dp_configuration.cxx b/desktop/source/deployment/registry/configuration/dp_configuration.cxx new file mode 100644 index 000000000000..e49253aa0765 --- /dev/null +++ b/desktop/source/deployment/registry/configuration/dp_configuration.cxx @@ -0,0 +1,812 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" + +//TODO: Large parts of this file were copied from dp_component.cxx; those parts +// should be consolidated. + +#include "dp_configuration.hrc" +#include "dp_backend.h" +#include "dp_persmap.h" +#include "dp_ucb.h" +#include "rtl/string.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/uri.hxx" +#include "rtl/memory.h" +#include "osl/file.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "ucbhelper/content.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/servicedecl.hxx" +#include "xmlscript/xml_helper.hxx" +#include "svl/inettype.hxx" +#include "com/sun/star/configuration/Update.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/io/XActiveDataSink.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/util/XRefreshable.hpp" +#include <list> +#include <memory> + +#include "dp_configurationbackenddb.hxx" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace configuration { +namespace { + +typedef ::std::list<OUString> t_stringlist; + +//============================================================================== +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + class PackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const ; + + const bool m_isSchema; + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + public: + inline PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool isSchema, bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier), + m_isSchema( isSchema ) + {} + }; + friend class PackageImpl; + + t_stringlist m_xcs_files; + t_stringlist m_xcu_files; + t_stringlist & getFiles( bool xcs ) { + return xcs ? m_xcs_files : m_xcu_files; + } + + bool m_configmgrini_inited; + bool m_configmgrini_modified; + std::auto_ptr<ConfigurationBackendDb> m_backendDb; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, sal_Bool bRemoved, + OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ); + + ::std::auto_ptr<PersistentMap> m_registeredPackages; + // for backwards compatibility + + virtual void SAL_CALL disposing(); + + const Reference<deployment::XPackageTypeInfo> m_xConfDataTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xConfSchemaTypeInfo; + Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + + void configmgrini_verify_init( + Reference<XCommandEnvironment> const & xCmdEnv ); + void configmgrini_flush( Reference<XCommandEnvironment> const & xCmdEnv ); + + /* The paramter isURL is false in the case of adding the conf:ini-entry + value from the backend db. This entry already contains the path as it + is used in the configmgr.ini. + */ + bool addToConfigmgrIni( bool isSchema, bool isURL, OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv ); + bool removeFromConfigmgrIni( bool isSchema, OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv ); + + void addDataToDb(OUString const & url, ConfigurationBackendDb::Data const & data); + ::boost::optional<ConfigurationBackendDb::Data> readDataFromDb(OUString const & url); + void revokeEntryFromDb(OUString const & url); + bool hasActiveEntry(OUString const & url); + bool activateEntry(OUString const & url); + +public: + BackendImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) + throw (deployment::DeploymentException, + uno::RuntimeException); + + using PackageRegistryBackend::disposing; +}; + +//______________________________________________________________________________ +void BackendImpl::disposing() +{ + try { + configmgrini_flush( Reference<XCommandEnvironment>() ); + + PackageRegistryBackend::disposing(); + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( + OUSTR("caught unexpected exception while disposing..."), + static_cast<OWeakObject *>(this), exc ); + } +} + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : PackageRegistryBackend( args, xComponentContext ), + m_configmgrini_inited( false ), + m_configmgrini_modified( false ), + m_xConfDataTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.configuration-data"), + OUSTR("*.xcu"), + getResourceString(RID_STR_CONF_DATA), + RID_IMG_CONF_XML ) ), + m_xConfSchemaTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.configuration-schema"), + OUSTR("*.xcs"), + getResourceString(RID_STR_CONF_SCHEMA), + RID_IMG_CONF_XML ) ), + m_typeInfos( 2 ) +{ + m_typeInfos[ 0 ] = m_xConfDataTypeInfo; + m_typeInfos[ 1 ] = m_xConfSchemaTypeInfo; + + const Reference<XCommandEnvironment> xCmdEnv; + + if (transientMode()) + { + //TODO + } + else + { + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new ConfigurationBackendDb(getComponentContext(), dbFile)); + //clean up data folders which are no longer used. + //This must not be done in the same process where the help files + //are still registers. Only after revoking and restarting OOo the folders + //can be removed. This works now, because the extension manager is a singleton + //and the backends are only create once per process. + ::std::list<OUString> folders = m_backendDb->getAllDataUrls(); + deleteUnusedFolders(OUString(), folders); + + + configmgrini_verify_init( xCmdEnv ); + m_registeredPackages.reset( + new PersistentMap( + makeURL( getCachePath(), OUSTR("registered_packages.db") ), + false ) ); + } +} + +void BackendImpl::addDataToDb( + OUString const & url, ConfigurationBackendDb::Data const & data) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url, data); +} + +::boost::optional<ConfigurationBackendDb::Data> BackendImpl::readDataFromDb( + OUString const & url) +{ + ::boost::optional<ConfigurationBackendDb::Data> data; + if (m_backendDb.get()) + data = m_backendDb->getEntry(url); + return data; +} + +void BackendImpl::revokeEntryFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->revokeEntry(url); +} + +bool BackendImpl::hasActiveEntry(OUString const & url) +{ + if (m_backendDb.get()) + return m_backendDb->hasActiveEntry(url); + return false; +} + +bool BackendImpl::activateEntry(OUString const & url) +{ + if (m_backendDb.get()) + return m_backendDb->activateEntry(url); + return false; +} + + + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return m_typeInfos; +} +void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/) + throw (deployment::DeploymentException, + uno::RuntimeException) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + OUString mediaType( mediaType_ ); + if (mediaType.getLength() == 0) + { + // detect media-type: + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, url, xCmdEnv )) + { + const OUString title( ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".xcu") )) { + mediaType = OUSTR("application/" + "vnd.sun.star.configuration-data"); + } + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".xcs") )) { + mediaType = OUSTR("application/" + "vnd.sun.star.configuration-schema"); + } + } + if (mediaType.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + OUString name; + if (!bRemoved) + { + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + name = ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>(); + } + + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.configuration-data")) + { + return new PackageImpl( + this, url, name, m_xConfDataTypeInfo, false /* data file */, + bRemoved, identifier); + } + else if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.configuration-schema")) { + return new PackageImpl( + this, url, name, m_xConfSchemaTypeInfo, true /* schema file */, + bRemoved, identifier); + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + + +//______________________________________________________________________________ +void BackendImpl::configmgrini_verify_init( + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (transientMode()) + return; + const ::osl::MutexGuard guard( getMutex() ); + if (! m_configmgrini_inited) + { + // common rc: + ::ucbhelper::Content ucb_content; + if (create_ucb_content( + &ucb_content, + makeURL( getCachePath(), OUSTR("configmgr.ini") ), + xCmdEnv, false /* no throw */ )) + { + OUString line; + if (readLine( &line, OUSTR("SCHEMA="), ucb_content, + RTL_TEXTENCODING_UTF8 )) + { + sal_Int32 index = RTL_CONSTASCII_LENGTH("SCHEMA="); + do { + OUString token( line.getToken( 0, ' ', index ).trim() ); + if (token.getLength() > 0) { + //The file may not exist anymore if a shared or bundled + //extension was removed, but it can still be in the configmgrini. + //After running XExtensionManager::synchronize, the configmgrini is + //cleaned up + m_xcs_files.push_back( token ); + } + } + while (index >= 0); + } + if (readLine( &line, OUSTR("DATA="), ucb_content, + RTL_TEXTENCODING_UTF8 )) { + sal_Int32 index = RTL_CONSTASCII_LENGTH("DATA="); + do { + OUString token( line.getToken( 0, ' ', index ).trim() ); + if (token.getLength() > 0) + { + if (token[ 0 ] == '?') + token = token.copy( 1 ); + //The file may not exist anymore if a shared or bundled + //extension was removed, but it can still be in the configmgrini. + //After running XExtensionManager::synchronize, the configmgrini is + //cleaned up + m_xcu_files.push_back( token ); + } + } + while (index >= 0); + } + } + m_configmgrini_modified = false; + m_configmgrini_inited = true; + } +} + +//______________________________________________________________________________ +void BackendImpl::configmgrini_flush( + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (transientMode()) + return; + if (!m_configmgrini_inited || !m_configmgrini_modified) + return; + + ::rtl::OStringBuffer buf; + if (! m_xcs_files.empty()) + { + t_stringlist::const_iterator iPos( m_xcs_files.begin() ); + t_stringlist::const_iterator const iEnd( m_xcs_files.end() ); + buf.append( RTL_CONSTASCII_STRINGPARAM("SCHEMA=") ); + while (iPos != iEnd) { + // encoded ASCII file-urls: + const ::rtl::OString item( + ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( item ); + ++iPos; + if (iPos != iEnd) + buf.append( ' ' ); + } + buf.append(LF); + } + if (! m_xcu_files.empty()) + { + t_stringlist::const_iterator iPos( m_xcu_files.begin() ); + t_stringlist::const_iterator const iEnd( m_xcu_files.end() ); + buf.append( RTL_CONSTASCII_STRINGPARAM("DATA=") ); + while (iPos != iEnd) { + // encoded ASCII file-urls: + const ::rtl::OString item( + ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( item ); + ++iPos; + if (iPos != iEnd) + buf.append( ' ' ); + } + buf.append(LF); + } + + // write configmgr.ini: + const Reference<io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(buf.getStr()), + buf.getLength() ) ) ); + ::ucbhelper::Content ucb_content( + makeURL( getCachePath(), OUSTR("configmgr.ini") ), xCmdEnv ); + ucb_content.writeStream( xData, true /* replace existing */ ); + + m_configmgrini_modified = false; +} + +//______________________________________________________________________________ +bool BackendImpl::addToConfigmgrIni( bool isSchema, bool isURL, OUString const & url_, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + const OUString rcterm( isURL ? dp_misc::makeRcTerm(url_) : url_ ); + const ::osl::MutexGuard guard( getMutex() ); + configmgrini_verify_init( xCmdEnv ); + t_stringlist & rSet = getFiles(isSchema); + if (::std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) { + rSet.push_front( rcterm ); // prepend to list, thus overriding + // write immediately: + m_configmgrini_modified = true; + configmgrini_flush( xCmdEnv ); + return true; + } + else + return false; +} + +//______________________________________________________________________________ +bool BackendImpl::removeFromConfigmgrIni( + bool isSchema, OUString const & url_, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + const OUString rcterm( dp_misc::makeRcTerm(url_) ); + const ::osl::MutexGuard guard( getMutex() ); + configmgrini_verify_init( xCmdEnv ); + t_stringlist & rSet = getFiles(isSchema); + t_stringlist::iterator i(std::find(rSet.begin(), rSet.end(), rcterm)); + if (i == rSet.end() && !isSchema) + { + //in case the xcu contained %origin% then the configmr.ini contains the + //url to the file in the user installation (e.g. $BUNDLED_EXTENSIONS_USER) + //However, m_url (getURL()) contains the URL for the file in the actual + //extension installatation. + ::boost::optional<ConfigurationBackendDb::Data> data = readDataFromDb(url_); + if (data) + i = std::find(rSet.begin(), rSet.end(), data->iniEntry); + } + if (i == rSet.end()) { + return false; + } + rSet.erase(i); + // write immediately: + m_configmgrini_modified = true; + configmgrini_flush( xCmdEnv ); + return true; +} + + +// Package +//______________________________________________________________________________ + +BackendImpl * BackendImpl::PackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); + } + return pBackend; +} + +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::PackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + BackendImpl * that = getMyBackend(); + const rtl::OUString url(getURL()); + + bool bReg = false; + if (that->hasActiveEntry(getURL())) + bReg = true; + if (!bReg) + //fallback for user extension registered in berkeley DB + bReg = that->m_registeredPackages->has( + rtl::OUStringToOString( url, RTL_TEXTENCODING_UTF8 )); + + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true, beans::Ambiguous<sal_Bool>( bReg, false ) ); +} + +//------------------------------------------------------------------------------ +OUString encodeForXml( OUString const & text ) +{ + // encode conforming xml: + sal_Int32 len = text.getLength(); + ::rtl::OUStringBuffer buf; + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + sal_Unicode c = text[ pos ]; + switch (c) { + case '<': + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("<") ); + break; + case '>': + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(">") ); + break; + case '&': + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("&") ); + break; + case '\'': + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("'") ); + break; + case '\"': + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(""") ); + break; + default: + buf.append( c ); + break; + } + } + return buf.makeStringAndClear(); +} + +//______________________________________________________________________________ +OUString replaceOrigin( + OUString const & url, OUString const & destFolder, Reference< XCommandEnvironment > const & xCmdEnv, bool & out_replaced) +{ + // looking for %origin%: + ::ucbhelper::Content ucb_content( url, xCmdEnv ); + ::rtl::ByteSequence bytes( readFile( ucb_content ) ); + ::rtl::ByteSequence filtered( bytes.getLength() * 2, + ::rtl::BYTESEQ_NODEFAULT ); + bool use_filtered = false; + ::rtl::OString origin; + sal_Char const * pBytes = reinterpret_cast<sal_Char const *>( + bytes.getConstArray()); + sal_Size nBytes = bytes.getLength(); + sal_Int32 write_pos = 0; + while (nBytes > 0) + { + sal_Int32 index = rtl_str_indexOfChar_WithLength( pBytes, nBytes, '%' ); + if (index < 0) { + if (! use_filtered) // opt + break; + index = nBytes; + } + + if ((write_pos + index) > filtered.getLength()) + filtered.realloc( (filtered.getLength() + index) * 2 ); + rtl_copyMemory( filtered.getArray() + write_pos, pBytes, index ); + write_pos += index; + pBytes += index; + nBytes -= index; + if (nBytes == 0) + break; + + // consume %: + ++pBytes; + --nBytes; + sal_Char const * pAdd = "%"; + sal_Int32 nAdd = 1; + if (nBytes > 1 && pBytes[ 0 ] == '%') + { + // %% => % + ++pBytes; + --nBytes; + use_filtered = true; + } + else if (rtl_str_shortenedCompare_WithLength( + pBytes, nBytes, + RTL_CONSTASCII_STRINGPARAM("origin%"), + RTL_CONSTASCII_LENGTH("origin%")) == 0) + { + if (origin.getLength() == 0) { + // encode only once + origin = ::rtl::OUStringToOString( + encodeForXml( url.copy( 0, url.lastIndexOf( '/' ) ) ), + // xxx todo: encode always for UTF-8? => lookup doc-header? + RTL_TEXTENCODING_UTF8 ); + } + pAdd = origin.getStr(); + nAdd = origin.getLength(); + pBytes += SAL_N_ELEMENTS("origin%"); + nBytes -= SAL_N_ELEMENTS("origin%"); + use_filtered = true; + } + if ((write_pos + nAdd) > filtered.getLength()) + filtered.realloc( (filtered.getLength() + nAdd) * 2 ); + rtl_copyMemory( filtered.getArray() + write_pos, pAdd, nAdd ); + write_pos += nAdd; + } + if (!use_filtered) + return url; + if (write_pos < filtered.getLength()) + filtered.realloc( write_pos ); + rtl::OUString newUrl(url); + if (destFolder.getLength()) + { + //get the file name of the xcu and add it to the url of the temporary folder + sal_Int32 i = url.lastIndexOf('/'); + newUrl = destFolder + url.copy(i); + } + + ucbhelper::Content(newUrl, xCmdEnv).writeStream( + xmlscript::createInputStream(filtered), true); + out_replaced = true; + return newUrl; +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool startup, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + OUString url( getURL() ); + + if (doRegisterPackage) + { + if (getMyBackend()->activateEntry(getURL())) + { + ::boost::optional<ConfigurationBackendDb::Data> data = that->readDataFromDb(url); + OSL_ASSERT(data); + that->addToConfigmgrIni( m_isSchema, false, data->iniEntry, xCmdEnv ); + } + else + { + ConfigurationBackendDb::Data data; + if (!m_isSchema) + { + const OUString sModFolder = that->createFolder(OUString(), xCmdEnv); + bool out_replaced = false; + url = replaceOrigin(url, sModFolder, xCmdEnv, out_replaced); + if (out_replaced) + data.dataUrl = sModFolder; + else + deleteTempFolder(sModFolder); + } + //No need for live-deployment for bundled extension, because OOo + //restarts after installation + if (that->m_eContext != CONTEXT_BUNDLED + && that->m_eContext != CONTEXT_BUNDLED_PREREG + && !startup) + { + if (m_isSchema) + { + com::sun::star::configuration::Update::get( + that->m_xComponentContext)->insertExtensionXcsFile( + that->m_eContext == CONTEXT_SHARED, expandUnoRcUrl(url)); + } + else + { + com::sun::star::configuration::Update::get( + that->m_xComponentContext)->insertExtensionXcuFile( + that->m_eContext == CONTEXT_SHARED, expandUnoRcUrl(url)); + } + } + that->addToConfigmgrIni( m_isSchema, true, url, xCmdEnv ); + data.iniEntry = dp_misc::makeRcTerm(url); + that->addDataToDb(getURL(), data); + } + } + else // revoke + { + if (!that->removeFromConfigmgrIni(m_isSchema, url, xCmdEnv)) { + t_string2string_map entries( + that->m_registeredPackages->getEntries()); + for (t_string2string_map::iterator i(entries.begin()); + i != entries.end(); ++i) + { + //If the xcu file was installed before the configmgr was chaned + //to use the configmgr.ini, one needed to rebuild to whole directory + //structur containing the xcu, xcs files from all extensions. Now, + //we just add all other xcu/xcs files to the configmgr.ini instead of + //rebuilding the directory structure. + rtl::OUString url2( + rtl::OStringToOUString(i->first, RTL_TEXTENCODING_UTF8)); + if (url2 != url) { + bool schema = i->second.equalsIgnoreAsciiCase( + "vnd.sun.star.configuration-schema"); + OUString url_replaced(url2); + ConfigurationBackendDb::Data data; + if (!schema) + { + const OUString sModFolder = that->createFolder(OUString(), xCmdEnv); + bool out_replaced = false; + url_replaced = replaceOrigin( + url2, sModFolder, xCmdEnv, out_replaced); + if (out_replaced) + data.dataUrl = sModFolder; + else + deleteTempFolder(sModFolder); + } + that->addToConfigmgrIni(schema, true, url_replaced, xCmdEnv); + data.iniEntry = dp_misc::makeRcTerm(url_replaced); + that->addDataToDb(url2, data); + } + that->m_registeredPackages->erase(i->first); + } + try + { + ::ucbhelper::Content( + makeURL( that->getCachePath(), OUSTR("registry") ), + xCmdEnv ).executeCommand( + OUSTR("delete"), Any( true /* delete physically */ ) ); + } + catch(Exception&) + { + OSL_ASSERT(0); + } + } + + ::boost::optional<ConfigurationBackendDb::Data> data = that->readDataFromDb(url); + //If an xcu file was life deployed then always a data entry is written. + //If the xcu file was already in the configmr.ini then there is also + //a data entry + if (!m_isSchema && data) + { + com::sun::star::configuration::Update::get( + that->m_xComponentContext)->removeExtensionXcuFile(expandUnoRcTerm(data->iniEntry)); + } + that->revokeEntryFromDb(url); + } +} + +} // anon namespace + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + "com.sun.star.comp.deployment.configuration.PackageRegistryBackend", + BACKEND_SERVICE_NAME ); + +} // namespace configuration +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/configuration/dp_configuration.hrc b/desktop/source/deployment/registry/configuration/dp_configuration.hrc new file mode 100755 index 000000000000..01e1905228b3 --- /dev/null +++ b/desktop/source/deployment/registry/configuration/dp_configuration.hrc @@ -0,0 +1,36 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_CONFIGURATION_HRC +#define INCLUDED_DP_CONFIGURATION_HRC + +#include "deployment.hrc" + +#define RID_STR_CONF_SCHEMA (RID_DEPLOYMENT_CONF_START+10) +#define RID_STR_CONF_DATA (RID_DEPLOYMENT_CONF_START+11) + +#endif diff --git a/desktop/source/deployment/registry/configuration/dp_configuration.src b/desktop/source/deployment/registry/configuration/dp_configuration.src new file mode 100644 index 000000000000..7ff749b18459 --- /dev/null +++ b/desktop/source/deployment/registry/configuration/dp_configuration.src @@ -0,0 +1,39 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_configuration.hrc" + +String RID_STR_CONF_SCHEMA +{ + Text [ en-US ] = "Configuration Schema"; +}; + +String RID_STR_CONF_DATA +{ + Text [ en-US ] = "Configuration Data"; +}; + diff --git a/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.cxx b/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.cxx new file mode 100644 index 000000000000..bfb1ed9df70e --- /dev/null +++ b/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.cxx @@ -0,0 +1,181 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "rtl/string.h" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" + +#include "dp_configurationbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/configuration-registry/2010" +#define NS_PREFIX "conf" +#define ROOT_ELEMENT_NAME "configuration-backend-db" +#define KEY_ELEMENT_NAME "configuration" + +namespace dp_registry { +namespace backend { +namespace configuration { + +ConfigurationBackendDb::ConfigurationBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +OUString ConfigurationBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ConfigurationBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString ConfigurationBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString ConfigurationBackendDb::getKeyElementName() +{ + return OUSTR(KEY_ELEMENT_NAME); +} + + +void ConfigurationBackendDb::addEntry(::rtl::OUString const & url, Data const & data) +{ + try{ + if (!activateEntry(url)) + { + Reference<css::xml::dom::XNode> helpNode + = writeKeyElement(url); + + writeSimpleElement(OUSTR("data-url"), data.dataUrl, helpNode); + writeSimpleElement(OUSTR("ini-entry"), data.iniEntry, helpNode); + save(); + } + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in configuration backend db: ") + + m_urlDb, 0, exc); + } +} + + +::boost::optional<ConfigurationBackendDb::Data> +ConfigurationBackendDb::getEntry(::rtl::OUString const & url) +{ + try + { + ConfigurationBackendDb::Data retData; + Reference<css::xml::dom::XNode> aNode = getKeyElement(url); + if (aNode.is()) + { + retData.dataUrl = readSimpleElement(OUSTR("data-url"), aNode); + retData.iniEntry = readSimpleElement(OUSTR("ini-entry"), aNode); + } + else + { + return ::boost::optional<Data>(); + } + return ::boost::optional<Data>(retData); + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in configuration backend db: ") + + m_urlDb, 0, exc); + } +} + +::std::list<OUString> ConfigurationBackendDb::getAllDataUrls() +{ + try + { + ::std::list<OUString> listRet; + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const OUString sPrefix = getNSPrefix(); + OUString sExpression( + sPrefix + OUSTR(":configuration/") + sPrefix + OUSTR(":data-url/text()")); + Reference<css::xml::dom::XNodeList> nodes = + xpathApi->selectNodeList(root, sExpression); + if (nodes.is()) + { + sal_Int32 length = nodes->getLength(); + for (sal_Int32 i = 0; i < length; i++) + listRet.push_back(nodes->item(i)->getNodeValue()); + } + return listRet; + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in configuration backend db: ") + + m_urlDb, 0, exc); + } +} + +} // namespace configuration +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.hxx b/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.hxx new file mode 100644 index 000000000000..00a5515b3780 --- /dev/null +++ b/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_CONFIGURATIONBACKENDDB_HXX +#define INCLUDED_DP_CONFIGURATIONBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "rtl/string.hxx" +#include <list> +#include "boost/optional.hpp" +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } +}}} + +namespace dp_registry { +namespace backend { +namespace configuration { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + */ +class ConfigurationBackendDb: public dp_registry::backend::BackendDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + + virtual ::rtl::OUString getNSPrefix(); + + virtual ::rtl::OUString getRootElementName(); + + virtual ::rtl::OUString getKeyElementName(); + +public: + struct Data + { + /* the URL to the folder containing the xcu or xcs files which contained + %origin% + */ + ::rtl::OUString dataUrl; + /* the URL of the xcu or xcs file which is written in to the configmgr.ini + */ + ::rtl::OUString iniEntry; + }; + +public: + + ConfigurationBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + + void addEntry(::rtl::OUString const & url, Data const & data); + + ::boost::optional<Data> getEntry(::rtl::OUString const & url); + ::std::list< ::rtl::OUString> getAllDataUrls(); +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/configuration/makefile.mk b/desktop/source/deployment/registry/configuration/makefile.mk new file mode 100755 index 000000000000..1fb637ef8e3a --- /dev/null +++ b/desktop/source/deployment/registry/configuration/makefile.mk @@ -0,0 +1,50 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_registry_configuration +ENABLE_EXCEPTIONS = TRUE + +INCPRE += ..$/..$/inc + +.INCLUDE : settings.mk + +CFLAGS+= $(SYSTEM_DB_CFLAGS) + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_configuration.src + +SLOFILES = \ + $(SLO)$/dp_configuration.obj \ + $(SLO)$/dp_configurationbackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/dp_backend.cxx b/desktop/source/deployment/registry/dp_backend.cxx new file mode 100644 index 000000000000..cbb0bf53abad --- /dev/null +++ b/desktop/source/deployment/registry/dp_backend.cxx @@ -0,0 +1,827 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_backend.h" +#include "dp_ucb.h" +#include "rtl/uri.hxx" +#include "rtl/bootstrap.hxx" +#include "osl/file.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/unwrapargs.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/deployment/InvalidRemovedParameterException.hpp" +#include "com/sun/star/deployment/thePackageManagerFactory.hpp" +#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" +#include "com/sun/star/ucb/IOErrorCode.hpp" +#include "com/sun/star/beans/StringPair.hpp" +#include "com/sun/star/sdbc/XResultSet.hpp" +#include "com/sun/star/sdbc/XRow.hpp" +#include "unotools/tempfile.hxx" + + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { + +//______________________________________________________________________________ +PackageRegistryBackend::~PackageRegistryBackend() +{ +} + +//______________________________________________________________________________ +void PackageRegistryBackend::disposing( lang::EventObject const & event ) + throw (RuntimeException) +{ + Reference<deployment::XPackage> xPackage( + event.Source, UNO_QUERY_THROW ); + OUString url( xPackage->getURL() ); + ::osl::MutexGuard guard( getMutex() ); + if ( m_bound.erase( url ) != 1 ) + { + OSL_ASSERT( false ); + } +} + +//______________________________________________________________________________ +PackageRegistryBackend::PackageRegistryBackend( + Sequence<Any> const & args, + Reference<XComponentContext> const & xContext ) + : t_BackendBase( getMutex() ), + m_xComponentContext( xContext ), + m_eContext( CONTEXT_UNKNOWN ), + m_readOnly( false ) +{ + boost::optional<OUString> cachePath; + boost::optional<bool> readOnly; + comphelper::unwrapArgs( args, m_context, cachePath, readOnly ); + if (cachePath) + m_cachePath = *cachePath; + if (readOnly) + m_readOnly = *readOnly; + + if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("user") )) + m_eContext = CONTEXT_USER; + else if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) + m_eContext = CONTEXT_SHARED; + else if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled") )) + m_eContext = CONTEXT_BUNDLED; + else if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("tmp") )) + m_eContext = CONTEXT_TMP; + else if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled_prereg") )) + m_eContext = CONTEXT_BUNDLED_PREREG; + else if (m_context.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.tdoc:/") )) + m_eContext = CONTEXT_DOCUMENT; + else + m_eContext = CONTEXT_UNKNOWN; +} + +//______________________________________________________________________________ +void PackageRegistryBackend::check() +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) { + throw lang::DisposedException( + OUSTR("PackageRegistryBackend instance has already been disposed!"), + static_cast<OWeakObject *>(this) ); + } +} + +//______________________________________________________________________________ +void PackageRegistryBackend::disposing() +{ + try { + for ( t_string2ref::const_iterator i = m_bound.begin(); i != m_bound.end(); ++i) + i->second->removeEventListener(this); + m_bound.clear(); + m_xComponentContext.clear(); + WeakComponentImplHelperBase::disposing(); + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( + OUSTR("caught unexpected exception while disposing!"), + static_cast<OWeakObject *>(this), exc ); + } +} + +// XPackageRegistry +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageRegistryBackend::bindPackage( + OUString const & url, OUString const & mediaType, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + deployment::InvalidRemovedParameterException, + ucb::CommandFailedException, + lang::IllegalArgumentException, RuntimeException) +{ + ::osl::ResettableMutexGuard guard( getMutex() ); + check(); + + t_string2ref::const_iterator const iFind( m_bound.find( url ) ); + if (iFind != m_bound.end()) + { + Reference<deployment::XPackage> xPackage( iFind->second ); + if (xPackage.is()) + { + if (mediaType.getLength() && + mediaType != xPackage->getPackageType()->getMediaType()) + throw lang::IllegalArgumentException + (OUSTR("XPackageRegistry::bindPackage: media type does not match"), + static_cast<OWeakObject*>(this), 1); + if (xPackage->isRemoved() != bRemoved) + throw deployment::InvalidRemovedParameterException( + OUSTR("XPackageRegistry::bindPackage: bRemoved parameter does not match"), + static_cast<OWeakObject*>(this), xPackage->isRemoved(), xPackage); + return xPackage; + } + } + + guard.clear(); + + Reference<deployment::XPackage> xNewPackage; + try { + xNewPackage = bindPackage_( url, mediaType, bRemoved, + identifier, xCmdEnv ); + } + catch (RuntimeException &) { + throw; + } + catch (lang::IllegalArgumentException &) { + throw; + } + catch (CommandFailedException &) { + throw; + } + catch (deployment::DeploymentException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw deployment::DeploymentException( + OUSTR("Error binding package: ") + url, + static_cast<OWeakObject *>(this), exc ); + } + + guard.reset(); + + ::std::pair< t_string2ref::iterator, bool > insertion( + m_bound.insert( t_string2ref::value_type( url, xNewPackage ) ) ); + if (insertion.second) + { // first insertion + OSL_ASSERT( Reference<XInterface>(insertion.first->second) + == xNewPackage ); + } + else + { // found existing entry + Reference<deployment::XPackage> xPackage( insertion.first->second ); + if (xPackage.is()) + return xPackage; + insertion.first->second = xNewPackage; + } + + guard.clear(); + xNewPackage->addEventListener( this ); // listen for disposing events + return xNewPackage; +} + +OUString PackageRegistryBackend::createFolder( + OUString const & relUrl, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + const OUString sDataFolder = makeURL(getCachePath(), relUrl); + //make sure the folder exist + ucbhelper::Content dataContent; + ::dp_misc::create_folder(&dataContent, sDataFolder, xCmdEnv); + + const OUString sDataFolderURL = dp_misc::expandUnoRcUrl(sDataFolder); + const String baseDir(sDataFolder); + const ::utl::TempFile aTemp(&baseDir, sal_True); + const OUString url = aTemp.GetURL(); + return sDataFolder + url.copy(url.lastIndexOf('/')); +} + +//folderURL can have the extension .tmp or .tmp_ +//Before OOo 3.4 the created a tmp file with osl_createTempFile and +//then created a Folder with a same name and a trailing '_' +//If the folderURL has no '_' then there is no corresponding tmp file. +void PackageRegistryBackend::deleteTempFolder( + OUString const & folderUrl) +{ + if (folderUrl.getLength()) + { + erase_path( folderUrl, Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + + if (folderUrl[folderUrl.getLength() - 1] == '_') + { + const OUString tempFile = folderUrl.copy(0, folderUrl.getLength() - 1); + erase_path( tempFile, Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + } + } +} + +//usedFolders can contain folder names which have the extension .tmp or .tmp_ +//Before OOo 3.4 we created a tmp file with osl_createTempFile and +//then created a Folder with a same name and a trailing '_' +//If the folderURL has no '_' then there is no corresponding tmp file. +void PackageRegistryBackend::deleteUnusedFolders( + OUString const & relUrl, + ::std::list< OUString> const & usedFolders) +{ + try + { + const OUString sDataFolder = makeURL(getCachePath(), relUrl); + ::ucbhelper::Content tempFolder( + sDataFolder, Reference<ucb::XCommandEnvironment>()); + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_FOLDERS_ONLY ) ); + // get all temp directories: + ::std::vector<OUString> tempEntries; + + const char tmp[] = ".tmp"; + + while (xResultSet->next()) + { + OUString title( + Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString( + 1 /* Title */ ) ); + + if (title.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(tmp))) + tempEntries.push_back( + makeURLAppendSysPathSegment(sDataFolder, title)); + } + + for ( ::std::size_t pos = 0; pos < tempEntries.size(); ++pos ) + { + if (::std::find( usedFolders.begin(), usedFolders.end(), tempEntries[pos] ) == + usedFolders.end()) + { + deleteTempFolder(tempEntries[pos]); + } + } + } + catch (ucb::InteractiveAugmentedIOException& e) + { + //In case the folder containing all the data folder does not + //exist yet, we ignore the exception + if (e.Code != ucb::IOErrorCode_NOT_EXISTING) + throw e; + } + +} + + +//______________________________________________________________________________ +Package::~Package() +{ +} + +//______________________________________________________________________________ +Package::Package( ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, + OUString const & rName, + OUString const & displayName, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, + OUString const & identifier) + : t_PackageBase( getMutex() ), + m_myBackend( myBackend ), + m_url( url ), + m_name( rName ), + m_displayName( displayName ), + m_xPackageType( xPackageType ), + m_bRemoved(bRemoved), + m_identifier(identifier) +{ + if (m_bRemoved) + { + //We use the last segment of the URL + OSL_ASSERT(m_name.getLength() == 0); + OUString name = m_url; + rtl::Bootstrap::expandMacros(name); + sal_Int32 index = name.lastIndexOf('/'); + if (index != -1 && index < name.getLength()) + m_name = name.copy(index + 1); + } +} + +//______________________________________________________________________________ +void Package::disposing() +{ + m_myBackend.clear(); + WeakComponentImplHelperBase::disposing(); +} + +//______________________________________________________________________________ +void Package::check() const +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) { + throw lang::DisposedException( + OUSTR("Package instance has already been disposed!"), + static_cast<OWeakObject *>(const_cast<Package *>(this))); + } +} + +// XComponent +//______________________________________________________________________________ +void Package::dispose() throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::dispose(); +} + +//______________________________________________________________________________ +void Package::addEventListener( + Reference<lang::XEventListener> const & xListener ) throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::addEventListener( xListener ); +} + +//______________________________________________________________________________ +void Package::removeEventListener( + Reference<lang::XEventListener> const & xListener ) throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::removeEventListener( xListener ); +} + +// XModifyBroadcaster +//______________________________________________________________________________ +void Package::addModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (RuntimeException) +{ + check(); + rBHelper.addListener( ::getCppuType( &xListener ), xListener ); +} + +//______________________________________________________________________________ +void Package::removeModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (RuntimeException) +{ + check(); + rBHelper.removeListener( ::getCppuType( &xListener ), xListener ); +} + +//______________________________________________________________________________ +void Package::checkAborted( + ::rtl::Reference<AbortChannel> const & abortChannel ) +{ + if (abortChannel.is() && abortChannel->isAborted()) { + throw CommandAbortedException( + OUSTR("abort!"), static_cast<OWeakObject *>(this) ); + } +} + +// XPackage +//______________________________________________________________________________ +Reference<task::XAbortChannel> Package::createAbortChannel() + throw (RuntimeException) +{ + check(); + return new AbortChannel; +} + +//______________________________________________________________________________ +sal_Bool Package::isBundle() throw (RuntimeException) +{ + return false; // default +} + +//______________________________________________________________________________ +::sal_Int32 Package::checkPrerequisites( + const css::uno::Reference< css::task::XAbortChannel >&, + const css::uno::Reference< css::ucb::XCommandEnvironment >&, + sal_Bool) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return 0; +} + +//______________________________________________________________________________ +::sal_Bool Package::checkDependencies( + const css::uno::Reference< css::ucb::XCommandEnvironment >& ) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::uno::RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return true; +} + + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackage> > Package::getBundle( + Reference<task::XAbortChannel> const &, + Reference<XCommandEnvironment> const & ) + throw (deployment::DeploymentException, + CommandFailedException, CommandAbortedException, + lang::IllegalArgumentException, RuntimeException) +{ + return Sequence< Reference<deployment::XPackage> >(); +} + +//______________________________________________________________________________ +OUString Package::getName() throw (RuntimeException) +{ + return m_name; +} + +beans::Optional<OUString> Package::getIdentifier() throw (RuntimeException) +{ + if (m_bRemoved) + return beans::Optional<OUString>(true, m_identifier); + + return beans::Optional<OUString>(); +} + +//______________________________________________________________________________ +OUString Package::getVersion() throw ( + deployment::ExtensionRemovedException, + RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return OUString(); +} + +//______________________________________________________________________________ +OUString Package::getURL() throw (RuntimeException) +{ + return m_url; +} + +//______________________________________________________________________________ +OUString Package::getDisplayName() throw ( + deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return m_displayName; +} + +//______________________________________________________________________________ +OUString Package::getDescription() throw ( + deployment::ExtensionRemovedException,RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return OUString(); +} + +//______________________________________________________________________________ +OUString Package::getLicenseText() throw ( + deployment::ExtensionRemovedException,RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return OUString(); +} + +//______________________________________________________________________________ +Sequence<OUString> Package::getUpdateInformationURLs() throw ( + deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return Sequence<OUString>(); +} + +//______________________________________________________________________________ +css::beans::StringPair Package::getPublisherInfo() throw ( + deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + css::beans::StringPair aEmptyPair; + return aEmptyPair; +} + +//______________________________________________________________________________ +uno::Reference< css::graphic::XGraphic > Package::getIcon( sal_Bool /*bHighContrast*/ ) + throw (deployment::ExtensionRemovedException, RuntimeException ) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + uno::Reference< css::graphic::XGraphic > aEmpty; + return aEmpty; +} + +//______________________________________________________________________________ +Reference<deployment::XPackageTypeInfo> Package::getPackageType() + throw (RuntimeException) +{ + return m_xPackageType; +} + +//______________________________________________________________________________ +void Package::exportTo( + OUString const & destFolderURL, OUString const & newTitle, + sal_Int32 nameClashAction, Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::ExtensionRemovedException, + CommandFailedException, CommandAbortedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + ::ucbhelper::Content destFolder( destFolderURL, xCmdEnv ); + ::ucbhelper::Content sourceContent( getURL(), xCmdEnv ); + if (! destFolder.transferContent( + sourceContent, ::ucbhelper::InsertOperation_COPY, + newTitle, nameClashAction )) + throw RuntimeException( OUSTR("UCB transferContent() failed!"), 0 ); +} + +//______________________________________________________________________________ +void Package::fireModified() +{ + ::cppu::OInterfaceContainerHelper * container = rBHelper.getContainer( + ::getCppuType( static_cast<Reference< + util::XModifyListener> const *>(0) ) ); + if (container != 0) { + Sequence< Reference<XInterface> > elements( + container->getElements() ); + lang::EventObject evt( static_cast<OWeakObject *>(this) ); + for ( sal_Int32 pos = 0; pos < elements.getLength(); ++pos ) + { + Reference<util::XModifyListener> xListener( + elements[ pos ], UNO_QUERY ); + if (xListener.is()) + xListener->modified( evt ); + } + } +} + +// XPackage +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > Package::isRegistered( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + CommandFailedException, CommandAbortedException, RuntimeException) +{ + try { + ::osl::ResettableMutexGuard guard( getMutex() ); + return isRegistered_( guard, + AbortChannel::get(xAbortChannel), + xCmdEnv ); + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException &) { + throw; + } + catch (CommandAbortedException &) { + throw; + } + catch (deployment::DeploymentException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw deployment::DeploymentException( + OUSTR("unexpected exception occurred!"), + static_cast<OWeakObject *>(this), exc ); + } +} + +//______________________________________________________________________________ +void Package::processPackage_impl( + bool doRegisterPackage, + bool startup, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + check(); + bool action = false; + + try { + try { + ::osl::ResettableMutexGuard guard( getMutex() ); + beans::Optional< beans::Ambiguous<sal_Bool> > option( + isRegistered_( guard, AbortChannel::get(xAbortChannel), + xCmdEnv ) ); + action = (option.IsPresent && + (option.Value.IsAmbiguous || + (doRegisterPackage ? !option.Value.Value + : option.Value.Value))); + if (action) { + + OUString displayName = isRemoved() ? getName() : getDisplayName(); + ProgressLevel progress( + xCmdEnv, + (doRegisterPackage + ? PackageRegistryBackend::StrRegisteringPackage::get() + : PackageRegistryBackend::StrRevokingPackage::get()) + + displayName ); + processPackage_( guard, + doRegisterPackage, + startup, + AbortChannel::get(xAbortChannel), + xCmdEnv ); + } + } + catch (RuntimeException &) { + OSL_FAIL( "### unexpected RuntimeException!" ); + throw; + } + catch (CommandFailedException &) { + throw; + } + catch (CommandAbortedException &) { + throw; + } + catch (deployment::DeploymentException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw deployment::DeploymentException( + (doRegisterPackage + ? getResourceString(RID_STR_ERROR_WHILE_REGISTERING) + : getResourceString(RID_STR_ERROR_WHILE_REVOKING)) + + getDisplayName(), static_cast<OWeakObject *>(this), exc ); + } + } + catch (...) { + if (action) + fireModified(); + throw; + } + if (action) + fireModified(); +} + +//______________________________________________________________________________ +void Package::registerPackage( + sal_Bool startup, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + deployment::ExtensionRemovedException, + CommandFailedException, CommandAbortedException, + lang::IllegalArgumentException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + processPackage_impl( true /* register */, startup, xAbortChannel, xCmdEnv ); +} + +//______________________________________________________________________________ +void Package::revokePackage( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + CommandFailedException, CommandAbortedException, + lang::IllegalArgumentException, RuntimeException) +{ + processPackage_impl( false /* revoke */, false, xAbortChannel, xCmdEnv ); + +} + +PackageRegistryBackend * Package::getMyBackend() const +{ + PackageRegistryBackend * pBackend = m_myBackend.get(); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<Package *>(this))); + } + return pBackend; +} +OUString Package::getRepositoryName() + throw (RuntimeException) +{ + PackageRegistryBackend * backEnd = getMyBackend(); + return backEnd->getContext(); +} + +beans::Optional< OUString > Package::getRegistrationDataURL() + throw (deployment::ExtensionRemovedException, + css::uno::RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return beans::Optional<OUString>(); +} + +sal_Bool Package::isRemoved() + throw (RuntimeException) +{ + return m_bRemoved; +} + + +//______________________________________________________________________________ +Package::TypeInfo::~TypeInfo() +{ +} + +// XPackageTypeInfo +//______________________________________________________________________________ +OUString Package::TypeInfo::getMediaType() throw (RuntimeException) +{ + return m_mediaType; +} + +//______________________________________________________________________________ +OUString Package::TypeInfo::getDescription() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + return getShortDescription(); +} + +//______________________________________________________________________________ +OUString Package::TypeInfo::getShortDescription() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + return m_shortDescr; +} + +//______________________________________________________________________________ +OUString Package::TypeInfo::getFileFilter() throw (RuntimeException) +{ + return m_fileFilter; +} + +//______________________________________________________________________________ +/************************** + * Get Icon + * + * @param highContrast NOTE: disabled the returning of high contrast icons. + * This bool is a noop now. + * @param smallIcon Return the small version of the icon + */ +Any Package::TypeInfo::getIcon( sal_Bool /*highContrast*/, sal_Bool smallIcon ) + throw (RuntimeException) +{ + if (! smallIcon) + return Any(); + const sal_uInt16 nIconId = m_smallIcon; + return Any( &nIconId, getCppuType( static_cast<sal_uInt16 const *>(0) ) ); +} + +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/dp_backenddb.cxx b/desktop/source/deployment/registry/dp_backenddb.cxx new file mode 100644 index 000000000000..5054564eae25 --- /dev/null +++ b/desktop/source/deployment/registry/dp_backenddb.cxx @@ -0,0 +1,716 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "rtl/string.h" +#include "rtl/strbuf.hxx" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "osl/file.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "com/sun/star/io/XActiveDataSource.hpp" +#include "com/sun/star/io/XActiveDataControl.hpp" +#include "dp_ucb.h" +#include "dp_misc.h" +#include "ucbhelper/content.hxx" +#include "xmlscript/xml_helper.hxx" +#include "dp_backenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + + +namespace dp_registry { +namespace backend { + +BackendDb::BackendDb( + Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url): + m_xContext(xContext) +{ + m_urlDb = dp_misc::expandUnoRcUrl(url); +} + +void BackendDb::save() +{ + const Reference<css::io::XActiveDataSource> xDataSource(m_doc,css::uno::UNO_QUERY_THROW); + ::rtl::ByteSequence bytes; + xDataSource->setOutputStream(::xmlscript::createOutputStream(&bytes)); + const Reference<css::io::XActiveDataControl> xDataControl(m_doc,css::uno::UNO_QUERY_THROW); + xDataControl->start(); + + const Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream(bytes)); + ::ucbhelper::Content ucbDb(m_urlDb, 0); + ucbDb.writeStream(xData, true /*replace existing*/); +} + +css::uno::Reference<css::xml::dom::XDocument> BackendDb::getDocument() +{ + if (!m_doc.is()) + { + const Reference<css::xml::dom::XDocumentBuilder> xDocBuilder( + m_xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.dom.DocumentBuilder"), + m_xContext ), css::uno::UNO_QUERY); + if (!xDocBuilder.is()) + throw css::uno::RuntimeException( + OUSTR(" Could not create service com.sun.star.xml.dom.DocumentBuilder"), 0); + + ::osl::DirectoryItem item; + ::osl::File::RC err = ::osl::DirectoryItem::get(m_urlDb, item); + if (err == ::osl::File::E_None) + { + ::ucbhelper::Content descContent( + m_urlDb, css::uno::Reference<css::ucb::XCommandEnvironment>()); + Reference<css::io::XInputStream> xIn = descContent.openStream(); + m_doc = xDocBuilder->parse(xIn); + } + else if (err == ::osl::File::E_NOENT) + { + //Create a new document and insert some basic stuff + m_doc = xDocBuilder->newDocument(); + const Reference<css::xml::dom::XElement> rootNode = + m_doc->createElementNS(getDbNSName(), getNSPrefix() + + OUSTR(":") + getRootElementName()); + + m_doc->appendChild(Reference<css::xml::dom::XNode>( + rootNode, UNO_QUERY_THROW)); + save(); + } + else + throw css::uno::RuntimeException( + OUSTR("Extension manager could not access database file:" ) + + m_urlDb, 0); + + if (!m_doc.is()) + throw css::uno::RuntimeException( + OUSTR("Extension manager could not get root node of data base file: ") + + m_urlDb, 0); + } + + return m_doc; +} + +Reference<css::xml::xpath::XXPathAPI> BackendDb::getXPathAPI() +{ + if (!m_xpathApi.is()) + { + m_xpathApi = Reference< css::xml::xpath::XXPathAPI >( + m_xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.xpath.XPathAPI"), + m_xContext), css::uno::UNO_QUERY); + + if (!m_xpathApi.is()) + throw css::uno::RuntimeException( + OUSTR(" Could not create service com.sun.star.xml.xpath.XPathAPI"), 0); + + m_xpathApi->registerNS( + getNSPrefix(), getDbNSName()); + } + + return m_xpathApi; +} + +void BackendDb::removeElement(::rtl::OUString const & sXPathExpression) +{ + try + { + const Reference<css::xml::dom::XDocument> doc = getDocument(); + const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + //find the extension element that is to be removed + const Reference<css::xml::dom::XNode> aNode = + xpathApi->selectSingleNode(root, sXPathExpression); + + if (aNode.is()) + { + root->removeChild(aNode); + save(); + } + +#if OSL_DEBUG_LEVEL > 0 + //There must not be any other entry with the same url + const Reference<css::xml::dom::XNode> nextNode = + xpathApi->selectSingleNode(root, sXPathExpression); + OSL_ASSERT(! nextNode.is()); +#endif + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +void BackendDb::removeEntry(::rtl::OUString const & url) +{ + const OUString sKeyElement = getKeyElementName(); + const OUString sPrefix = getNSPrefix(); + ::rtl::OUStringBuffer sExpression(500); + sExpression.append(sPrefix); + sExpression.appendAscii(":"); + sExpression.append(sKeyElement); + sExpression.append(OUSTR("[@url = \"")); + sExpression.append(url); + sExpression.appendAscii("\"]"); + + removeElement(sExpression.makeStringAndClear()); +} + +void BackendDb::revokeEntry(::rtl::OUString const & url) +{ + try + { + Reference<css::xml::dom::XElement> entry = Reference<css::xml::dom::XElement>(getKeyElement(url), UNO_QUERY); + if (entry.is()) + { + entry->setAttribute(OUSTR("revoked"), OUSTR("true")); + save(); + } + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to revoke data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +bool BackendDb::activateEntry(::rtl::OUString const & url) +{ + try + { + bool ret = false; + Reference<css::xml::dom::XElement> entry = Reference<css::xml::dom::XElement>(getKeyElement(url), UNO_QUERY); + if (entry.is()) + { + //no attribute "active" means it is active, that is, registered. + entry->removeAttribute(OUSTR("revoked")); + save(); + ret = true; + } + return ret; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to revoke data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +bool BackendDb::hasActiveEntry(::rtl::OUString const & url) +{ + try + { + bool ret = false; + Reference<css::xml::dom::XElement> entry = Reference<css::xml::dom::XElement>(getKeyElement(url), UNO_QUERY); + if (entry.is()) + { + OUString sActive = entry->getAttribute(OUSTR("revoked")); + if (!sActive.equals(OUSTR("true"))) + ret = true; + } + return ret; + + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to determine an active entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +Reference<css::xml::dom::XNode> BackendDb::getKeyElement( + ::rtl::OUString const & url) +{ + try + { + const OUString sPrefix = getNSPrefix(); + const OUString sKeyElement = getKeyElementName(); + ::rtl::OUStringBuffer sExpression(500); + sExpression.append(sPrefix); + sExpression.appendAscii(":"); + sExpression.append(sKeyElement); + sExpression.append(OUSTR("[@url = \"")); + sExpression.append(url); + sExpression.appendAscii("\"]"); + + const Reference<css::xml::dom::XDocument> doc = getDocument(); + const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + return xpathApi->selectSingleNode(root, sExpression.makeStringAndClear()); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read key element in backend db: ") + + m_urlDb, 0, exc); + } +} + +//Only writes the data if there is at least one entry +void BackendDb::writeVectorOfPair( + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString > > const & vecPairs, + OUString const & sVectorTagName, + OUString const & sPairTagName, + OUString const & sFirstTagName, + OUString const & sSecondTagName, + css::uno::Reference<css::xml::dom::XNode> const & xParent) +{ + try{ + if (vecPairs.size() == 0) + return; + const OUString sNameSpace = getDbNSName(); + OSL_ASSERT(sNameSpace.getLength()); + const OUString sPrefix(getNSPrefix() + OUSTR(":")); + const Reference<css::xml::dom::XDocument> doc = getDocument(); + const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + const Reference<css::xml::dom::XElement> vectorNode( + doc->createElementNS(sNameSpace, sPrefix + sVectorTagName)); + + xParent->appendChild( + Reference<css::xml::dom::XNode>( + vectorNode, css::uno::UNO_QUERY_THROW)); + typedef ::std::vector< ::std::pair< OUString, OUString > >::const_iterator CIT; + for (CIT i = vecPairs.begin(); i != vecPairs.end(); i++) + { + const Reference<css::xml::dom::XElement> pairNode( + doc->createElementNS(sNameSpace, sPrefix + sPairTagName)); + + vectorNode->appendChild( + Reference<css::xml::dom::XNode>( + pairNode, css::uno::UNO_QUERY_THROW)); + + const Reference<css::xml::dom::XElement> firstNode( + doc->createElementNS(sNameSpace, sPrefix + sFirstTagName)); + + pairNode->appendChild( + Reference<css::xml::dom::XNode>( + firstNode, css::uno::UNO_QUERY_THROW)); + + const Reference<css::xml::dom::XText> firstTextNode( + doc->createTextNode( i->first)); + + firstNode->appendChild( + Reference<css::xml::dom::XNode>( + firstTextNode, css::uno::UNO_QUERY_THROW)); + + const Reference<css::xml::dom::XElement> secondNode( + doc->createElementNS(sNameSpace, sPrefix + sSecondTagName)); + + pairNode->appendChild( + Reference<css::xml::dom::XNode>( + secondNode, css::uno::UNO_QUERY_THROW)); + + const Reference<css::xml::dom::XText> secondTextNode( + doc->createTextNode( i->second)); + + secondNode->appendChild( + Reference<css::xml::dom::XNode>( + secondTextNode, css::uno::UNO_QUERY_THROW)); + } + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +::std::vector< ::std::pair< OUString, OUString > > +BackendDb::readVectorOfPair( + Reference<css::xml::dom::XNode> const & parent, + OUString const & sListTagName, + OUString const & sPairTagName, + OUString const & sFirstTagName, + OUString const & sSecondTagName) +{ + try + { + OSL_ASSERT(parent.is()); + const OUString sPrefix(getNSPrefix() + OUSTR(":")); + const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const OUString sExprPairs( + sPrefix + sListTagName + OUSTR("/") + sPrefix + sPairTagName); + const Reference<css::xml::dom::XNodeList> listPairs = + xpathApi->selectNodeList(parent, sExprPairs); + + ::std::vector< ::std::pair< OUString, OUString > > retVector; + sal_Int32 length = listPairs->getLength(); + for (sal_Int32 i = 0; i < length; i++) + { + const Reference<css::xml::dom::XNode> aPair = listPairs->item(i); + const OUString sExprFirst(sPrefix + sFirstTagName + OUSTR("/text()")); + const Reference<css::xml::dom::XNode> first = + xpathApi->selectSingleNode(aPair, sExprFirst); + + const OUString sExprSecond(sPrefix + sSecondTagName + OUSTR("/text()")); + const Reference<css::xml::dom::XNode> second = + xpathApi->selectSingleNode(aPair, sExprSecond); + OSL_ASSERT(first.is() && second.is()); + + retVector.push_back(::std::make_pair( + first->getNodeValue(), second->getNodeValue())); + } + return retVector; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +//Only writes the data if there is at least one entry +void BackendDb::writeSimpleList( + ::std::list< ::rtl::OUString> const & list, + OUString const & sListTagName, + OUString const & sMemberTagName, + Reference<css::xml::dom::XNode> const & xParent) +{ + try + { + if (list.size() == 0) + return; + const OUString sNameSpace = getDbNSName(); + const OUString sPrefix(getNSPrefix() + OUSTR(":")); + const Reference<css::xml::dom::XDocument> doc = getDocument(); + + const Reference<css::xml::dom::XElement> listNode( + doc->createElementNS(sNameSpace, sPrefix + sListTagName)); + + xParent->appendChild( + Reference<css::xml::dom::XNode>( + listNode, css::uno::UNO_QUERY_THROW)); + + typedef ::std::list<OUString>::const_iterator ITC_ITEMS; + for (ITC_ITEMS i = list.begin(); i != list.end(); ++i) + { + const Reference<css::xml::dom::XNode> memberNode( + doc->createElementNS(sNameSpace, sPrefix + sMemberTagName), css::uno::UNO_QUERY_THROW); + + listNode->appendChild(memberNode); + + const Reference<css::xml::dom::XNode> textNode( + doc->createTextNode( *i), css::uno::UNO_QUERY_THROW); + + memberNode->appendChild(textNode); + } + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +//Writes only the element if is has a value. +//The prefix is automatically added to the element name +void BackendDb::writeSimpleElement( + OUString const & sElementName, OUString const & value, + Reference<css::xml::dom::XNode> const & xParent) +{ + try + { + if (value.getLength() == 0) + return; + const OUString sPrefix = getNSPrefix(); + const Reference<css::xml::dom::XDocument> doc = getDocument(); + const OUString sNameSpace = getDbNSName(); + const Reference<css::xml::dom::XNode> dataNode( + doc->createElementNS(sNameSpace, sPrefix + OUSTR(":") + sElementName), + UNO_QUERY_THROW); + xParent->appendChild(dataNode); + + const Reference<css::xml::dom::XNode> dataValue( + doc->createTextNode(value), UNO_QUERY_THROW); + dataNode->appendChild(dataValue); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry(writeSimpleElement) in backend db: ") + + m_urlDb, 0, exc); + } + +} + +/** The key elements have an url attribute and are always children of the root + element. +*/ +Reference<css::xml::dom::XNode> BackendDb::writeKeyElement( + ::rtl::OUString const & url) +{ + try + { + const OUString sNameSpace = getDbNSName(); + const OUString sPrefix = getNSPrefix(); + const OUString sElementName = getKeyElementName(); + const Reference<css::xml::dom::XDocument> doc = getDocument(); + const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + //Check if there are an entry with the same url. This can be the case if the + //the status of an XPackage is ambiguous. In this case a call to activateExtension + //(dp_extensionmanager.cxx), will register the package again. See also + //Package::processPackage_impl in dp_backend.cxx. + //A package can become + //invalid after its successful registration, for example if a second extension with + //the same service is installed. + const OUString sExpression( + sPrefix + OUSTR(":") + sElementName + OUSTR("[@url = \"") + url + OUSTR("\"]")); + const Reference<css::xml::dom::XNode> existingNode = + getXPathAPI()->selectSingleNode(root, sExpression); + if (existingNode.is()) + { + OSL_ASSERT(0); + //replace the existing entry. + removeEntry(url); + } + + const Reference<css::xml::dom::XElement> keyElement( + doc->createElementNS(sNameSpace, sPrefix + OUSTR(":") + sElementName)); + + keyElement->setAttribute(OUSTR("url"), url); + + const Reference<css::xml::dom::XNode> keyNode( + keyElement, UNO_QUERY_THROW); + root->appendChild(keyNode); + return keyNode; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write key element in backend db: ") + + m_urlDb, 0, exc); + } +} + +OUString BackendDb::readSimpleElement( + OUString const & sElementName, Reference<css::xml::dom::XNode> const & xParent) +{ + try + { + const OUString sPrefix = getNSPrefix(); + const OUString sExpr(sPrefix + OUSTR(":") + sElementName + OUSTR("/text()")); + const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const Reference<css::xml::dom::XNode> val = + xpathApi->selectSingleNode(xParent, sExpr); + if (val.is()) + return val->getNodeValue(); + return OUString(); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data (readSimpleElement) in backend db: ") + + m_urlDb, 0, exc); + } +} + + +::std::list< OUString> BackendDb::readList( + Reference<css::xml::dom::XNode> const & parent, + OUString const & sListTagName, + OUString const & sMemberTagName) +{ + try + { + OSL_ASSERT(parent.is()); + const OUString sPrefix(getNSPrefix() + OUSTR(":")); + const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const OUString sExprList( + sPrefix + sListTagName + OUSTR("/") + sPrefix + sMemberTagName + OUSTR("/text()")); + const Reference<css::xml::dom::XNodeList> list = + xpathApi->selectNodeList(parent, sExprList); + + ::std::list<OUString > retList; + sal_Int32 length = list->getLength(); + for (sal_Int32 i = 0; i < length; i++) + { + const Reference<css::xml::dom::XNode> member = list->item(i); + retList.push_back(member->getNodeValue()); + } + return retList; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +::std::list<OUString> BackendDb::getOneChildFromAllEntries( + OUString const & name) +{ + try + { + ::std::list<OUString> listRet; + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const OUString sPrefix = getNSPrefix(); + const OUString sKeyElement = getKeyElementName(); + ::rtl::OUStringBuffer buf(512); + buf.append(sPrefix); + buf.appendAscii(":"); + buf.append(sKeyElement); + buf.appendAscii("/"); + buf.append(sPrefix); + buf.appendAscii(":"); + buf.append(name); + buf.append(OUSTR("/text()")); + + Reference<css::xml::dom::XNodeList> nodes = + xpathApi->selectNodeList(root, buf.makeStringAndClear()); + if (nodes.is()) + { + sal_Int32 length = nodes->getLength(); + for (sal_Int32 i = 0; i < length; i++) + listRet.push_back(nodes->item(i)->getNodeValue()); + } + return listRet; + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + + +RegisteredDb::RegisteredDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ +} + +void RegisteredDb::addEntry(::rtl::OUString const & url) +{ + try{ + if (!activateEntry(url)) + { + const OUString sNameSpace = getDbNSName(); + const OUString sPrefix = getNSPrefix(); + const OUString sEntry = getKeyElementName(); + + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + +#if OSL_DEBUG_LEVEL > 0 + //There must not be yet an entry with the same url + OUString sExpression( + sPrefix + OUSTR(":") + sEntry + OUSTR("[@url = \"") + url + OUSTR("\"]")); + Reference<css::xml::dom::XNode> _extensionNode = + getXPathAPI()->selectSingleNode(root, sExpression); + OSL_ASSERT(! _extensionNode.is()); +#endif + Reference<css::xml::dom::XElement> helpElement( + doc->createElementNS(sNameSpace, sPrefix + OUSTR(":") + sEntry)); + + helpElement->setAttribute(OUSTR("url"), url); + + Reference<css::xml::dom::XNode> helpNode( + helpElement, UNO_QUERY_THROW); + root->appendChild(helpNode); + + save(); + } + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +bool RegisteredDb::getEntry(::rtl::OUString const & url) +{ + try + { + const OUString sPrefix = getNSPrefix(); + const OUString sEntry = getKeyElementName(); + const OUString sExpression( + sPrefix + OUSTR(":") + sEntry + OUSTR("[@url = \"") + url + OUSTR("\"]")); + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + Reference<css::xml::dom::XNode> aNode = + xpathApi->selectSingleNode(root, sExpression); + + return aNode.is(); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/dp_registry.cxx b/desktop/source/deployment/registry/dp_registry.cxx new file mode 100644 index 000000000000..9e799dd2d559 --- /dev/null +++ b/desktop/source/deployment/registry/dp_registry.cxx @@ -0,0 +1,578 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_registry.hrc" +#include "dp_misc.h" +#include "dp_resource.h" +#include "dp_interact.h" +#include "dp_ucb.h" +#include "osl/diagnose.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/uri.hxx" +#include "cppuhelper/compbase2.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "comphelper/sequence.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/uno/DeploymentException.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/util/XUpdatable.hpp" +#include "com/sun/star/container/XContentEnumerationAccess.hpp" +#include "com/sun/star/deployment/PackageRegistryBackend.hpp" +#include <boost/unordered_map.hpp> +#include <set> +#include <boost/unordered_set.hpp> +#include <memory> + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + + +namespace dp_registry { + +namespace backend { +namespace bundle { +Reference<deployment::XPackageRegistry> create( + Reference<deployment::XPackageRegistry> const & xRootRegistry, + OUString const & context, OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ); +} +} + +namespace { + +typedef ::cppu::WeakComponentImplHelper2< + deployment::XPackageRegistry, util::XUpdatable > t_helper; + +//============================================================================== +class PackageRegistryImpl : private MutexHolder, public t_helper +{ + struct ci_string_hash { + ::std::size_t operator () ( OUString const & str ) const { + return str.toAsciiLowerCase().hashCode(); + } + }; + struct ci_string_equals { + bool operator () ( OUString const & str1, OUString const & str2 ) const{ + return str1.equalsIgnoreAsciiCase( str2 ); + } + }; + typedef ::boost::unordered_map< + OUString, Reference<deployment::XPackageRegistry>, + ci_string_hash, ci_string_equals > t_string2registry; + typedef ::boost::unordered_map< + OUString, OUString, + ci_string_hash, ci_string_equals > t_string2string; + typedef ::std::set< + Reference<deployment::XPackageRegistry> > t_registryset; + + t_string2registry m_mediaType2backend; + t_string2string m_filter2mediaType; + t_registryset m_ambiguousBackends; + t_registryset m_allBackends; + ::std::vector< Reference<deployment::XPackageTypeInfo> > m_typesInfos; + + void insertBackend( + Reference<deployment::XPackageRegistry> const & xBackend ); + +protected: + inline void check(); + virtual void SAL_CALL disposing(); + + virtual ~PackageRegistryImpl(); + PackageRegistryImpl() : t_helper( getMutex() ) {} + + +public: + static Reference<deployment::XPackageRegistry> create( + OUString const & context, + OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ); + + // XUpdatable + virtual void SAL_CALL update() throw (RuntimeException); + + // XPackageRegistry + virtual Reference<deployment::XPackage> SAL_CALL bindPackage( + OUString const & url, OUString const & mediaType, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + deployment::InvalidRemovedParameterException, + CommandFailedException, + lang::IllegalArgumentException, RuntimeException); + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) + throw (deployment::DeploymentException, + RuntimeException); + +}; + +//______________________________________________________________________________ +inline void PackageRegistryImpl::check() +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) { + throw lang::DisposedException( + OUSTR("PackageRegistry instance has already been disposed!"), + static_cast<OWeakObject *>(this) ); + } +} + +//______________________________________________________________________________ +void PackageRegistryImpl::disposing() +{ + // dispose all backends: + t_registryset::const_iterator iPos( m_allBackends.begin() ); + t_registryset::const_iterator const iEnd( m_allBackends.end() ); + for ( ; iPos != iEnd; ++iPos ) { + try_dispose( *iPos ); + } + m_mediaType2backend = t_string2registry(); + m_ambiguousBackends = t_registryset(); + m_allBackends = t_registryset(); + + t_helper::disposing(); +} + +//______________________________________________________________________________ +PackageRegistryImpl::~PackageRegistryImpl() +{ +} + +//______________________________________________________________________________ +OUString normalizeMediaType( OUString const & mediaType ) +{ + ::rtl::OUStringBuffer buf; + sal_Int32 index = 0; + for (;;) { + buf.append( mediaType.getToken( 0, '/', index ).trim() ); + if (index < 0) + break; + buf.append( static_cast< sal_Unicode >('/') ); + } + return buf.makeStringAndClear(); +} + +//______________________________________________________________________________ + +void PackageRegistryImpl::packageRemoved( + ::rtl::OUString const & url, ::rtl::OUString const & mediaType) + throw (css::deployment::DeploymentException, + css::uno::RuntimeException) +{ + const t_string2registry::const_iterator i = + m_mediaType2backend.find(mediaType); + + if (i != m_mediaType2backend.end()) + { + i->second->packageRemoved(url, mediaType); + } +} + +void PackageRegistryImpl::insertBackend( + Reference<deployment::XPackageRegistry> const & xBackend ) +{ + m_allBackends.insert( xBackend ); + typedef ::boost::unordered_set<OUString, ::rtl::OUStringHash> t_stringset; + t_stringset ambiguousFilters; + + const Sequence< Reference<deployment::XPackageTypeInfo> > packageTypes( + xBackend->getSupportedPackageTypes() ); + for ( sal_Int32 pos = 0; pos < packageTypes.getLength(); ++pos ) + { + Reference<deployment::XPackageTypeInfo> const & xPackageType = + packageTypes[ pos ]; + m_typesInfos.push_back( xPackageType ); + + const OUString mediaType( normalizeMediaType( + xPackageType->getMediaType() ) ); + ::std::pair<t_string2registry::iterator, bool> mb_insertion( + m_mediaType2backend.insert( t_string2registry::value_type( + mediaType, xBackend ) ) ); + if (mb_insertion.second) + { + // add parameterless media-type, too: + sal_Int32 semi = mediaType.indexOf( ';' ); + if (semi >= 0) { + m_mediaType2backend.insert( + t_string2registry::value_type( + mediaType.copy( 0, semi ), xBackend ) ); + } + const OUString fileFilter( xPackageType->getFileFilter() ); + //The package backend shall also be called to determine the mediatype + //(XPackageRegistry.bindPackage) when the URL points to a directory. + const bool bExtension = mediaType.equals(OUSTR("application/vnd.sun.star.package-bundle")); + if (fileFilter.getLength() == 0 || + fileFilter.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*.*") ) || + fileFilter.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*") ) || + bExtension) + { + m_ambiguousBackends.insert( xBackend ); + } + else + { + sal_Int32 nIndex = 0; + do { + OUString token( fileFilter.getToken( 0, ';', nIndex ) ); + if (token.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("*.") )) + token = token.copy( 1 ); + if (token.getLength() == 0) + continue; + // mark any further wildcards ambig: + bool ambig = (token.indexOf('*') >= 0 || + token.indexOf('?') >= 0); + if (! ambig) { + ::std::pair<t_string2string::iterator, bool> ins( + m_filter2mediaType.insert( + t_string2string::value_type( + token, mediaType ) ) ); + ambig = !ins.second; + if (ambig) { + // filter has already been in: add previously + // added backend to ambig set + const t_string2registry::const_iterator iFind( + m_mediaType2backend.find( + /* media-type of pr. added backend */ + ins.first->second ) ); + OSL_ASSERT( + iFind != m_mediaType2backend.end() ); + if (iFind != m_mediaType2backend.end()) + m_ambiguousBackends.insert( iFind->second ); + } + } + if (ambig) { + m_ambiguousBackends.insert( xBackend ); + // mark filter to be removed later from filters map: + ambiguousFilters.insert( token ); + } + } + while (nIndex >= 0); + } + } +#if OSL_DEBUG_LEVEL > 0 + else { + ::rtl::OUStringBuffer buf; + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM( + "more than one PackageRegistryBackend for " + "media-type=\"") ); + buf.append( mediaType ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" => ") ); + buf.append( Reference<lang::XServiceInfo>( + xBackend, UNO_QUERY_THROW )-> + getImplementationName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") ); + OSL_FAIL( ::rtl::OUStringToOString( + buf.makeStringAndClear(), + RTL_TEXTENCODING_UTF8 ) ); + } +#endif + } + + // cut out ambiguous filters: + t_stringset::const_iterator iPos( ambiguousFilters.begin() ); + const t_stringset::const_iterator iEnd( ambiguousFilters.end() ); + for ( ; iPos != iEnd; ++iPos ) { + m_filter2mediaType.erase( *iPos ); + } +} + +//______________________________________________________________________________ +Reference<deployment::XPackageRegistry> PackageRegistryImpl::create( + OUString const & context, + OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ) +{ + PackageRegistryImpl * that = new PackageRegistryImpl; + Reference<deployment::XPackageRegistry> xRet(that); + + // auto-detect all registered package registries: + Reference<container::XEnumeration> xEnum( + Reference<container::XContentEnumerationAccess>( + xComponentContext->getServiceManager(), + UNO_QUERY_THROW )->createContentEnumeration( + OUSTR("com.sun.star.deployment.PackageRegistryBackend") ) ); + if (xEnum.is()) + { + while (xEnum->hasMoreElements()) + { + Any element( xEnum->nextElement() ); + Sequence<Any> registryArgs( + cachePath.getLength() == 0 ? 1 : 3 ); + registryArgs[ 0 ] <<= context; + if (cachePath.getLength() > 0) + { + Reference<lang::XServiceInfo> xServiceInfo( + element, UNO_QUERY_THROW ); + OUString registryCachePath( + makeURL( cachePath, + ::rtl::Uri::encode( + xServiceInfo->getImplementationName(), + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ) ); + registryArgs[ 1 ] <<= registryCachePath; + registryArgs[ 2 ] <<= readOnly; + if (! readOnly) + create_folder( 0, registryCachePath, + Reference<XCommandEnvironment>() ); + } + + Reference<deployment::XPackageRegistry> xBackend; + Reference<lang::XSingleComponentFactory> xFac( element, UNO_QUERY ); + if (xFac.is()) { + xBackend.set( + xFac->createInstanceWithArgumentsAndContext( + registryArgs, xComponentContext ), UNO_QUERY ); + } + else { + Reference<lang::XSingleServiceFactory> xSingleServiceFac( + element, UNO_QUERY_THROW ); + xBackend.set( + xSingleServiceFac->createInstanceWithArguments( + registryArgs ), UNO_QUERY ); + } + if (! xBackend.is()) { + throw DeploymentException( + OUSTR("cannot instantiate PackageRegistryBackend service: ") + + Reference<lang::XServiceInfo>( + element, UNO_QUERY_THROW )->getImplementationName(), + static_cast<OWeakObject *>(that) ); + } + + that->insertBackend( xBackend ); + } + } + + // Insert bundle back-end. + // Always register as last, because we want to add extensions also as folders + // and as a default we accept every folder, which was not recognized by the other + // backends. + Reference<deployment::XPackageRegistry> extensionBackend = + ::dp_registry::backend::bundle::create( + that, context, cachePath, readOnly, xComponentContext); + that->insertBackend(extensionBackend); + + Reference<lang::XServiceInfo> xServiceInfo( + extensionBackend, UNO_QUERY_THROW ); + + OSL_ASSERT(xServiceInfo.is()); + OUString registryCachePath( + makeURL( cachePath, + ::rtl::Uri::encode( + xServiceInfo->getImplementationName(), + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ) ); + create_folder( 0, registryCachePath, Reference<XCommandEnvironment>()); + + +#if OSL_DEBUG_LEVEL > 1 + // dump tables: + { + t_registryset allBackends; + dp_misc::TRACE("> [dp_registry.cxx] media-type detection:\n\n" ); + for ( t_string2string::const_iterator iPos( + that->m_filter2mediaType.begin() ); + iPos != that->m_filter2mediaType.end(); ++iPos ) + { + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("extension \"") ); + buf.append( iPos->first ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\" maps to media-type \"") ); + buf.append( iPos->second ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\" maps to backend ") ); + const Reference<deployment::XPackageRegistry> xBackend( + that->m_mediaType2backend.find( iPos->second )->second ); + allBackends.insert( xBackend ); + buf.append( Reference<lang::XServiceInfo>( + xBackend, UNO_QUERY_THROW ) + ->getImplementationName() ); + dp_misc::writeConsole( buf.makeStringAndClear() + OUSTR("\n")); + } + dp_misc::TRACE( "> [dp_registry.cxx] ambiguous backends:\n\n" ); + for ( t_registryset::const_iterator iPos( + that->m_ambiguousBackends.begin() ); + iPos != that->m_ambiguousBackends.end(); ++iPos ) + { + ::rtl::OUStringBuffer buf; + buf.append( + Reference<lang::XServiceInfo>( + *iPos, UNO_QUERY_THROW )->getImplementationName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") ); + const Sequence< Reference<deployment::XPackageTypeInfo> > types( + (*iPos)->getSupportedPackageTypes() ); + for ( sal_Int32 pos = 0; pos < types.getLength(); ++pos ) { + Reference<deployment::XPackageTypeInfo> const & xInfo = + types[ pos ]; + buf.append( xInfo->getMediaType() ); + const OUString filter( xInfo->getFileFilter() ); + if (filter.getLength() > 0) { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (") ); + buf.append( filter ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") ); + } + if (pos < (types.getLength() - 1)) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); + } + dp_misc::TRACE(buf.makeStringAndClear() + OUSTR("\n\n")); + } + allBackends.insert( that->m_ambiguousBackends.begin(), + that->m_ambiguousBackends.end() ); + OSL_ASSERT( allBackends == that->m_allBackends ); + } +#endif + + return xRet; +} + +// XUpdatable: broadcast to backends +//______________________________________________________________________________ +void PackageRegistryImpl::update() throw (RuntimeException) +{ + check(); + t_registryset::const_iterator iPos( m_allBackends.begin() ); + const t_registryset::const_iterator iEnd( m_allBackends.end() ); + for ( ; iPos != iEnd; ++iPos ) { + const Reference<util::XUpdatable> xUpdatable( *iPos, UNO_QUERY ); + if (xUpdatable.is()) + xUpdatable->update(); + } +} + +// XPackageRegistry +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageRegistryImpl::bindPackage( + OUString const & url, OUString const & mediaType_, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, deployment::InvalidRemovedParameterException, + CommandFailedException, + lang::IllegalArgumentException, RuntimeException) +{ + check(); + OUString mediaType(mediaType_); + if (mediaType.getLength() == 0) + { + ::ucbhelper::Content ucbContent; + if (create_ucb_content( + &ucbContent, url, xCmdEnv, false /* no throw */ ) + && !ucbContent.isFolder()) + { + OUString title( ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + for (;;) + { + const t_string2string::const_iterator iFind( + m_filter2mediaType.find(title) ); + if (iFind != m_filter2mediaType.end()) { + mediaType = iFind->second; + break; + } + sal_Int32 point = title.indexOf( '.', 1 /* consume . */ ); + if (point < 0) + break; + title = title.copy(point); + } + } + } + if (mediaType.getLength() == 0) + { + // try ambiguous backends: + t_registryset::const_iterator iPos( m_ambiguousBackends.begin() ); + const t_registryset::const_iterator iEnd( m_ambiguousBackends.end() ); + for ( ; iPos != iEnd; ++iPos ) + { + try { + return (*iPos)->bindPackage( url, mediaType, bRemoved, + identifier, xCmdEnv ); + } + catch (lang::IllegalArgumentException &) { + } + } + throw lang::IllegalArgumentException( + getResourceString(RID_STR_CANNOT_DETECT_MEDIA_TYPE) + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + else + { + // get backend by media-type: + t_string2registry::const_iterator iFind( + m_mediaType2backend.find( normalizeMediaType(mediaType) ) ); + if (iFind == m_mediaType2backend.end()) { + // xxx todo: more sophisticated media-type argument parsing... + sal_Int32 q = mediaType.indexOf( ';' ); + if (q >= 0) { + iFind = m_mediaType2backend.find( + normalizeMediaType( + // cut parameters: + mediaType.copy( 0, q ) ) ); + } + } + if (iFind == m_mediaType2backend.end()) { + throw lang::IllegalArgumentException( + getResourceString(RID_STR_UNSUPPORTED_MEDIA_TYPE) + mediaType, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + return iFind->second->bindPackage( url, mediaType, bRemoved, + identifier, xCmdEnv ); + } +} + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +PackageRegistryImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return comphelper::containerToSequence(m_typesInfos); +} +} // anon namespace + +//============================================================================== +Reference<deployment::XPackageRegistry> SAL_CALL create( + OUString const & context, + OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ) +{ + return PackageRegistryImpl::create( + context, cachePath, readOnly, xComponentContext ); +} + +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/dp_registry.src b/desktop/source/deployment/registry/dp_registry.src new file mode 100644 index 000000000000..68a52621741f --- /dev/null +++ b/desktop/source/deployment/registry/dp_registry.src @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_registry.hrc" + +String RID_STR_REGISTERING_PACKAGE +{ + Text [ en-US ] = "Enabling: "; +}; + +String RID_STR_REVOKING_PACKAGE +{ + Text [ en-US ] = "Disabling: "; +}; + +String RID_STR_CANNOT_DETECT_MEDIA_TYPE +{ + Text [ en-US ] = "Cannot detect media-type: "; +}; + +String RID_STR_UNSUPPORTED_MEDIA_TYPE +{ + Text [ en-US ] = "This media-type is not supported: "; +}; + +String RID_STR_ERROR_WHILE_REGISTERING +{ + Text [ en-US ] = "An error occurred while enabling: "; +}; + +String RID_STR_ERROR_WHILE_REVOKING +{ + Text [ en-US ] = "An error occurred while disabling: "; +}; + diff --git a/desktop/source/deployment/registry/executable/dp_executable.cxx b/desktop/source/deployment/registry/executable/dp_executable.cxx new file mode 100644 index 000000000000..3579695ce81a --- /dev/null +++ b/desktop/source/deployment/registry/executable/dp_executable.cxx @@ -0,0 +1,344 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_misc.h" +#include "dp_backend.h" +#include "dp_ucb.h" +#include "dp_interact.h" +#include "rtl/string.hxx" +#include "osl/file.hxx" +#include "ucbhelper/content.hxx" +#include "comphelper/servicedecl.hxx" +#include "svl/inettype.hxx" +#include "cppuhelper/implbase1.hxx" +#include "dp_executablebackenddb.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace dp_misc; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace executable { +namespace { + +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + class ExecutablePackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + bool getFileAttributes(sal_uInt64& out_Attributes); + bool isUrlTargetInExtension(); + + public: + inline ExecutablePackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier) + {} + }; + friend class ExecutablePackageImpl; + + typedef ::boost::unordered_map< OUString, Reference<XInterface>, + ::rtl::OUStringHash > t_string2object; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ); + + void addDataToDb(OUString const & url); + bool hasActiveEntry(OUString const & url); + void revokeEntryFromDb(OUString const & url); + + Reference<deployment::XPackageTypeInfo> m_xExecutableTypeInfo; + std::auto_ptr<ExecutableBackendDb> m_backendDb; +public: + BackendImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) + throw (deployment::DeploymentException, + uno::RuntimeException); + + using PackageRegistryBackend::disposing; +}; + + +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : PackageRegistryBackend( args, xComponentContext ), + m_xExecutableTypeInfo(new Package::TypeInfo( + OUSTR("application/vnd.sun.star.executable"), + OUSTR(""), + OUSTR("Executable"), + RID_IMG_COMPONENT ) ) +{ + if (!transientMode()) + { + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new ExecutableBackendDb(getComponentContext(), dbFile)); + } +} + +void BackendImpl::addDataToDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url); +} + +void BackendImpl::revokeEntryFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->revokeEntry(url); +} + +bool BackendImpl::hasActiveEntry(OUString const & url) +{ + if (m_backendDb.get()) + return m_backendDb->hasActiveEntry(url); + return false; +} + + +// XPackageRegistry +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return Sequence<Reference<deployment::XPackageTypeInfo> >( + & m_xExecutableTypeInfo, 1); +} + +void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/) + throw (deployment::DeploymentException, + uno::RuntimeException) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + +// PackageRegistryBackend +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (mediaType.getLength() == 0) + { + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + OUString name; + if (!bRemoved) + { + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + name = ucbContent.getPropertyValue( + dp_misc::StrTitle::get() ).get<OUString>(); + } + if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.executable")) + { + return new BackendImpl::ExecutablePackageImpl( + this, url, name, m_xExecutableTypeInfo, bRemoved, + identifier); + } + } + } + return Reference<deployment::XPackage>(); +} + + + +// Package +BackendImpl * BackendImpl::ExecutablePackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<ExecutablePackageImpl *>(this))); + } + return pBackend; +} + +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::ExecutablePackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<dp_misc::AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + bool registered = getMyBackend()->hasActiveEntry(getURL()); + return beans::Optional< beans::Ambiguous<sal_Bool> >( + sal_True /* IsPresent */, + beans::Ambiguous<sal_Bool>( + registered, sal_False /* IsAmbiguous */ ) ); +} + +void BackendImpl::ExecutablePackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool /*startup*/, + ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & /*xCmdEnv*/ ) +{ + checkAborted(abortChannel); + if (doRegisterPackage) + { + if (!isUrlTargetInExtension()) + { + OSL_ASSERT(0); + return; + } + sal_uInt64 attributes = 0; + //Setting the executable attribut does not affect executables on Windows + if (getFileAttributes(attributes)) + { + if(getMyBackend()->m_context.equals(OUSTR("user"))) + attributes |= osl_File_Attribute_OwnExe; + else if (getMyBackend()->m_context.equals(OUSTR("shared"))) + attributes |= (osl_File_Attribute_OwnExe | osl_File_Attribute_GrpExe + | osl_File_Attribute_OthExe); + else if (!getMyBackend()->m_context.equals(OUSTR("bundled")) + && !getMyBackend()->m_context.equals(OUSTR("bundled_prereg"))) + //Bundled extension are required to be in the properly + //installed. That is an executable must have the right flags + OSL_ASSERT(0); + + //This won't have affect on Windows + osl::File::setAttributes( + dp_misc::expandUnoRcUrl(m_url), attributes); + } + getMyBackend()->addDataToDb(getURL()); + } + else + { + getMyBackend()->revokeEntryFromDb(getURL()); + } +} + +//We currently cannot check if this XPackage represents a content of a particular extension +//But we can check if we are within $UNO_USER_PACKAGES_CACHE etc. +//Done for security reasons. For example an extension manifest could contain a path to +//an executable outside the extension. +bool BackendImpl::ExecutablePackageImpl::isUrlTargetInExtension() +{ + bool bSuccess = false; + OUString sExtensionDir; + if(getMyBackend()->m_context.equals(OUSTR("user"))) + sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$UNO_USER_PACKAGES_CACHE")); + else if (getMyBackend()->m_context.equals(OUSTR("shared"))) + sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$UNO_SHARED_PACKAGES_CACHE")); + else if (getMyBackend()->m_context.equals(OUSTR("bundled")) + || getMyBackend()->m_context.equals(OUSTR("bundled_prereg"))) + sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$BUNDLED_EXTENSIONS")); + else + OSL_ASSERT(0); + //remove file ellipses + if (osl::File::E_None == osl::File::getAbsoluteFileURL(OUString(), sExtensionDir, sExtensionDir)) + { + OUString sFile; + if (osl::File::E_None == osl::File::getAbsoluteFileURL( + OUString(), dp_misc::expandUnoRcUrl(m_url), sFile)) + { + if (sal_True == sFile.match(sExtensionDir, 0)) + bSuccess = true; + } + } + return bSuccess; +} + +bool BackendImpl::ExecutablePackageImpl::getFileAttributes(sal_uInt64& out_Attributes) +{ + bool bSuccess = false; + const OUString url(dp_misc::expandUnoRcUrl(m_url)); + osl::DirectoryItem item; + if (osl::FileBase::E_None == osl::DirectoryItem::get(url, item)) + { + osl::FileStatus aStatus(osl_FileStatus_Mask_Attributes); + if( osl::FileBase::E_None == item.getFileStatus(aStatus)) + { + out_Attributes = aStatus.getAttributes(); + bSuccess = true; + } + } + return bSuccess; +} + + + +} // anon namespace + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + "com.sun.star.comp.deployment.executable.PackageRegistryBackend", + BACKEND_SERVICE_NAME ); + +} // namespace component +} // namespace backend +} // namespace dp_registry + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/executable/dp_executablebackenddb.cxx b/desktop/source/deployment/registry/executable/dp_executablebackenddb.cxx new file mode 100644 index 000000000000..0c65a9bf4d2c --- /dev/null +++ b/desktop/source/deployment/registry/executable/dp_executablebackenddb.cxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "rtl/string.h" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "dp_misc.h" +#include "dp_executablebackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/executable-registry/2010" +#define NS_PREFIX "exe" +#define ROOT_ELEMENT_NAME "executable-backend-db" +#define ENTRY_NAME "executable" + +namespace dp_registry { +namespace backend { +namespace executable { + +ExecutableBackendDb::ExecutableBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):RegisteredDb(xContext, url) +{ + +} + +OUString ExecutableBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ExecutableBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString ExecutableBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString ExecutableBackendDb::getKeyElementName() +{ + return OUSTR(ENTRY_NAME); +} + + +} // namespace executable +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/executable/dp_executablebackenddb.hxx b/desktop/source/deployment/registry/executable/dp_executablebackenddb.hxx new file mode 100644 index 000000000000..1a5828015260 --- /dev/null +++ b/desktop/source/deployment/registry/executable/dp_executablebackenddb.hxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_EXECUTABLEBACKENDDB_HXX +#define INCLUDED_DP_EXECUTABLEBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } +}}} + +namespace dp_registry { +namespace backend { +namespace executable { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + The format looks like this: + +<?xml version="1.0"?> + */ +class ExecutableBackendDb: public dp_registry::backend::RegisteredDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + + virtual ::rtl::OUString getNSPrefix(); + + virtual ::rtl::OUString getRootElementName(); + + virtual ::rtl::OUString getKeyElementName(); + +public: + + ExecutableBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/executable/makefile.mk b/desktop/source/deployment/registry/executable/makefile.mk new file mode 100755 index 000000000000..81b2baa44e5d --- /dev/null +++ b/desktop/source/deployment/registry/executable/makefile.mk @@ -0,0 +1,44 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_registry_executable +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +INCPRE += ..$/..$/inc + +SLOFILES = \ + $(SLO)$/dp_executable.obj \ + $(SLO)$/dp_executablebackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/help/dp_help.cxx b/desktop/source/deployment/registry/help/dp_help.cxx new file mode 100644 index 000000000000..02bffa948e03 --- /dev/null +++ b/desktop/source/deployment/registry/help/dp_help.cxx @@ -0,0 +1,676 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_help.hrc" +#include "dp_backend.h" +#include "dp_helpbackenddb.hxx" +#include "dp_ucb.h" +#include "rtl/uri.hxx" +#include "osl/file.hxx" +#include "rtl/bootstrap.hxx" +#include "ucbhelper/content.hxx" +#include "comphelper/servicedecl.hxx" +#include "svl/inettype.hxx" +#include "unotools/pathoptions.hxx" + +#include <l10ntools/compilehelp.hxx> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/util/XMacroExpander.hpp> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> +#include <com/sun/star/uri/XVndSunStarExpandUrl.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include "boost/optional.hpp" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace help { +namespace { + +//============================================================================== +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + class PackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + + public: + PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, OUString const & identifier); + + bool extensionContainsCompiledHelp(); + + //XPackage + virtual css::beans::Optional< ::rtl::OUString > SAL_CALL getRegistrationDataURL() + throw (deployment::ExtensionRemovedException, css::uno::RuntimeException); + }; + friend class PackageImpl; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ); + + void implProcessHelp( PackageImpl * package, bool doRegisterPackage, + Reference<ucb::XCommandEnvironment> const & xCmdEnv); + void implCollectXhpFiles( const rtl::OUString& aDir, + std::vector< rtl::OUString >& o_rXhpFileVector ); + + void addDataToDb(OUString const & url, HelpBackendDb::Data const & data); + ::boost::optional<HelpBackendDb::Data> readDataFromDb(OUString const & url); + bool hasActiveEntry(OUString const & url); + void revokeEntryFromDb(OUString const & url); + bool activateEntry(OUString const & url); + + Reference< ucb::XSimpleFileAccess > getFileAccess( void ); + Reference< ucb::XSimpleFileAccess > m_xSFA; + + const Reference<deployment::XPackageTypeInfo> m_xHelpTypeInfo; + Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + std::auto_ptr<HelpBackendDb> m_backendDb; + +public: + BackendImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) + throw (deployment::DeploymentException, + uno::RuntimeException); + +}; + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : PackageRegistryBackend( args, xComponentContext ), + m_xHelpTypeInfo( new Package::TypeInfo( + OUSTR("application/vnd.sun.star.help"), + rtl::OUString(), + getResourceString(RID_STR_HELP), + RID_IMG_HELP ) ), + m_typeInfos( 1 ) +{ + m_typeInfos[ 0 ] = m_xHelpTypeInfo; + if (!transientMode()) + { + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new HelpBackendDb(getComponentContext(), dbFile)); + + //clean up data folders which are no longer used. + //This must not be done in the same process where the help files + //are still registers. Only after revoking and restarting OOo the folders + //can be removed. This works now, because the extension manager is a singleton + //and the backends are only create once per process. + ::std::list<OUString> folders = m_backendDb->getAllDataUrls(); + deleteUnusedFolders(OUString(), folders); + } +} + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return m_typeInfos; +} + +void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/) + throw (deployment::DeploymentException, + uno::RuntimeException) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + // we don't support auto detection: + if (mediaType_.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType_, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + OUString name; + if (!bRemoved) + { + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + name = ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>(); + } + + if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.help")) + { + return new PackageImpl( + this, url, name, m_xHelpTypeInfo, bRemoved, + identifier); + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType_, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + +void BackendImpl::addDataToDb( + OUString const & url, HelpBackendDb::Data const & data) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url, data); +} + +::boost::optional<HelpBackendDb::Data> BackendImpl::readDataFromDb( + OUString const & url) +{ + ::boost::optional<HelpBackendDb::Data> data; + if (m_backendDb.get()) + data = m_backendDb->getEntry(url); + return data; +} + +bool BackendImpl::hasActiveEntry(OUString const & url) +{ + if (m_backendDb.get()) + return m_backendDb->hasActiveEntry(url); + return false; +} + +void BackendImpl::revokeEntryFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->revokeEntry(url); +} + +bool BackendImpl::activateEntry(OUString const & url) +{ + if (m_backendDb.get()) + return m_backendDb->activateEntry(url); + return false; +} + + +BackendImpl::PackageImpl::PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name, xPackageType, bRemoved, + identifier) +{ +} + +// Package +BackendImpl * BackendImpl::PackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); + } + return pBackend; +} + +bool BackendImpl::PackageImpl::extensionContainsCompiledHelp() +{ + bool bCompiled = true; + rtl::OUString aExpandedHelpURL = dp_misc::expandUnoRcUrl(getURL()); + + ::osl::Directory helpFolder(aExpandedHelpURL); + if ( helpFolder.open() == ::osl::File::E_None) + { + //iterate over the contents of the help folder + //We assume that all folders withing the help folder contain language specific + //help files. If just one of them does not contain compiled help then this + //function returns false. + ::osl::DirectoryItem item; + ::osl::File::RC errorNext = ::osl::File::E_None; + while ((errorNext = helpFolder.getNextItem(item)) == ::osl::File::E_None) + { + //No find the language folders + ::osl::FileStatus stat(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName |osl_FileStatus_Mask_FileURL); + if (item.getFileStatus(stat) == ::osl::File::E_None) + { + if (stat.getFileType() != ::osl::FileStatus::Directory) + continue; + + //look if there is the folder help.idxl in the language folder + OUString compUrl(stat.getFileURL() + OUSTR("/help.idxl")); + ::osl::Directory compiledFolder(compUrl); + if (compiledFolder.open() != ::osl::File::E_None) + { + bCompiled = false; + break; + } + } + else + { + //Error + OSL_ASSERT(0); + bCompiled = false; + break; + } + } + if (errorNext != ::osl::File::E_NOENT + && errorNext != ::osl::File::E_None) + { + //Error + OSL_ASSERT(0); + bCompiled = false; + } + } + return bCompiled; +} + +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::PackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + BackendImpl * that = getMyBackend(); + + bool bReg = false; + if (that->hasActiveEntry(getURL())) + bReg = true; + + return beans::Optional< beans::Ambiguous<sal_Bool> >( true, beans::Ambiguous<sal_Bool>( bReg, false ) ); +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool /* startup */, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + (void)doRegisterPackage; + (void)abortChannel; + (void)xCmdEnv; + + BackendImpl* that = getMyBackend(); + that->implProcessHelp( this, doRegisterPackage, xCmdEnv); +} + +beans::Optional< OUString > BackendImpl::PackageImpl::getRegistrationDataURL() + throw (deployment::ExtensionRemovedException, + css::uno::RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + ::boost::optional<HelpBackendDb::Data> data = + getMyBackend()->readDataFromDb(getURL()); + + if (data && getMyBackend()->hasActiveEntry(getURL())) + return beans::Optional<OUString>(true, data->dataUrl); + + return beans::Optional<OUString>(true, OUString()); +} + +static rtl::OUString aSlash(RTL_CONSTASCII_USTRINGPARAM("/")); +static rtl::OUString aHelpStr(RTL_CONSTASCII_USTRINGPARAM("help")); + +void BackendImpl::implProcessHelp( + PackageImpl * package, bool doRegisterPackage, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + Reference< deployment::XPackage > xPackage(package); + OSL_ASSERT(xPackage.is()); + if (doRegisterPackage) + { + //revive already processed help if possible + if ( !activateEntry(xPackage->getURL())) + { + HelpBackendDb::Data data; + data.dataUrl = xPackage->getURL(); + if (!package->extensionContainsCompiledHelp()) + { + const OUString sHelpFolder = createFolder(OUString(), xCmdEnv); + data.dataUrl = sHelpFolder; + + Reference< ucb::XSimpleFileAccess > xSFA = getFileAccess(); + rtl::OUString aHelpURL = xPackage->getURL(); + rtl::OUString aExpandedHelpURL = dp_misc::expandUnoRcUrl( aHelpURL ); + rtl::OUString aName = xPackage->getName(); + if( !xSFA->isFolder( aExpandedHelpURL ) ) + { + rtl::OUString aErrStr = getResourceString( RID_STR_HELPPROCESSING_GENERAL_ERROR ); + aErrStr += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "No help folder" )); + OWeakObject* oWeakThis = static_cast<OWeakObject *>(this); + throw deployment::DeploymentException( rtl::OUString(), oWeakThis, + makeAny( uno::Exception( aErrStr, oWeakThis ) ) ); + } + + Reference<XComponentContext> const & xContext = getComponentContext(); + Reference< script::XInvocation > xInvocation; + if( xContext.is() ) + { + try + { + xInvocation = Reference< script::XInvocation >( + xContext->getServiceManager()->createInstanceWithContext( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.help.HelpIndexer" )), xContext ) , UNO_QUERY ); + } + catch (Exception &) + { + // i98680: Survive missing lucene + } + } + + // Scan languages + Sequence< rtl::OUString > aLanguageFolderSeq = xSFA->getFolderContents( aExpandedHelpURL, true ); + sal_Int32 nLangCount = aLanguageFolderSeq.getLength(); + const rtl::OUString* pSeq = aLanguageFolderSeq.getConstArray(); + for( sal_Int32 iLang = 0 ; iLang < nLangCount ; ++iLang ) + { + rtl::OUString aLangURL = pSeq[iLang]; + if( xSFA->isFolder( aLangURL ) ) + { + std::vector< rtl::OUString > aXhpFileVector; + + // calculate jar file URL + sal_Int32 indexStartSegment = aLangURL.lastIndexOf('/'); + // for example "/en" + OUString langFolderURLSegment( + aLangURL.copy( + indexStartSegment + 1, aLangURL.getLength() - indexStartSegment - 1)); + + //create the folder in the "temporary folder" + ::ucbhelper::Content langFolderContent; + const OUString langFolderDest = makeURL(sHelpFolder, langFolderURLSegment); + const OUString langFolderDestExpanded = ::dp_misc::expandUnoRcUrl(langFolderDest); + ::dp_misc::create_folder( + &langFolderContent, + langFolderDest, xCmdEnv); + + rtl::OUString aJarFile( + makeURL(sHelpFolder, langFolderURLSegment + aSlash + aHelpStr + + OUSTR(".jar"))); + aJarFile = ::dp_misc::expandUnoRcUrl(aJarFile); + + rtl::OUString aEncodedJarFilePath = rtl::Uri::encode( + aJarFile, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + rtl::OUString aDestBasePath = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.zip://" )); + aDestBasePath += aEncodedJarFilePath; + aDestBasePath += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "/" )); + + sal_Int32 nLenLangFolderURL = aLangURL.getLength() + 1; + + Sequence< rtl::OUString > aSubLangSeq = xSFA->getFolderContents( aLangURL, true ); + sal_Int32 nSubLangCount = aSubLangSeq.getLength(); + const rtl::OUString* pSubLangSeq = aSubLangSeq.getConstArray(); + for( sal_Int32 iSubLang = 0 ; iSubLang < nSubLangCount ; ++iSubLang ) + { + rtl::OUString aSubFolderURL = pSubLangSeq[iSubLang]; + if( !xSFA->isFolder( aSubFolderURL ) ) + continue; + + implCollectXhpFiles( aSubFolderURL, aXhpFileVector ); + + // Copy to package (later: move?) + rtl::OUString aDestPath = aDestBasePath; + rtl::OUString aPureFolderName = aSubFolderURL.copy( nLenLangFolderURL ); + aDestPath += aPureFolderName; + xSFA->copy( aSubFolderURL, aDestPath ); + } + + // Call compiler + sal_Int32 nXhpFileCount = aXhpFileVector.size(); + rtl::OUString* pXhpFiles = new rtl::OUString[nXhpFileCount]; + for( sal_Int32 iXhp = 0 ; iXhp < nXhpFileCount ; ++iXhp ) + { + rtl::OUString aXhpFile = aXhpFileVector[iXhp]; + rtl::OUString aXhpRelFile = aXhpFile.copy( nLenLangFolderURL ); + pXhpFiles[iXhp] = aXhpRelFile; + } + + rtl::OUString aOfficeHelpPath( SvtPathOptions().GetHelpPath() ); + rtl::OUString aOfficeHelpPathFileURL; + ::osl::File::getFileURLFromSystemPath( aOfficeHelpPath, aOfficeHelpPathFileURL ); + + HelpProcessingErrorInfo aErrorInfo; + bool bSuccess = compileExtensionHelp( + aOfficeHelpPathFileURL, aHelpStr, aLangURL, + nXhpFileCount, pXhpFiles, + langFolderDestExpanded, aErrorInfo ); + + if( bSuccess && xInvocation.is() ) + { + Sequence<uno::Any> aParamsSeq( 6 ); + + aParamsSeq[0] = uno::makeAny( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "-lang" ) )); + + rtl::OUString aLang; + sal_Int32 nLastSlash = aLangURL.lastIndexOf( '/' ); + if( nLastSlash != -1 ) + aLang = aLangURL.copy( nLastSlash + 1 ); + else + aLang = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "en" )); + aParamsSeq[1] = uno::makeAny( aLang ); + + aParamsSeq[2] = uno::makeAny( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "-mod" ) )); + aParamsSeq[3] = uno::makeAny( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "help" ) )); + + aParamsSeq[4] = uno::makeAny( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "-zipdir" ) )); + rtl::OUString aSystemPath; + osl::FileBase::getSystemPathFromFileURL( + langFolderDestExpanded, aSystemPath ); + aParamsSeq[5] = uno::makeAny( aSystemPath ); + + Sequence< sal_Int16 > aOutParamIndex; + Sequence< uno::Any > aOutParam; + uno::Any aRet = xInvocation->invoke( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "createIndex" )), + aParamsSeq, aOutParamIndex, aOutParam ); + } + + if( !bSuccess ) + { + sal_uInt16 nErrStrId = 0; + switch( aErrorInfo.m_eErrorClass ) + { + case HELPPROCESSING_GENERAL_ERROR: + case HELPPROCESSING_INTERNAL_ERROR: nErrStrId = RID_STR_HELPPROCESSING_GENERAL_ERROR; break; + case HELPPROCESSING_XMLPARSING_ERROR: nErrStrId = RID_STR_HELPPROCESSING_XMLPARSING_ERROR; break; + default: ; + }; + + rtl::OUString aErrStr; + if( nErrStrId != 0 ) + { + aErrStr = getResourceString( nErrStrId ); + + // Remoce CR/LF + rtl::OUString aErrMsg( aErrorInfo.m_aErrorMsg ); + sal_Unicode nCR = 13, nLF = 10; + sal_Int32 nSearchCR = aErrMsg.indexOf( nCR ); + sal_Int32 nSearchLF = aErrMsg.indexOf( nLF ); + sal_Int32 nCopy; + if( nSearchCR != -1 || nSearchLF != -1 ) + { + if( nSearchCR == -1 ) + nCopy = nSearchLF; + else if( nSearchLF == -1 ) + nCopy = nSearchCR; + else + nCopy = ( nSearchCR < nSearchLF ) ? nSearchCR : nSearchLF; + + aErrMsg = aErrMsg.copy( 0, nCopy ); + } + aErrStr += aErrMsg; + if( nErrStrId == RID_STR_HELPPROCESSING_XMLPARSING_ERROR && aErrorInfo.m_aXMLParsingFile.getLength() ) + { + aErrStr += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( " in " )); + + rtl::OUString aDecodedFile = rtl::Uri::decode( aErrorInfo.m_aXMLParsingFile, + rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + aErrStr += aDecodedFile; + if( aErrorInfo.m_nXMLParsingLine != -1 ) + { + aErrStr += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ", line " )); + aErrStr += ::rtl::OUString::valueOf( aErrorInfo.m_nXMLParsingLine ); + } + } + } + + OWeakObject* oWeakThis = static_cast<OWeakObject *>(this); + throw deployment::DeploymentException( rtl::OUString(), oWeakThis, + makeAny( uno::Exception( aErrStr, oWeakThis ) ) ); + } + } + } + } + //Writing the data entry replaces writing the flag file. If we got to this + //point the registration was successful. + addDataToDb(xPackage->getURL(), data); + } + } //if (doRegisterPackage) + else + { + revokeEntryFromDb(xPackage->getURL()); + } +} + +void BackendImpl::implCollectXhpFiles( const rtl::OUString& aDir, + std::vector< rtl::OUString >& o_rXhpFileVector ) +{ + Reference< ucb::XSimpleFileAccess > xSFA = getFileAccess(); + + // Scan xhp files recursively + Sequence< rtl::OUString > aSeq = xSFA->getFolderContents( aDir, true ); + sal_Int32 nCount = aSeq.getLength(); + const rtl::OUString* pSeq = aSeq.getConstArray(); + for( sal_Int32 i = 0 ; i < nCount ; ++i ) + { + rtl::OUString aURL = pSeq[i]; + if( xSFA->isFolder( aURL ) ) + { + implCollectXhpFiles( aURL, o_rXhpFileVector ); + } + else + { + sal_Int32 nLastDot = aURL.lastIndexOf( '.' ); + if( nLastDot != -1 ) + { + rtl::OUString aExt = aURL.copy( nLastDot + 1 ); + if( aExt.equalsIgnoreAsciiCase( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "xhp" )) ) ) + o_rXhpFileVector.push_back( aURL ); + } + } + } +} + +Reference< ucb::XSimpleFileAccess > BackendImpl::getFileAccess( void ) +{ + if( !m_xSFA.is() ) + { + Reference<XComponentContext> const & xContext = getComponentContext(); + if( xContext.is() ) + { + m_xSFA = Reference< ucb::XSimpleFileAccess >( + xContext->getServiceManager()->createInstanceWithContext( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.SimpleFileAccess" )), + xContext ), UNO_QUERY ); + } + if( !m_xSFA.is() ) + { + throw RuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "dp_registry::backend::help::BackendImpl::getFileAccess(), " + "could not instatiate SimpleFileAccess." )), + Reference< XInterface >() ); + } + } + return m_xSFA; +} + +} // anon namespace + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + "com.sun.star.comp.deployment.help.PackageRegistryBackend", + BACKEND_SERVICE_NAME ); + +} // namespace help +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/help/dp_help.hrc b/desktop/source/deployment/registry/help/dp_help.hrc new file mode 100755 index 000000000000..c1e10547ccdd --- /dev/null +++ b/desktop/source/deployment/registry/help/dp_help.hrc @@ -0,0 +1,39 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_HELP_HRC +#define INCLUDED_DP_HELP_HRC + +#include "deployment.hrc" + +#define RID_STR_HELP (RID_DEPLOYMENT_HELP_START+2) + +#define RID_STR_HELPPROCESSING_GENERAL_ERROR (RID_DEPLOYMENT_HELP_START+3) +#define RID_STR_HELPPROCESSING_XMLPARSING_ERROR (RID_DEPLOYMENT_HELP_START+4) + + +#endif diff --git a/desktop/source/deployment/registry/help/dp_help.src b/desktop/source/deployment/registry/help/dp_help.src new file mode 100644 index 000000000000..6b6a3f9a6508 --- /dev/null +++ b/desktop/source/deployment/registry/help/dp_help.src @@ -0,0 +1,44 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_help.hrc" + +String RID_STR_HELP +{ + Text [ en-US ] = "Help"; +}; + +String RID_STR_HELPPROCESSING_GENERAL_ERROR +{ + Text [ en-US ] = "The extension cannot be installed because:\n"; +}; + +String RID_STR_HELPPROCESSING_XMLPARSING_ERROR +{ + Text [ en-US ] = "The extension will not be installed because an error occurred in the Help files:\n"; +}; + diff --git a/desktop/source/deployment/registry/help/dp_helpbackenddb.cxx b/desktop/source/deployment/registry/help/dp_helpbackenddb.cxx new file mode 100644 index 000000000000..491f6d6c1db9 --- /dev/null +++ b/desktop/source/deployment/registry/help/dp_helpbackenddb.cxx @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "rtl/string.h" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" + +#include "dp_helpbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/help-registry/2010" +#define NS_PREFIX "help" +#define ROOT_ELEMENT_NAME "help-backend-db" +#define KEY_ELEMENT_NAME "help" + +namespace dp_registry { +namespace backend { +namespace help { + +HelpBackendDb::HelpBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +OUString HelpBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString HelpBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString HelpBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString HelpBackendDb::getKeyElementName() +{ + return OUSTR(KEY_ELEMENT_NAME); +} + + +void HelpBackendDb::addEntry(::rtl::OUString const & url, Data const & data) +{ + try{ + if (!activateEntry(url)) + { + Reference<css::xml::dom::XNode> helpNode + = writeKeyElement(url); + + writeSimpleElement(OUSTR("data-url"), data.dataUrl, helpNode); + save(); + } + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in help backend db: ") + + m_urlDb, 0, exc); + } +} + + +::boost::optional<HelpBackendDb::Data> +HelpBackendDb::getEntry(::rtl::OUString const & url) +{ + try + { + HelpBackendDb::Data retData; + Reference<css::xml::dom::XNode> aNode = getKeyElement(url); + if (aNode.is()) + { + retData.dataUrl = readSimpleElement(OUSTR("data-url"), aNode); + } + else + { + return ::boost::optional<Data>(); + } + return ::boost::optional<Data>(retData); + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in help backend db: ") + + m_urlDb, 0, exc); + } +} + +::std::list<OUString> HelpBackendDb::getAllDataUrls() +{ + return getOneChildFromAllEntries(OUString(RTL_CONSTASCII_USTRINGPARAM("data-url"))); +} + +} // namespace help +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/help/dp_helpbackenddb.hxx b/desktop/source/deployment/registry/help/dp_helpbackenddb.hxx new file mode 100644 index 000000000000..34e732d4118d --- /dev/null +++ b/desktop/source/deployment/registry/help/dp_helpbackenddb.hxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_HELPBACKENDDB_HXX +#define INCLUDED_DP_HELPBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include <list> +#include "boost/optional.hpp" +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } +}}} + +namespace dp_registry { +namespace backend { +namespace help { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + */ +class HelpBackendDb: public dp_registry::backend::BackendDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + + virtual ::rtl::OUString getNSPrefix(); + + virtual ::rtl::OUString getRootElementName(); + + virtual ::rtl::OUString getKeyElementName(); + +public: + struct Data + { + /* the URL to the folder containing the compiled help files, etc. + */ + ::rtl::OUString dataUrl; + + }; + +public: + + HelpBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + + void addEntry(::rtl::OUString const & url, Data const & data); + + ::boost::optional<Data> getEntry(::rtl::OUString const & url); + //must also return the data urls for entries with @activ="false". That is, + //those are currently revoked. + ::std::list< ::rtl::OUString> getAllDataUrls(); + +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/help/makefile.mk b/desktop/source/deployment/registry/help/makefile.mk new file mode 100755 index 000000000000..81778bf728c0 --- /dev/null +++ b/desktop/source/deployment/registry/help/makefile.mk @@ -0,0 +1,50 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_registry_help +ENABLE_EXCEPTIONS = TRUE + +INCPRE += ..$/..$/inc + +.INCLUDE : settings.mk + +CFLAGS+= $(SYSTEM_DB_CFLAGS) + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_help.src + +SLOFILES = \ + $(SLO)$/dp_help.obj \ + $(SLO)$/dp_helpbackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/inc/dp_backend.h b/desktop/source/deployment/registry/inc/dp_backend.h new file mode 100755 index 000000000000..847eb43d5cb2 --- /dev/null +++ b/desktop/source/deployment/registry/inc/dp_backend.h @@ -0,0 +1,401 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_REGISTRY_H +#define INCLUDED_DP_REGISTRY_H + +#include "dp_misc.h" +#include "dp_resource.h" +#include "dp_interact.h" +#include "rtl/ref.hxx" +#include "cppuhelper/weakref.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/compbase1.hxx" +#include "cppuhelper/compbase2.hxx" +#include "tools/inetmime.hxx" +#include "com/sun/star/lang/XEventListener.hpp" +#include "com/sun/star/deployment/XPackageRegistry.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include "com/sun/star/deployment/InvalidRemovedParameterException.hpp" +#include <memory> +#include <boost/unordered_map.hpp> +#include <list> +#include "dp_registry.hrc" + +namespace dp_registry +{ +namespace backend +{ + +namespace css = ::com::sun::star; + +class PackageRegistryBackend; + +#define BACKEND_SERVICE_NAME "com.sun.star.deployment.PackageRegistryBackend" + +typedef ::cppu::WeakComponentImplHelper1< + css::deployment::XPackage > t_PackageBase; + +//============================================================================== +class Package : protected ::dp_misc::MutexHolder, public t_PackageBase +{ + PackageRegistryBackend * getMyBackend() const; + void processPackage_impl( + bool registerPackage, + bool startup, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ); + +protected: + ::rtl::Reference<PackageRegistryBackend> m_myBackend; + const ::rtl::OUString m_url; + ::rtl::OUString m_name; + ::rtl::OUString m_displayName; + const css::uno::Reference<css::deployment::XPackageTypeInfo> m_xPackageType; + const bool m_bRemoved; + //Only set if m_bRemoved = true; + const ::rtl::OUString m_identifier; + + void check() const; + void fireModified(); + virtual void SAL_CALL disposing(); + + void checkAborted( + ::rtl::Reference< ::dp_misc::AbortChannel > const & abortChannel ); + + // @@@ to be implemented by specific backend: + virtual css::beans::Optional< css::beans::Ambiguous<sal_Bool> > + isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference< ::dp_misc::AbortChannel > const & abortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + = 0; + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference< ::dp_misc::AbortChannel > const & abortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + = 0; + + virtual ~Package(); + Package( ::rtl::Reference<PackageRegistryBackend> const & myBackend, + ::rtl::OUString const & url, + ::rtl::OUString const & name, + ::rtl::OUString const & displayName, + css::uno::Reference<css::deployment::XPackageTypeInfo> const & + xPackageType, + bool bRemoved, + ::rtl::OUString const & identifier); + +public: + + class TypeInfo : + public ::cppu::WeakImplHelper1<css::deployment::XPackageTypeInfo> + { + const ::rtl::OUString m_mediaType; + const ::rtl::OUString m_fileFilter; + const ::rtl::OUString m_shortDescr; + const sal_uInt16 m_smallIcon; + public: + virtual ~TypeInfo(); + TypeInfo( ::rtl::OUString const & mediaType, + ::rtl::OUString const & fileFilter, + ::rtl::OUString const & shortDescr, + sal_uInt16 smallIcon) + : m_mediaType(mediaType), m_fileFilter(fileFilter), + m_shortDescr(shortDescr), + m_smallIcon(smallIcon) + {} + // XPackageTypeInfo + virtual ::rtl::OUString SAL_CALL getMediaType() + throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getDescription() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getShortDescription() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getFileFilter() + throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL getIcon( sal_Bool highContrast, + sal_Bool smallIcon ) + throw (css::uno::RuntimeException); + }; + + // XComponent + virtual void SAL_CALL dispose() throw (css::uno::RuntimeException); + virtual void SAL_CALL addEventListener( + css::uno::Reference<css::lang::XEventListener> const & xListener ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( + css::uno::Reference<css::lang::XEventListener> const & xListener ) + throw (css::uno::RuntimeException); + + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + + // XPackage + virtual css::uno::Reference<css::task::XAbortChannel> SAL_CALL + createAbortChannel() throw (css::uno::RuntimeException); + virtual css::beans::Optional< css::beans::Ambiguous<sal_Bool> > + SAL_CALL isRegistered( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException); + + virtual ::sal_Int32 SAL_CALL checkPrerequisites( + const css::uno::Reference< css::task::XAbortChannel >& xAbortChannel, + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv, + sal_Bool noLicenseChecking) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException); + + virtual ::sal_Bool SAL_CALL checkDependencies( + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv ) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::uno::RuntimeException); + + virtual void SAL_CALL registerPackage( + sal_Bool startup, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, css::uno::RuntimeException); + virtual void SAL_CALL revokePackage( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBundle() + throw (css::uno::RuntimeException); + virtual css::uno::Sequence< css::uno::Reference<css::deployment::XPackage> > + SAL_CALL getBundle( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getName() + throw (css::uno::RuntimeException); + virtual css::beans::Optional< ::rtl::OUString > SAL_CALL getIdentifier() + throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getVersion() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getURL() + throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getDisplayName() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getDescription() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getLicenseText() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL + getUpdateInformationURLs() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual css::beans::StringPair SAL_CALL getPublisherInfo() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual css::uno::Reference< css::graphic::XGraphic > SAL_CALL + getIcon( sal_Bool bHighContrast ) + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual css::uno::Reference<css::deployment::XPackageTypeInfo> SAL_CALL + getPackageType() throw (css::uno::RuntimeException); + virtual void SAL_CALL exportTo( + ::rtl::OUString const & destFolderURL, + ::rtl::OUString const & newTitle, + sal_Int32 nameClashAction, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getRepositoryName() + throw (css::uno::RuntimeException); + virtual css::beans::Optional< ::rtl::OUString > SAL_CALL getRegistrationDataURL() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual sal_Bool SAL_CALL isRemoved() + throw (css::uno::RuntimeException); + +}; + +typedef ::cppu::WeakComponentImplHelper2< + css::lang::XEventListener, + css::deployment::XPackageRegistry > t_BackendBase; + +//============================================================================== +class PackageRegistryBackend + : protected ::dp_misc::MutexHolder, public t_BackendBase +{ + //The map held originally WeakReferences. The map entries are removed in the disposing + //function, which is called when the XPackages are destructed or they are + //explicitely disposed. The latter happens, for example, when a extension is + //removed (see dp_manager.cxx). However, because of how the help systems work, now + // XPackageManager::getDeployedPackages is called often. This results in a lot + //of bindPackage calls which are costly. Therefore we keep hard references in + //the map now. + typedef ::boost::unordered_map< + ::rtl::OUString, css::uno::Reference<css::deployment::XPackage>, + ::rtl::OUStringHash > t_string2ref; + t_string2ref m_bound; + +protected: + ::rtl::OUString m_cachePath; + css::uno::Reference<css::uno::XComponentContext> m_xComponentContext; + + ::rtl::OUString m_context; + // currently only for library containers: + enum { + CONTEXT_UNKNOWN, + CONTEXT_USER, CONTEXT_SHARED,CONTEXT_BUNDLED, CONTEXT_TMP, CONTEXT_BUNDLED_PREREG, + CONTEXT_DOCUMENT + } m_eContext; + bool m_readOnly; + + struct StrCannotDetectMediaType : public ::dp_misc::StaticResourceString< + StrCannotDetectMediaType, RID_STR_CANNOT_DETECT_MEDIA_TYPE> {}; + struct StrUnsupportedMediaType : public ::dp_misc::StaticResourceString< + StrUnsupportedMediaType, RID_STR_UNSUPPORTED_MEDIA_TYPE> {}; + + // @@@ to be implemented by specific backend: + virtual css::uno::Reference<css::deployment::XPackage> bindPackage_( + ::rtl::OUString const & url, ::rtl::OUString const & mediaType, + sal_Bool bRemoved, ::rtl::OUString const & identifier, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + = 0; + + void check(); + virtual void SAL_CALL disposing(); + + virtual ~PackageRegistryBackend(); + PackageRegistryBackend( + css::uno::Sequence<css::uno::Any> const & args, + css::uno::Reference<css::uno::XComponentContext> const & xContext ); + + /* creates a folder with a unique name. + If url is empty then it is created in the the backend folder, otherwise + at a location relative to that folder specified by url. + */ + ::rtl::OUString createFolder( + ::rtl::OUString const & relUrl, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + /* deletes folders and files. + + All folder all files which end with ".tmp" or ".tmp_" and which are + not used are deleted. + */ + void deleteUnusedFolders( + ::rtl::OUString const & relUrl, + ::std::list< ::rtl::OUString> const & usedFolders); + /* deletes one folder with a "temporary" name and the corresponding + tmp file, which was used to derive the folder name. + */ + static void deleteTempFolder( + ::rtl::OUString const & folderUrl); + + ::rtl::OUString getSharedRegistrationDataURL( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::deployment::XPackage> const & item); + + /* The backends must implement this function, which is called + from XPackageRegistry::packageRemoved (also implemented here). + This ensure that the backends clean up their registration data + when an extension was removed. + */ +// virtual void deleteDbEntry( ::rtl::OUString const & url) = 0; + + + +public: + struct StrRegisteringPackage : public ::dp_misc::StaticResourceString< + StrRegisteringPackage, RID_STR_REGISTERING_PACKAGE> {}; + struct StrRevokingPackage : public ::dp_misc::StaticResourceString< + StrRevokingPackage, RID_STR_REVOKING_PACKAGE> {}; + + inline css::uno::Reference<css::uno::XComponentContext> const & + getComponentContext() const { return m_xComponentContext; } + + inline ::rtl::OUString const & getCachePath() const { return m_cachePath; } + inline bool transientMode() const { return m_cachePath.getLength() == 0; } + + inline ::rtl::OUString getContext() const {return m_context; } + + // XEventListener + virtual void SAL_CALL disposing( css::lang::EventObject const & evt ) + throw (css::uno::RuntimeException); + + // XPackageRegistry + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL bindPackage( + ::rtl::OUString const & url, ::rtl::OUString const & mediaType, + sal_Bool bRemoved, ::rtl::OUString const & identifier, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::deployment::InvalidRemovedParameterException, + css::ucb::CommandFailedException, + css::lang::IllegalArgumentException, css::uno::RuntimeException); + +// virtual void SAL_CALL packageRemoved( +// ::rtl::OUString const & url, ::rtl::OUString const & mediaType) +// throw (css::deployment::DeploymentException, +// css::uno::RuntimeException); + +}; + +} +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/inc/dp_backenddb.hxx b/desktop/source/deployment/registry/inc/dp_backenddb.hxx new file mode 100644 index 000000000000..063da7bae1c4 --- /dev/null +++ b/desktop/source/deployment/registry/inc/dp_backenddb.hxx @@ -0,0 +1,181 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_BACKENDDB_HXX +#define INCLUDED_DP_BACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include <list> +#include <vector> + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace xml { namespace dom { + class XDocument; + class XNode; + }} + namespace xml { namespace xpath { + class XXPathAPI; + }} +}}} + +namespace dp_registry { +namespace backend { + +class BackendDb +{ +private: + + css::uno::Reference<css::xml::dom::XDocument> m_doc; + css::uno::Reference<css::xml::xpath::XXPathAPI> m_xpathApi; + + BackendDb(BackendDb const &); + BackendDb & operator = (BackendDb const &); + +protected: + const css::uno::Reference<css::uno::XComponentContext> m_xContext; + ::rtl::OUString m_urlDb; + +protected: + + /* caller must make sure that only one thread accesses the function + */ + css::uno::Reference<css::xml::dom::XDocument> getDocument(); + + /* the namespace prefix is "reg" (without quotes) + */ + css::uno::Reference<css::xml::xpath::XXPathAPI> getXPathAPI(); + void save(); + void removeElement(::rtl::OUString const & sXPathExpression); + + css::uno::Reference<css::xml::dom::XNode> getKeyElement( + ::rtl::OUString const & url); + + void writeSimpleList( + ::std::list< ::rtl::OUString> const & list, + ::rtl::OUString const & sListTagName, + ::rtl::OUString const & sMemberTagName, + css::uno::Reference<css::xml::dom::XNode> const & xParent); + + void writeVectorOfPair( + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString > > const & vecPairs, + ::rtl::OUString const & sVectorTagName, + ::rtl::OUString const & sPairTagName, + ::rtl::OUString const & sFirstTagName, + ::rtl::OUString const & sSecondTagName, + css::uno::Reference<css::xml::dom::XNode> const & xParent); + + void writeSimpleElement( + ::rtl::OUString const & sElementName, ::rtl::OUString const & value, + css::uno::Reference<css::xml::dom::XNode> const & xParent); + + css::uno::Reference<css::xml::dom::XNode> writeKeyElement( + ::rtl::OUString const & url); + + ::rtl::OUString readSimpleElement( + ::rtl::OUString const & sElementName, + css::uno::Reference<css::xml::dom::XNode> const & xParent); + + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString > > + readVectorOfPair( + css::uno::Reference<css::xml::dom::XNode> const & parent, + ::rtl::OUString const & sListTagName, + ::rtl::OUString const & sPairTagName, + ::rtl::OUString const & sFirstTagName, + ::rtl::OUString const & sSecondTagName); + + ::std::list< ::rtl::OUString> readList( + css::uno::Reference<css::xml::dom::XNode> const & parent, + ::rtl::OUString const & sListTagName, + ::rtl::OUString const & sMemberTagName); + + /* returns the values of one particulary child element of all key elements. + */ + ::std::list< ::rtl::OUString> getOneChildFromAllEntries( + ::rtl::OUString const & sElementName); + + + /* returns the namespace which is to be written as xmlns attribute + into the root element. + */ + virtual ::rtl::OUString getDbNSName()=0; + /* return the namespace prefix which is to be registered with the XPath API. + + The prefix can then be used in XPath expressions. + */ + virtual ::rtl::OUString getNSPrefix()=0; + /* returns the name of the root element without any namespace prefix. + */ + virtual ::rtl::OUString getRootElementName()=0; + /* returns the name of xml element for each entry + */ + virtual ::rtl::OUString getKeyElementName()=0; + +public: + BackendDb(css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + virtual ~BackendDb() {}; + + void removeEntry(::rtl::OUString const & url); + + /* This is called to write the "revoked" attribute to the entry. + This is done when XPackage::revokePackage is called. + */ + void revokeEntry(::rtl::OUString const & url); + + /* returns false if the entry does not exist yet. + */ + bool activateEntry(::rtl::OUString const & url); + + bool hasActiveEntry(::rtl::OUString const & url); + +}; + +class RegisteredDb: public BackendDb +{ + +public: + RegisteredDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + virtual ~RegisteredDb() {}; + + + virtual void addEntry(::rtl::OUString const & url); + virtual bool getEntry(::rtl::OUString const & url); + +}; + +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/inc/dp_registry.hrc b/desktop/source/deployment/registry/inc/dp_registry.hrc new file mode 100755 index 000000000000..4a3b1d0b1a4a --- /dev/null +++ b/desktop/source/deployment/registry/inc/dp_registry.hrc @@ -0,0 +1,40 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_REGISTRY_HRC +#define INCLUDED_DP_REGISTRY_HRC + +#include "deployment.hrc" + +#define RID_STR_CANNOT_DETECT_MEDIA_TYPE (RID_DEPLOYMENT_REGISTRY_START+0) +#define RID_STR_UNSUPPORTED_MEDIA_TYPE (RID_DEPLOYMENT_REGISTRY_START+1) +#define RID_STR_ERROR_WHILE_REGISTERING (RID_DEPLOYMENT_REGISTRY_START+2) +#define RID_STR_ERROR_WHILE_REVOKING (RID_DEPLOYMENT_REGISTRY_START+3) +#define RID_STR_REGISTERING_PACKAGE (RID_DEPLOYMENT_REGISTRY_START+4) +#define RID_STR_REVOKING_PACKAGE (RID_DEPLOYMENT_REGISTRY_START+5) + +#endif diff --git a/desktop/source/deployment/registry/makefile.mk b/desktop/source/deployment/registry/makefile.mk new file mode 100755 index 000000000000..e45cec272ca7 --- /dev/null +++ b/desktop/source/deployment/registry/makefile.mk @@ -0,0 +1,49 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_registry +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_registry.src + +INCPRE += inc + +SLOFILES = \ + $(SLO)$/dp_backend.obj \ + $(SLO)$/dp_registry.obj \ + $(SLO)$/dp_backenddb.obj + +.INCLUDE : ..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/package/dp_extbackenddb.cxx b/desktop/source/deployment/registry/package/dp_extbackenddb.cxx new file mode 100644 index 000000000000..5331f612c383 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_extbackenddb.cxx @@ -0,0 +1,140 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" + +#include "dp_extbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/extension-registry/2010" +#define NS_PREFIX "ext" +#define ROOT_ELEMENT_NAME "extension-backend-db" +#define KEY_ELEMENT_NAME "extension" + +namespace dp_registry { +namespace backend { +namespace bundle { + +ExtensionBackendDb::ExtensionBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +OUString ExtensionBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ExtensionBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString ExtensionBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString ExtensionBackendDb::getKeyElementName() +{ + return OUSTR(KEY_ELEMENT_NAME); +} + +void ExtensionBackendDb::addEntry(::rtl::OUString const & url, Data const & data) +{ + try{ + //reactive revoked entry if possible. + if (!activateEntry(url)) + { + Reference<css::xml::dom::XNode> extensionNodeNode = writeKeyElement(url); + writeVectorOfPair( + data.items, + OUSTR("extension-items"), + OUSTR("item"), + OUSTR("url"), + OUSTR("media-type"), + extensionNodeNode); + save(); + } + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +ExtensionBackendDb::Data ExtensionBackendDb::getEntry(::rtl::OUString const & url) +{ + try + { + ExtensionBackendDb::Data retData; + Reference<css::xml::dom::XNode> aNode = getKeyElement(url); + + if (aNode.is()) + { + retData.items = + readVectorOfPair( + aNode, + OUSTR("extension-items"), + OUSTR("item"), + OUSTR("url"), + OUSTR("media-type")); + } + return retData; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +} // namespace bundle +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/package/dp_extbackenddb.hxx b/desktop/source/deployment/registry/package/dp_extbackenddb.hxx new file mode 100644 index 000000000000..e94c846887c3 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_extbackenddb.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_EXTBACKENDDB_HXX +#define INCLUDED_DP_EXTBACKENDDB_HXX + +#include <utility> +#include <vector> + +#include "rtl/ustring.hxx" + +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace xml { namespace dom { + class XDocument; + class XNode; + }} + namespace xml { namespace xpath { + class XXPathAPI; + }} +}}} + +namespace dp_registry { +namespace backend { +namespace bundle { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + */ +class ExtensionBackendDb: public dp_registry::backend::BackendDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + virtual ::rtl::OUString getNSPrefix(); + virtual ::rtl::OUString getRootElementName(); + virtual ::rtl::OUString getKeyElementName(); + +public: + struct Data + { + /* every element consists of a pair of the url to the item (jar,rdb, etc) + and the media type + */ + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString> > items; + typedef ::std::vector< + ::std::pair< ::rtl::OUString, ::rtl::OUString> >::const_iterator ITC_ITEMS; + }; + +public: + ExtensionBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + + void addEntry(::rtl::OUString const & url, Data const & data); + + Data getEntry(::rtl::OUString const & url); + +}; + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/package/dp_package.cxx b/desktop/source/deployment/registry/package/dp_package.cxx new file mode 100644 index 000000000000..f28269411703 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_package.cxx @@ -0,0 +1,1691 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_package.hrc" +#include "dp_backend.h" +#include "dp_ucb.h" +#include "dp_interact.h" +#include "dp_dependencies.hxx" +#include "dp_platform.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_identifier.hxx" +#include "rtl/uri.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase1.hxx" +#include "ucbhelper/content.hxx" +#include "svl/inettype.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/makesequence.hxx" +#include "comphelper/sequence.hxx" +#include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/beans/UnknownPropertyException.hpp" +#include "com/sun/star/graphic/XGraphic.hpp" +#include "com/sun/star/graphic/XGraphicProvider.hpp" +#include "com/sun/star/io/XOutputStream.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/task/InteractionClassification.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/ucb/XInteractionReplaceExistingData.hpp" +#include "com/sun/star/ucb/NameClashResolveRequest.hpp" +#include "com/sun/star/ucb/XContentAccess.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/ucb/UnsupportedCommandException.hpp" +#include "com/sun/star/sdbc/XResultSet.hpp" +#include "com/sun/star/sdbc/XRow.hpp" +#include "com/sun/star/packages/manifest/XManifestReader.hpp" +#include "com/sun/star/packages/manifest/XManifestWriter.hpp" +#include "com/sun/star/deployment/DependencyException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/PlatformException.hpp" +#include "com/sun/star/deployment/Prerequisites.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include "boost/optional.hpp" +#include <vector> +#include <stdio.h> + +#include "dp_extbackenddb.hxx" +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace css = ::com::sun::star; + +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace bundle { +namespace { + +typedef cppu::ImplInheritanceHelper1<PackageRegistryBackend, + lang::XServiceInfo> ImplBaseT; + +//============================================================================== +class BackendImpl : public ImplBaseT +{ + class PackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + /** constains the old tooltip description for the Extension Manager GUI in OOo v.2.x + We keep it for backward compatibility. + */ + OUString m_oldDescription; + OUString m_url_expanded; + const bool m_legacyBundle; + Sequence< Reference<deployment::XPackage> > m_bundle; + Sequence< Reference<deployment::XPackage> > * m_pBundle; + + ExtensionBackendDb::Data m_dbData; + + Reference<deployment::XPackage> bindBundleItem( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, //that is, useing data base information + OUString const & identifier, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + bool notifyDetectionError = true ); + + typedef ::std::vector< Reference<deployment::XPackage> > t_packagevec; + void scanBundle( + t_packagevec & bundle, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ); + void scanLegacyBundle( + t_packagevec & bundle, + OUString const & url, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + bool skip_registration = false ); + ::std::vector<Reference<deployment::XPackage> > getPackagesFromDb( + Reference<ucb::XCommandEnvironment> const & xCmdEnv); + bool checkPlatform( + Reference<ucb::XCommandEnvironment > const & environment); + + bool checkDependencies( + Reference<ucb::XCommandEnvironment > const & + environment, + DescriptionInfoset const & description); + // throws css::uno::RuntimeException, + // css::deployment::DeploymentException + + ::sal_Bool checkLicense( + Reference< ucb::XCommandEnvironment > const & xCmdEnv, + DescriptionInfoset const & description, bool bNoLicenseChecking) + throw (deployment::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + RuntimeException); + // @throws DeploymentException + OUString getTextFromURL( + const Reference< ucb::XCommandEnvironment >& xCmdEnv, + const OUString& licenseUrl); + + DescriptionInfoset getDescriptionInfoset(); + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ); + + virtual void SAL_CALL disposing(); + + + + public: + PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, + OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool legacyBundle, + bool bRemoved, + OUString const & identifier); + + // XPackage + virtual sal_Bool SAL_CALL isBundle() throw (RuntimeException); + + virtual Sequence< Reference<deployment::XPackage> > SAL_CALL getBundle( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, RuntimeException); + virtual OUString SAL_CALL getDescription() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual OUString SAL_CALL getLicenseText() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual void SAL_CALL exportTo( + OUString const & destFolderURL, OUString const & newTitle, + sal_Int32 nameClashAction, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deployment::ExtensionRemovedException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + RuntimeException); + + virtual ::sal_Int32 SAL_CALL checkPrerequisites( + const Reference< task::XAbortChannel >& xAbortChannel, + const Reference< ucb::XCommandEnvironment >& xCmdEnv, + ::sal_Bool noLicenseChecking) + throw (deployment::ExtensionRemovedException, + deployment::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + RuntimeException); + + virtual ::sal_Bool SAL_CALL checkDependencies( + const Reference< ucb::XCommandEnvironment >& xCmdEnv ) + throw (deployment::DeploymentException, + deployment::ExtensionRemovedException, + ucb::CommandFailedException, + RuntimeException); + + virtual beans::Optional<OUString> SAL_CALL getIdentifier() + throw (RuntimeException); + + virtual OUString SAL_CALL getVersion() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual Sequence<OUString> SAL_CALL getUpdateInformationURLs() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual beans::StringPair SAL_CALL getPublisherInfo() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual OUString SAL_CALL getDisplayName() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual Reference< graphic::XGraphic > SAL_CALL + getIcon( ::sal_Bool bHighContrast ) + throw (deployment::ExtensionRemovedException, + RuntimeException); + }; + friend class PackageImpl; + + Reference<deployment::XPackageRegistry> m_xRootRegistry; + const Reference<deployment::XPackageTypeInfo> m_xBundleTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xLegacyBundleTypeInfo; + Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + + std::auto_ptr<ExtensionBackendDb> m_backendDb; + + void addDataToDb(OUString const & url, ExtensionBackendDb::Data const & data); + ExtensionBackendDb::Data readDataFromDb(OUString const & url); + void revokeEntryFromDb(OUString const & url); + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ); + + virtual void SAL_CALL disposing(); + +public: + BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext, + Reference<deployment::XPackageRegistry> const & xRootRegistry ); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService( OUString const& name ) + throw (RuntimeException); + virtual Sequence<OUString> SAL_CALL getSupportedServiceNames() + throw (RuntimeException); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) + throw (deployment::DeploymentException, + uno::RuntimeException); + + using ImplBaseT::disposing; +}; + +//Used to find a XPackage with a particular URL +class XPackage_eq : public std::unary_function<Reference<deployment::XPackage>, bool> +{ + OUString m_URL; +public: + explicit XPackage_eq(const OUString & s) : m_URL(s) {} + bool operator() (const Reference<deployment::XPackage> & p) const + { + return m_URL.equals(p->getURL()); + } +}; + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext, + Reference<deployment::XPackageRegistry> const & xRootRegistry ) + : ImplBaseT( args, xComponentContext ), + m_xRootRegistry( xRootRegistry ), + m_xBundleTypeInfo( new Package::TypeInfo( + OUSTR("application/vnd.sun.star.package-bundle"), + OUSTR("*.oxt;*.uno.pkg"), + getResourceString(RID_STR_PACKAGE_BUNDLE), + RID_IMG_DEF_PACKAGE_BUNDLE ) ), + m_xLegacyBundleTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.legacy-package-bundle"), + OUSTR("*.zip"), + m_xBundleTypeInfo->getShortDescription(), + RID_IMG_DEF_PACKAGE_BUNDLE ) ), + m_typeInfos(2) +{ + m_typeInfos[ 0 ] = m_xBundleTypeInfo; + m_typeInfos[ 1 ] = m_xLegacyBundleTypeInfo; + + if (!transientMode()) + { + OUString dbFile = makeURL(getCachePath(), getImplementationName()); + dbFile = makeURL(dbFile, OUSTR("backenddb.xml")); + m_backendDb.reset( + new ExtensionBackendDb(getComponentContext(), dbFile)); + } +} + +//______________________________________________________________________________ +void BackendImpl::disposing() +{ + m_xRootRegistry.clear(); + PackageRegistryBackend::disposing(); +} + +// XServiceInfo +OUString BackendImpl::getImplementationName() throw (RuntimeException) +{ + return OUSTR("com.sun.star.comp.deployment.bundle.PackageRegistryBackend"); +} + +sal_Bool BackendImpl::supportsService( OUString const& name ) + throw (RuntimeException) +{ + return getSupportedServiceNames()[0].equals(name); +} + +Sequence<OUString> BackendImpl::getSupportedServiceNames() + throw (RuntimeException) +{ + return comphelper::makeSequence( + OUString(RTL_CONSTASCII_USTRINGPARAM(BACKEND_SERVICE_NAME)) ); +} + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return m_typeInfos; +} + +void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/) + throw (deployment::DeploymentException, + uno::RuntimeException) +{ + //Notify the backend responsible for processing the different media + //types that this extension was removed. + ExtensionBackendDb::Data data = readDataFromDb(url); + for (ExtensionBackendDb::Data::ITC_ITEMS i = data.items.begin(); i != data.items.end(); i++) + { + m_xRootRegistry->packageRemoved(i->first, i->second); + } + + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, + sal_Bool bRemoved, OUString const & identifier, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + OUString mediaType( mediaType_ ); + if (mediaType.getLength() == 0) + { + // detect media-type: + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, url, xCmdEnv )) + { + if (ucbContent.isFolder()) + { + //Every .oxt, uno.pkg file must contain a META-INF folder + ::ucbhelper::Content metaInfContent; + if (create_ucb_content( + &metaInfContent, makeURL( url, OUSTR("META-INF") ), + xCmdEnv, false /* no throw */ )) + { + mediaType = OUSTR("application/vnd.sun.star.package-bundle"); + } + //No support of legacy bundles, because every folder could be one. + } + else + { + const OUString title( ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".oxt") ) || + title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".uno.pkg") )) + mediaType = OUSTR("application/vnd.sun.star.package-bundle"); + else if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".zip") )) + mediaType = + OUSTR("application/vnd.sun.star.legacy-package-bundle"); + } + } + if (mediaType.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + + //In case a XPackage is created for a removed extension, we cannot + //obtain the name + OUString name; + if (!bRemoved) + { + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + name = ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>(); + } + if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.package-bundle")) { + return new PackageImpl( + this, url, name, m_xBundleTypeInfo, false, bRemoved, + identifier); + } + else if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.legacy-package-bundle")) { + return new PackageImpl( + this, url, name, m_xLegacyBundleTypeInfo, true, bRemoved, + identifier); + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + +void BackendImpl::addDataToDb( + OUString const & url, ExtensionBackendDb::Data const & data) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url, data); +} + +ExtensionBackendDb::Data BackendImpl::readDataFromDb( + OUString const & url) +{ + ExtensionBackendDb::Data data; + if (m_backendDb.get()) + data = m_backendDb->getEntry(url); + return data; +} + +void BackendImpl::revokeEntryFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->revokeEntry(url); +} + + + +BackendImpl::PackageImpl::PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, + OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool legacyBundle, bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier), + m_url_expanded( expandUnoRcUrl( url ) ), + m_legacyBundle( legacyBundle ), + m_pBundle( 0 ) +{ + if (bRemoved) + m_dbData = getMyBackend()->readDataFromDb(url); +} + +BackendImpl * BackendImpl::PackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); + } + return pBackend; +} +//______________________________________________________________________________ +void BackendImpl::PackageImpl::disposing() +{ + sal_Int32 len = m_bundle.getLength(); + Reference<deployment::XPackage> const * p = m_bundle.getConstArray(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + try_dispose( p[ pos ] ); + m_bundle.realloc( 0 ); + + Package::disposing(); +} + +// Package +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::PackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + //In case the object was created for a removed extension (m_bRemoved = true) + //but the extension is not registered, then bundle will be empty. Then + //the return value will be Optional<...>.IsPresent= false. Althoug this is + //not true, this does not matter. Then registerPackage or revokePackage + //would never be called for the items. But since the extension is removed + //and not registered anyway, this does not matter. + const Sequence< Reference<deployment::XPackage> > bundle( + getBundle( abortChannel.get(), xCmdEnv ) ); + + bool reg = false; + bool present = false; + bool ambig = false; + for ( sal_Int32 pos = bundle.getLength(); pos--; ) + { + Reference<deployment::XPackage> const & xPackage = bundle[ pos ]; + Reference<task::XAbortChannel> xSubAbortChannel( + xPackage->createAbortChannel() ); + AbortChannel::Chain chain( abortChannel, xSubAbortChannel ); + beans::Optional< beans::Ambiguous<sal_Bool> > option( + xPackage->isRegistered( xSubAbortChannel, xCmdEnv ) ); + + //present = true if at least one bundle item has this value. + //reg = true if all bundle items have an option value (option.IsPresent == 1) + //and all have value of true (option.Value.Value == true) + //If not, then the bundle has the status of not registered and ambiguous. + if (option.IsPresent) + { + beans::Ambiguous<sal_Bool> const & status = option.Value; + if (present) + { + //we never come here in the first iteration + if (reg != (status.Value != sal_False)) { + + ambig = true; + reg = false; + break; + } + } + else + { + //we always come here in the first iteration + reg = status.Value; + present = true; + } + } + } + return beans::Optional< beans::Ambiguous<sal_Bool> >( + present, beans::Ambiguous<sal_Bool>(reg, ambig) ); +} + +OUString BackendImpl::PackageImpl::getTextFromURL( + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv, + const OUString& licenseUrl) +{ + try + { + ::ucbhelper::Content descContent(licenseUrl, xCmdEnv); + ::rtl::ByteSequence seq = dp_misc::readFile(descContent); + return OUString( reinterpret_cast<sal_Char const *>( + seq.getConstArray()), seq.getLength(), RTL_TEXTENCODING_UTF8); + } + catch (css::uno::Exception&) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Could not read file ") + licenseUrl, 0, exc); + } + +} + +DescriptionInfoset BackendImpl::PackageImpl::getDescriptionInfoset() +{ + return dp_misc::getDescriptionInfoset(m_url_expanded); +} + +bool BackendImpl::PackageImpl::checkPlatform( + css::uno::Reference< css::ucb::XCommandEnvironment > const & environment) +{ + bool ret = false; + DescriptionInfoset info(getDescriptionInfoset()); + Sequence<OUString> platforms(info.getSupportedPlaforms()); + if (hasValidPlatform(platforms)) + { + ret = true; + } + else + { + ret = false; + rtl::OUString msg( + RTL_CONSTASCII_USTRINGPARAM("unsupported platform")); + Any e( + css::deployment::PlatformException( + msg, static_cast<OWeakObject *>(this), this)); + if (!interactContinuation( + e, cppu::UnoType< css::task::XInteractionApprove >::get(), + environment, NULL, NULL)) + { + throw css::deployment::DeploymentException( + msg, static_cast<OWeakObject *>(this), e); + } + } + return ret; +} + + +bool BackendImpl::PackageImpl::checkDependencies( + css::uno::Reference< css::ucb::XCommandEnvironment > const & environment, + DescriptionInfoset const & description) +{ + css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > + unsatisfied(dp_misc::Dependencies::check(description)); + + if (unsatisfied.getLength() == 0) { + return true; + } else { + rtl::OUString msg( + RTL_CONSTASCII_USTRINGPARAM("unsatisfied dependencies")); + Any e( + css::deployment::DependencyException( + msg, static_cast<OWeakObject *>(this), unsatisfied)); + if (!interactContinuation( + e, cppu::UnoType< css::task::XInteractionApprove >::get(), + environment, NULL, NULL)) + { + throw css::deployment::DeploymentException( + msg, static_cast<OWeakObject *>(this), e); + } + return false; + } +} + +::sal_Bool BackendImpl::PackageImpl::checkLicense( + css::uno::Reference< css::ucb::XCommandEnvironment > const & xCmdEnv, + DescriptionInfoset const & info, bool alreadyInstalled) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException) +{ + try + { + ::boost::optional<SimpleLicenseAttributes> simplLicAttr + = info.getSimpleLicenseAttributes(); + if (! simplLicAttr) + return true; + OUString sLic = info.getLocalizedLicenseURL(); + //If we do not get a localized licence then there is an error in the description.xml + //This should be handled by using a validating parser. Therefore we assume that no + //license is available. + if (sLic.getLength() == 0) + throw css::deployment::DeploymentException( + OUSTR("Could not obtain path to license. Possible error in description.xml"), 0, Any()); + OUString sHref = m_url_expanded + OUSTR("/") + sLic; + OUString sLicense = getTextFromURL(xCmdEnv, sHref); + ////determine who has to agree to the license + //check correct value for attribute + if ( ! (simplLicAttr->acceptBy.equals(OUSTR("user")) || simplLicAttr->acceptBy.equals(OUSTR("admin")))) + throw css::deployment::DeploymentException( + OUSTR("Could not obtain attribute simple-lincense@accept-by or it has no valid value"), 0, Any()); + + + //Only use interaction if there is no version of this extension already installed + //and the suppress-on-update flag is not set for the new extension + // alreadyInstalled | bSuppressOnUpdate | show license + //---------------------------------------- + // 0 | 0 | 1 + // 0 | 1 | 1 + // 1 | 0 | 1 + // 1 | 1 | 0 + + if ( !(alreadyInstalled && simplLicAttr->suppressOnUpdate)) + { + css::deployment::LicenseException licExc( + OUString(), 0, getDisplayName(), sLicense, + simplLicAttr->acceptBy); + bool approve = false; + bool abort = false; + if (! interactContinuation( + Any(licExc), task::XInteractionApprove::static_type(), xCmdEnv, &approve, &abort )) + throw css::deployment::DeploymentException( + OUSTR("Could not interact with user."), 0, Any()); + + if (approve == true) + return true; + else + return false; + } + return true; + } catch (css::ucb::CommandFailedException&) { + throw; + } catch (css::ucb::CommandAbortedException&) { + throw; + } catch (css::deployment::DeploymentException&) { + throw; + } catch (css::uno::RuntimeException&) { + throw; + } catch (css::uno::Exception&) { + Any anyExc = cppu::getCaughtException(); + throw css::deployment::DeploymentException(OUSTR("Unexpected exception"), 0, anyExc); + } +} + +::sal_Int32 BackendImpl::PackageImpl::checkPrerequisites( + const css::uno::Reference< css::task::XAbortChannel >&, + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv, + sal_Bool alreadyInstalled) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + DescriptionInfoset info = getDescriptionInfoset(); + if (!info.hasDescription()) + return 0; + + //always return LICENSE as long as the user did not accept the license + //so that XExtensonManager::checkPrerequisitesAndEnable will again + //check the license + if (!checkPlatform(xCmdEnv)) + return deployment::Prerequisites::PLATFORM | + deployment::Prerequisites::LICENSE; + else if(!checkDependencies(xCmdEnv, info)) + return deployment::Prerequisites::DEPENDENCIES | + deployment::Prerequisites::LICENSE; + else if(!checkLicense(xCmdEnv, info, alreadyInstalled)) + return deployment::Prerequisites::LICENSE; + else + return 0; +} + +::sal_Bool BackendImpl::PackageImpl::checkDependencies( + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv ) + throw (deployment::DeploymentException, + deployment::ExtensionRemovedException, + ucb::CommandFailedException, + RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + DescriptionInfoset info = getDescriptionInfoset(); + if (!info.hasDescription()) + return sal_True; + + return checkDependencies(xCmdEnv, info); +} + +beans::Optional<OUString> BackendImpl::PackageImpl::getIdentifier() + throw (RuntimeException) +{ + OUString identifier; + if (m_bRemoved) + identifier = m_identifier; + else + identifier = dp_misc::generateIdentifier( + getDescriptionInfoset().getIdentifier(), m_name); + + return beans::Optional<OUString>( + true, identifier); +} + +OUString BackendImpl::PackageImpl::getVersion() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return getDescriptionInfoset().getVersion(); +} + +Sequence<OUString> BackendImpl::PackageImpl::getUpdateInformationURLs() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return getDescriptionInfoset().getUpdateInformationUrls(); +} + +beans::StringPair BackendImpl::PackageImpl::getPublisherInfo() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + ::std::pair< OUString, OUString > aInfo = getDescriptionInfoset().getLocalizedPublisherNameAndURL(); + beans::StringPair aStrPair( aInfo.first, aInfo.second ); + return aStrPair; +} + +//______________________________________________________________________________ +uno::Reference< graphic::XGraphic > BackendImpl::PackageImpl::getIcon( sal_Bool bHighContrast ) + throw (deployment::ExtensionRemovedException, RuntimeException ) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + uno::Reference< graphic::XGraphic > xGraphic; + + OUString aIconURL = getDescriptionInfoset().getIconURL( bHighContrast ); + if ( aIconURL.getLength() ) + { + OUString aFullIconURL = m_url_expanded + OUSTR("/") + aIconURL; + + uno::Reference< XComponentContext > xContext( getMyBackend()->getComponentContext() ); + uno::Reference< graphic::XGraphicProvider > xGraphProvider( + xContext->getServiceManager()->createInstanceWithContext( OUSTR( "com.sun.star.graphic.GraphicProvider" ), xContext ), + uno::UNO_QUERY ); + + if ( xGraphProvider.is() ) + { + uno::Sequence< beans::PropertyValue > aMediaProps( 1 ); + aMediaProps[0].Name = OUSTR( "URL" ); + aMediaProps[0].Value <<= aFullIconURL; + + xGraphic = xGraphProvider->queryGraphic( aMediaProps ); + } + } + + return xGraphic; +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + const Sequence< Reference<deployment::XPackage> > bundle( + getBundle( abortChannel.get(), xCmdEnv ) ); + + if (doRegisterPackage) + { + ExtensionBackendDb::Data data; + const sal_Int32 len = bundle.getLength(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + checkAborted(abortChannel); + Reference<deployment::XPackage> const & xPackage = bundle[ pos ]; + Reference<task::XAbortChannel> xSubAbortChannel( + xPackage->createAbortChannel() ); + AbortChannel::Chain chain( abortChannel, xSubAbortChannel ); + try { + xPackage->registerPackage( startup, xSubAbortChannel, xCmdEnv ); + } + catch (Exception &) + { + //We even try a rollback if the user cancelled the action (CommandAbortedException) + //in order to prevent invalid database entries. + Any exc( ::cppu::getCaughtException() ); + // try to handle exception, notify: + bool approve = false, abort = false; + if (! interactContinuation( + Any( lang::WrappedTargetException( + OUSTR("bundle item registration error!"), + static_cast<OWeakObject *>(this), exc ) ), + task::XInteractionApprove::static_type(), xCmdEnv, + &approve, &abort )) { + OSL_ASSERT( !approve && !abort ); + if (m_legacyBundle) // default for legacy packages: ignore + continue; + // no selection at all, so rethrow; + // no C++ rethrow after getCaughtException(), + // see cppuhelper/exc_hlp.hxx: + ::cppu::throwException(exc); + } + if (approve && !abort) // ignore error, just continue + continue; + + { + ProgressLevel progress( + xCmdEnv, OUSTR("rollback...") ); + // try rollback + for ( ; pos--; ) + { + try { + bundle[ pos ]->revokePackage( + xSubAbortChannel, xCmdEnv ); + } + catch (Exception &) + { + OSL_FAIL( ::rtl::OUStringToOString( + ::comphelper::anyToString( + ::cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + // ignore any errors of rollback + } + } + progress.update( OUSTR("rollback finished.") ); + } + + deployment::DeploymentException dpExc; + if (exc >>= dpExc) { + throw ucb::CommandFailedException( + dpExc.Message, dpExc.Context, dpExc.Cause ); + } + else { + // rethrow CommandFailedException + ::cppu::throwException(exc); + } + } + data.items.push_back( + ::std::make_pair(xPackage->getURL(), + xPackage->getPackageType()->getMediaType())); + } + getMyBackend()->addDataToDb(getURL(), data); + } + else + { + // revoke in reverse order: + for ( sal_Int32 pos = bundle.getLength(); pos--; ) + { + checkAborted(abortChannel); + Reference<deployment::XPackage> const & xPackage = bundle[ pos ]; + Reference<task::XAbortChannel> xSubAbortChannel( + xPackage->createAbortChannel() ); + AbortChannel::Chain chain( abortChannel, xSubAbortChannel ); + try { + bundle[ pos ]->revokePackage( xSubAbortChannel, xCmdEnv ); + } + catch (RuntimeException &) { + throw; + } + catch (ucb::CommandAbortedException &) { + throw; + } + catch (Exception &) { + // CommandFailedException, DeploymentException: + Any exc( ::cppu::getCaughtException() ); + // try to handle exception, notify: + bool approve = false, abort = false; + if (! interactContinuation( + Any( lang::WrappedTargetException( + OUSTR("bundle item revocation error!"), + static_cast<OWeakObject *>(this), exc ) ), + task::XInteractionApprove::static_type(), xCmdEnv, + &approve, &abort )) { + OSL_ASSERT( !approve && !abort ); + if (m_legacyBundle) // default for legacy packages: ignore + continue; + // no selection at all, so rethrow + // no C++ rethrow after getCaughtException(), + // see cppuhelper/exc_hlp.hxx: + ::cppu::throwException(exc); + } + // ignore errors when revoking, although abort may have been + // selected + } + } + getMyBackend()->revokeEntryFromDb(getURL()); + } +} + +//______________________________________________________________________________ +OUString BackendImpl::PackageImpl::getDescription() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + const OUString sRelativeURL(getDescriptionInfoset().getLocalizedDescriptionURL()); + OUString sDescription; + if (sRelativeURL.getLength()) + { + OUString sURL = m_url_expanded + OUSTR("/") + sRelativeURL; + + try + { + sDescription = getTextFromURL( css::uno::Reference< css::ucb::XCommandEnvironment >(), sURL ); + } + catch ( css::deployment::DeploymentException& ) + { + OSL_FAIL( ::rtl::OUStringToOString( ::comphelper::anyToString( ::cppu::getCaughtException() ), RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } + + if (sDescription.getLength()) + return sDescription; + return m_oldDescription; +} + +//______________________________________________________________________________ +OUString BackendImpl::PackageImpl::getLicenseText() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + OUString sLicense; + DescriptionInfoset aInfo = getDescriptionInfoset(); + + ::boost::optional< SimpleLicenseAttributes > aSimplLicAttr = aInfo.getSimpleLicenseAttributes(); + if ( aSimplLicAttr ) + { + OUString aLicenseURL = aInfo.getLocalizedLicenseURL(); + + if ( aLicenseURL.getLength() ) + { + OUString aFullURL = m_url_expanded + OUSTR("/") + aLicenseURL; + sLicense = getTextFromURL( Reference< ucb::XCommandEnvironment >(), aFullURL); + } + } + + return sLicense; +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::exportTo( + OUString const & destFolderURL, OUString const & newTitle, + sal_Int32 nameClashAction, Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (ucb::CommandFailedException, + deployment::ExtensionRemovedException, + ucb::CommandAbortedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + ::ucbhelper::Content sourceContent( m_url_expanded, xCmdEnv ); + OUString title(newTitle); + if (title.getLength() == 0) + sourceContent.getPropertyValue( StrTitle::get() ) >>= title; + OUString destURL( makeURL( destFolderURL, ::rtl::Uri::encode( + title, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ) ); + + if (nameClashAction == ucb::NameClash::ASK) + { + if (create_ucb_content( + 0, destURL, xCmdEnv, false /* no throw */ )) { + bool replace = false, abort = false; + if (! interactContinuation( + Any( ucb::NameClashResolveRequest( + OUSTR("file already exists: ") + title, + static_cast<OWeakObject *>(this), + task::InteractionClassification_QUERY, + destFolderURL, title, OUString() ) ), + ucb::XInteractionReplaceExistingData::static_type(), xCmdEnv, + &replace, &abort ) || !replace) { + return; + } + } + } + else if (nameClashAction != ucb::NameClash::OVERWRITE) { + throw ucb::CommandFailedException( + OUSTR("unsupported nameClashAction!"), + static_cast<OWeakObject *>(this), Any() ); + } + erase_path( destURL, xCmdEnv ); + + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.zip://") ); + buf.append( ::rtl::Uri::encode( destURL, + rtl_UriCharClassRegName, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + buf.append( static_cast<sal_Unicode>('/') ); + OUString destFolder( buf.makeStringAndClear() ); + + ::ucbhelper::Content destFolderContent( destFolder, xCmdEnv ); + { + // transfer every item of folder into zip: + Reference<sdbc::XResultSet> xResultSet( + sourceContent.createCursor( + Sequence<OUString>(), + ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ) ); + ProgressLevel progress( xCmdEnv, OUString() ); + while (xResultSet->next()) + { + ::ucbhelper::Content subContent( + Reference<ucb::XContentAccess>( + xResultSet, UNO_QUERY_THROW )->queryContent(), xCmdEnv ); + if (! destFolderContent.transferContent( + subContent, ::ucbhelper::InsertOperation_COPY, + OUString(), ucb::NameClash::OVERWRITE )) + throw RuntimeException( OUSTR("UCB transferContent() failed!"), + static_cast<OWeakObject *>(this) ); + progress.update( Any() ); // animating progress bar + } + } + + // assure META-INF folder: + ::ucbhelper::Content metainfFolderContent; + create_folder( &metainfFolderContent, + makeURL( destFolderContent.getURL(), OUSTR("META-INF") ), + xCmdEnv ); + + if (m_legacyBundle) + { + // easy to migrate legacy bundles to new format: + // just export them once using a .oxt name! + // set detected media-types of any bundle item: + + // collect all manifest entries: + Sequence< Reference<deployment::XPackage> > bundle; + try { + bundle = getBundle( Reference<task::XAbortChannel>(), xCmdEnv ); + } + // xxx todo: think about exception specs: + catch (deployment::DeploymentException &) { + OSL_FAIL( ::rtl::OUStringToOString( + ::comphelper::anyToString( + ::cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + } + catch (lang::IllegalArgumentException & exc) { + (void) exc; + OSL_FAIL( ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + ::std::vector< Sequence<beans::PropertyValue> > manifest; + manifest.reserve( bundle.getLength() ); + sal_Int32 baseURLlen = m_url_expanded.getLength(); + Reference<deployment::XPackage> const *pbundle = bundle.getConstArray(); + const OUString strMediaType = OUSTR("MediaType"); + const OUString strFullPath = OUSTR("FullPath"); + const OUString strIsFolder = OUSTR("IsFolder"); + for ( sal_Int32 pos = bundle.getLength(); pos--; ) + { + Reference<deployment::XPackage> const & xPackage = pbundle[ pos ]; + OUString url_( expandUnoRcUrl( xPackage->getURL() ) ); + OSL_ASSERT( url_.getLength() >= baseURLlen ); + OUString fullPath; + if (url_.getLength() > baseURLlen) + fullPath = url_.copy( baseURLlen + 1 ); + ::ucbhelper::Content ucbContent( url_, xCmdEnv ); + if (ucbContent.getPropertyValue(strIsFolder).get<bool>()) + fullPath += OUSTR("/"); + Sequence<beans::PropertyValue> attribs( 2 ); + beans::PropertyValue * pattribs = attribs.getArray(); + pattribs[ 0 ].Name = strFullPath; + pattribs[ 0 ].Value <<= fullPath; + pattribs[ 1 ].Name = strMediaType; + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OUString mediaType; + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) + mediaType = xPackageType->getMediaType(); + else + mediaType = OUSTR("unknown"); + pattribs[ 1 ].Value <<= mediaType; + manifest.push_back( attribs ); + } + + // write into pipe: + Reference<XComponentContext> xContext( + getMyBackend()->getComponentContext() ); + Reference<packages::manifest::XManifestWriter> xManifestWriter( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.packages.manifest.ManifestWriter"), + xContext ), UNO_QUERY_THROW ); + Reference<io::XOutputStream> xPipe( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.io.Pipe"), xContext ), UNO_QUERY_THROW ); + xManifestWriter->writeManifestSequence( + xPipe, comphelper::containerToSequence(manifest) ); + + // write buffered pipe data to content: + ::ucbhelper::Content manifestContent( + makeURL( metainfFolderContent.getURL(), OUSTR("manifest.xml") ), + xCmdEnv ); + manifestContent.writeStream( + Reference<io::XInputStream>( xPipe, UNO_QUERY_THROW ), + true /* replace existing */ ); + } + else + { + // overwrite manifest.xml: + ::ucbhelper::Content manifestContent; + if ( ! create_ucb_content( + &manifestContent, + makeURL( m_url_expanded, OUSTR("META-INF/manifest.xml") ), + xCmdEnv, false ) ) + { + OSL_FAIL( "### missing META-INF/manifest.xml file!" ); + return; + } + + if (! metainfFolderContent.transferContent( + manifestContent, ::ucbhelper::InsertOperation_COPY, + OUString(), ucb::NameClash::OVERWRITE )) + throw RuntimeException( OUSTR("UCB transferContent() failed!"), + static_cast<OWeakObject *>(this) ); + } + + // xxx todo: maybe obsolete in the future + try { + destFolderContent.executeCommand( OUSTR("flush"), Any() ); + } + catch (ucb::UnsupportedCommandException &) { + } +} + +//______________________________________________________________________________ +sal_Bool BackendImpl::PackageImpl::isBundle() throw (RuntimeException) +{ + return true; +} + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackage> > BackendImpl::PackageImpl::getBundle( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + ucb::CommandFailedException, ucb::CommandAbortedException, + lang::IllegalArgumentException, RuntimeException) +{ + Sequence< Reference<deployment::XPackage> > * pBundle = m_pBundle; + if (pBundle == 0) + { + t_packagevec bundle; + if (m_bRemoved) + { + bundle = getPackagesFromDb(xCmdEnv); + } + else + { + try { + if (m_legacyBundle) + { + // .zip legacy packages allow script.xlb, dialog.xlb in bundle + // root folder: + OUString mediaType; + // probe for script.xlb: + if (create_ucb_content( + 0, makeURL( m_url_expanded, OUSTR("script.xlb") ), + xCmdEnv, false /* no throw */ )) { + mediaType = OUSTR("application/vnd.sun.star.basic-library"); + } + // probe for dialog.xlb: + else if (create_ucb_content( + 0, makeURL( m_url_expanded, OUSTR("dialog.xlb") ), + xCmdEnv, false /* no throw */ )) + mediaType = OUSTR("application/vnd.sun.star." + "dialog-library"); + + if (mediaType.getLength() > 0) { + const Reference<deployment::XPackage> xPackage( + bindBundleItem( getURL(), mediaType, false, OUString(), + xCmdEnv ) ); + if (xPackage.is()) + bundle.push_back( xPackage ); + // continue scanning: + } + scanLegacyBundle( bundle, getURL(), + AbortChannel::get(xAbortChannel), xCmdEnv ); + } + else + { + // .oxt: + scanBundle( bundle, AbortChannel::get(xAbortChannel), xCmdEnv ); + } + + } + catch (RuntimeException &) { + throw; + } + catch (ucb::CommandFailedException &) { + throw; + } + catch (ucb::CommandAbortedException &) { + throw; + } + catch (deployment::DeploymentException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw deployment::DeploymentException( + OUSTR("error scanning bundle: ") + getURL(), + static_cast<OWeakObject *>(this), exc ); + } + } + + // sort: schema before config data, typelibs before components: + Sequence< Reference<deployment::XPackage> > ret( bundle.size() ); + Reference<deployment::XPackage> * pret = ret.getArray(); + sal_Int32 lower_end = 0; + sal_Int32 upper_end = ret.getLength(); + t_packagevec::const_iterator iPos( bundle.begin() ); + t_packagevec::const_iterator const iEnd( bundle.end() ); + for ( ; iPos != iEnd; ++iPos ) + { + const Reference<deployment::XPackageTypeInfo> xPackageType( + (*iPos)->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) { + const OUString mediaType( xPackageType->getMediaType() ); + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( + mediaType, type, subType, ¶ms ) && + type.EqualsIgnoreCaseAscii("application") && + (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.uno-component") || + subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.configuration-data"))) + { + --upper_end; + pret[ upper_end ] = *iPos; + continue; + } + } + pret[ lower_end ] = *iPos; + ++lower_end; + } + OSL_ASSERT( lower_end == upper_end ); + + const ::osl::MutexGuard guard( getMutex() ); + pBundle = m_pBundle; + if (pBundle == 0) { + m_bundle = ret; + pBundle = &m_bundle; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + m_pBundle = pBundle; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + return *pBundle; +} + +inline bool isBundle_( OUString const & mediaType ) +{ + // xxx todo: additional parsing? + return mediaType.getLength() > 0 && + (mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.package-bundle") ) || + mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.legacy-package-bundle") )); +} + +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::PackageImpl::bindBundleItem( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + bool notifyDetectionError ) +{ + // ignore any nested bundles: + if (isBundle_(mediaType)) + return Reference<deployment::XPackage>(); + + Reference<deployment::XPackage>xPackage; + try { + xPackage.set( getMyBackend()->m_xRootRegistry->bindPackage( + url, mediaType, bRemoved, identifier, xCmdEnv ) ); + OSL_ASSERT( xPackage.is() ); + } + catch (RuntimeException &) { + throw; + } + catch (ucb::CommandFailedException &) { + // ignore already handled error + } + catch (Exception &) { + const Any exc( ::cppu::getCaughtException() ); + if (notifyDetectionError || + !exc.isExtractableTo( + ::getCppuType( reinterpret_cast< + lang::IllegalArgumentException const *>(0) ) )) + { + interactContinuation( + Any( lang::WrappedTargetException( + OUSTR("bundle item error!"), + static_cast<OWeakObject *>(this), exc ) ), + task::XInteractionApprove::static_type(), xCmdEnv, 0, 0 ); + } + } + + if (xPackage.is()) { + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + // ignore any nested bundles: + if (xPackageType.is() && isBundle_( xPackageType->getMediaType() )) + xPackage.clear(); + } + return xPackage; +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::scanBundle( + t_packagevec & bundle, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + OSL_ASSERT( !m_legacyBundle ); + + ::ucbhelper::Content manifestContent; + if (! create_ucb_content( + &manifestContent, + makeURL( m_url_expanded, OUSTR("META-INF/manifest.xml") ), + xCmdEnv, false /* no throw */ )) + { + OSL_FAIL( "### missing META-INF/manifest.xml file!" ); + return; + } + + + const lang::Locale officeLocale = getOfficeLocale(); + OUString descrFile; + lang::Locale descrFileLocale; + + const Reference<XComponentContext> xContext( + getMyBackend()->getComponentContext() ); + Reference<packages::manifest::XManifestReader> xManifestReader( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.packages.manifest.ManifestReader"), + xContext ), UNO_QUERY_THROW ); + const Sequence< Sequence<beans::PropertyValue> > manifestSeq( + xManifestReader->readManifestSequence( manifestContent.openStream() ) ); + const OUString packageRootURL( getURL() ); + for ( sal_Int32 pos = manifestSeq.getLength(); pos--; ) + { + OUString fullPath, mediaType; + Sequence<beans::PropertyValue> const & attribs = manifestSeq[ pos ]; + for ( sal_Int32 i = attribs.getLength(); i--; ) + { + if (fullPath.getLength() > 0 && mediaType.getLength() > 0) + break; + if (attribs[i].Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("FullPath") )) + attribs[i].Value >>= fullPath; + else if (attribs[i].Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("MediaType") )) + attribs[i].Value >>= mediaType; + } + + if (fullPath.getLength() == 0 || mediaType.getLength() == 0 || + mediaType.equalsAsciiL( // opt: exclude common text/xml + RTL_CONSTASCII_STRINGPARAM("text/xml") )) + continue; + + String type, subType; + INetContentTypeParameterList params; + if (! INetContentTypes::parse( mediaType, type, subType, ¶ms )) + continue; + + INetContentTypeParameter const * param = params.find( + ByteString("platform") ); + if (param != 0 && !platform_fits( param->m_sValue )) + continue; + const OUString url( makeURL( packageRootURL, fullPath ) ); + + // check for bundle description: + if (type.EqualsIgnoreCaseAscii("application") && + subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.package-bundle-description")) + { + // check locale: + param = params.find( ByteString("locale") ); + if (param == 0) { + if (descrFile.getLength() == 0) + descrFile = url; + } + else { + // match best locale: + lang::Locale locale( toLocale(param->m_sValue) ); + if (locale.Language == officeLocale.Language) + { + if (descrFileLocale.Country == officeLocale.Country + && locale.Country != officeLocale.Country) + continue; + if (descrFileLocale.Variant == officeLocale.Variant + && locale.Variant != officeLocale.Variant) + continue; + descrFile = url; + descrFileLocale = locale; + } + } + continue; + } + + checkAborted( abortChannel ); + + //We make sure that we only create one XPackage for a particular URL. + //Sometime programmers insert the same URL several times in the manifest + //which may lead to DisposedExceptions. + if (bundle.end() == std::find_if(bundle.begin(), bundle.end(), XPackage_eq(url))) + { + const Reference<deployment::XPackage> xPackage( + bindBundleItem( url, mediaType, false, OUString(), xCmdEnv ) ); + if (xPackage.is()) + bundle.push_back( xPackage ); + } + else + { + fprintf(stderr, "manifest.xml contains a duplicate entry!\n"); + } + } + + if (descrFile.getLength() > 0) + { + ::ucbhelper::Content descrFileContent; + if (create_ucb_content( &descrFileContent, descrFile, + xCmdEnv, false /* no throw */ )) + { + // patch description: + ::rtl::ByteSequence bytes( readFile( descrFileContent ) ); + ::rtl::OUStringBuffer buf; + if ( bytes.getLength() ) + { + buf.append( OUString( reinterpret_cast<sal_Char const *>( + bytes.getConstArray() ), + bytes.getLength(), RTL_TEXTENCODING_UTF8 ) ); + } + else + { + buf.append( Package::getDescription() ); + } + m_oldDescription = buf.makeStringAndClear(); + } + } +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::scanLegacyBundle( + t_packagevec & bundle, + OUString const & url, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + bool skip_registration ) +{ + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + + // check for platform pathes: + const OUString title( ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".plt") ) && + !platform_fits( title.copy( 0, title.getLength() - 4 ) )) { + return; + } + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("skip_registration") )) + skip_registration = true; + + OUString ar [] = { StrTitle::get(), OUSTR("IsFolder") }; + Reference<sdbc::XResultSet> xResultSet( + ucbContent.createCursor( + Sequence<OUString>( ar, ARLEN(ar) ), + ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ) ); + while (xResultSet->next()) + { + checkAborted( abortChannel ); + + const Reference<sdbc::XRow> xRow( xResultSet, UNO_QUERY_THROW ); + const OUString title_enc( ::rtl::Uri::encode( + xRow->getString( 1 /* Title */ ), + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + const OUString path( makeURL( url, title_enc ) ); + + OUString mediaType; + const Reference<deployment::XPackage> xPackage( + bindBundleItem( path, OUString() /* detect */, false, OUString(), + xCmdEnv, false /* ignore detection errors */ ) ); + if (xPackage.is()) { + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) + mediaType = xPackageType->getMediaType(); + + if (skip_registration && + // xxx todo: additional parsing? + mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.uno-component") )) + continue; + + bundle.push_back( xPackage ); + } + + if (mediaType.getLength() == 0 || + // script.xlb, dialog.xlb can be met everywhere: + mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.basic-library") ) || + mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.dialog-library") )) + { + if (xRow->getBoolean( 2 /* IsFolder */ )) { // recurse into folder: + scanLegacyBundle( + bundle, path, abortChannel, xCmdEnv, skip_registration ); + } + } + } +} + +OUString BackendImpl::PackageImpl::getDisplayName() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + OUString sName = getDescriptionInfoset().getLocalizedDisplayName(); + if (sName.getLength() == 0) + return m_displayName; + else + return sName; +} + +::std::vector<Reference<deployment::XPackage> > +BackendImpl::PackageImpl::getPackagesFromDb( + Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + ::std::vector<Reference<deployment::XPackage> > retVector; + + typedef ::std::vector< ::std::pair<OUString, OUString> >::const_iterator ITC; + for (ITC i = m_dbData.items.begin(); i != m_dbData.items.end(); i++) + { + Reference<deployment::XPackage> xExtension = + bindBundleItem(i->first, i->second, true, m_identifier, xCmdEnv); + OSL_ASSERT(xExtension.is()); + if (xExtension.is()) + retVector.push_back(xExtension); + } + + return retVector; +} + +} // anon namespace + +//============================================================================== +Reference<deployment::XPackageRegistry> create( + Reference<deployment::XPackageRegistry> const & xRootRegistry, + OUString const & context, OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ) +{ + Sequence<Any> args( + cachePath.getLength() == 0 ? 1 : 3 ); + args[ 0 ] <<= context; + if (cachePath.getLength() > 0) { + args[ 1 ] <<= cachePath; + args[ 2 ] <<= readOnly; + } + return new BackendImpl( args, xComponentContext, xRootRegistry ); +} + +} // namespace bundle +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/package/dp_package.hrc b/desktop/source/deployment/registry/package/dp_package.hrc new file mode 100755 index 000000000000..3a840b64f0b6 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_package.hrc @@ -0,0 +1,35 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_PACKAGE_HRC +#define INCLUDED_DP_PACKAGE_HRC + +#include "deployment.hrc" + +#define RID_STR_PACKAGE_BUNDLE (RID_DEPLOYMENT_BUNDLE_START+10) + +#endif diff --git a/desktop/source/deployment/registry/package/dp_package.src b/desktop/source/deployment/registry/package/dp_package.src new file mode 100644 index 000000000000..57307040bba4 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_package.src @@ -0,0 +1,34 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_package.hrc" + +String RID_STR_PACKAGE_BUNDLE +{ + Text [ en-US ] = "Extension"; +}; + diff --git a/desktop/source/deployment/registry/package/makefile.mk b/desktop/source/deployment/registry/package/makefile.mk new file mode 100755 index 000000000000..203ce176d289 --- /dev/null +++ b/desktop/source/deployment/registry/package/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_registry_package +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_package.src + +INCPRE += ..$/..$/inc + +SLOFILES = \ + $(SLO)$/dp_package.obj \ + $(SLO)$/dp_extbackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/script/dp_lib_container.cxx b/desktop/source/deployment/registry/script/dp_lib_container.cxx new file mode 100644 index 000000000000..2bc2c07130a0 --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_lib_container.cxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" + +#include "dp_script.hrc" +#include "dp_resource.h" +#include "dp_xml.h" +#include "dp_lib_container.h" + +#include "rtl/ustring.hxx" +#include "ucbhelper/content.hxx" +#include "xmlscript/xmllib_imexp.hxx" + + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace script { + +namespace { +struct StrCannotDetermineLibName : public StaticResourceString< + StrCannotDetermineLibName, RID_STR_CANNOT_DETERMINE_LIBNAME> {}; +} + +//______________________________________________________________________________ +OUString LibraryContainer::get_libname( + OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv, + Reference<XComponentContext> const & xContext ) +{ + ::xmlscript::LibDescriptor import; + ::ucbhelper::Content ucb_content( url, xCmdEnv ); + xml_parse( ::xmlscript::importLibrary( import ), ucb_content, xContext ); + + if (import.aName.getLength() == 0) { + throw Exception( StrCannotDetermineLibName::get(), + Reference<XInterface>() ); + } + return import.aName; +} + +} +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/script/dp_lib_container.h b/desktop/source/deployment/registry/script/dp_lib_container.h new file mode 100755 index 000000000000..0cd5cb2cba90 --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_lib_container.h @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_LIB_CONTAINER_H +#define INCLUDED_DP_LIB_CONTAINER_H + +#include <com/sun/star/uno/Reference.hxx> + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace ucb { + class XCommandEnvironment; + } +}}} + +namespace rtl { + class OUString; +} + +namespace css = ::com::sun::star; + +namespace dp_registry { +namespace backend { +namespace script { + +//============================================================================== +class LibraryContainer +{ +public: + static ::rtl::OUString get_libname( + ::rtl::OUString const & url, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + css::uno::Reference<css::uno::XComponentContext> const & xContext ); +}; + +} +} +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/script/dp_script.cxx b/desktop/source/deployment/registry/script/dp_script.cxx new file mode 100644 index 000000000000..c9d3b19a5309 --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_script.cxx @@ -0,0 +1,483 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_script.hrc" +#include "dp_lib_container.h" +#include "dp_backend.h" +#include "dp_ucb.h" +#include "rtl/uri.hxx" +#include "ucbhelper/content.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase1.hxx" +#include "comphelper/servicedecl.hxx" +#include "svl/inettype.hxx" +#include "com/sun/star/util/XUpdatable.hpp" +#include "com/sun/star/script/XLibraryContainer3.hpp" +#include <com/sun/star/util/XMacroExpander.hpp> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> +#include <memory> +#include "dp_scriptbackenddb.hxx" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; +namespace css = ::com::sun::star; + +namespace dp_registry { +namespace backend { +namespace script { +namespace { + +typedef ::cppu::ImplInheritanceHelper1< + ::dp_registry::backend::PackageRegistryBackend, util::XUpdatable > t_helper; + +class BackendImpl : public t_helper +{ + class PackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + const OUString m_scriptURL; + const OUString m_dialogURL; + OUString m_dialogName; + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + public: + PackageImpl( + ::rtl::Reference<BackendImpl> const & myBackend, + OUString const & url, + Reference<XCommandEnvironment> const &xCmdEnv, + OUString const & scriptURL, OUString const & dialogURL, + bool bRemoved, OUString const & identifier); + }; + friend class PackageImpl; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ); + + void addDataToDb(OUString const & url); + bool hasActiveEntry(OUString const & url); + void revokeEntryFromDb(OUString const & url); + + const Reference<deployment::XPackageTypeInfo> m_xBasicLibTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xDialogLibTypeInfo; + Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + std::auto_ptr<ScriptBackendDb> m_backendDb; +public: + BackendImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XUpdatable + virtual void SAL_CALL update() throw (RuntimeException); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) + throw (deployment::DeploymentException, + uno::RuntimeException); + +}; + +//______________________________________________________________________________ +BackendImpl::PackageImpl::PackageImpl( + ::rtl::Reference<BackendImpl> const & myBackend, + OUString const & url, + Reference<XCommandEnvironment> const &xCmdEnv, + OUString const & scriptURL, OUString const & dialogURL, bool bRemoved, + OUString const & identifier) + : Package( myBackend.get(), url, + OUString(), OUString(), // will be late-initialized + scriptURL.getLength() > 0 ? myBackend->m_xBasicLibTypeInfo + : myBackend->m_xDialogLibTypeInfo, bRemoved, identifier), + m_scriptURL( scriptURL ), + m_dialogURL( dialogURL ) +{ + // name, displayName: + if (dialogURL.getLength() > 0) { + m_dialogName = LibraryContainer::get_libname( + dialogURL, xCmdEnv, myBackend->getComponentContext() ); + } + if (scriptURL.getLength() > 0) { + m_name = LibraryContainer::get_libname( + scriptURL, xCmdEnv, myBackend->getComponentContext() ); + } + else + m_name = m_dialogName; + m_displayName = m_name; +} + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : t_helper( args, xComponentContext ), + m_xBasicLibTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.basic-library"), + OUString() /* no file filter */, + getResourceString(RID_STR_BASIC_LIB), + RID_IMG_SCRIPTLIB) ), + m_xDialogLibTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.dialog-library"), + OUString() /* no file filter */, + getResourceString(RID_STR_DIALOG_LIB), + RID_IMG_DIALOGLIB) ), + m_typeInfos( 2 ) +{ + m_typeInfos[ 0 ] = m_xBasicLibTypeInfo; + m_typeInfos[ 1 ] = m_xDialogLibTypeInfo; + + OSL_ASSERT( ! transientMode() ); + + if (!transientMode()) + { + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new ScriptBackendDb(getComponentContext(), dbFile)); + } + +} +void BackendImpl::addDataToDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url); +} + +bool BackendImpl::hasActiveEntry(OUString const & url) +{ + if (m_backendDb.get()) + return m_backendDb->hasActiveEntry(url); + return false; +} + +// XUpdatable +//______________________________________________________________________________ +void BackendImpl::update() throw (RuntimeException) +{ + // Nothing to do here after fixing i70283!? +} + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return m_typeInfos; +} +void BackendImpl::revokeEntryFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->revokeEntry(url); +} + +void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/) + throw (deployment::DeploymentException, + uno::RuntimeException) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + OUString mediaType( mediaType_ ); + if (mediaType.getLength() == 0) + { + // detect media-type: + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, url, xCmdEnv ) && + ucbContent.isFolder()) + { + // probe for script.xlb: + if (create_ucb_content( + 0, makeURL( url, OUSTR("script.xlb") ), + xCmdEnv, false /* no throw */ )) + mediaType = OUSTR("application/vnd.sun.star.basic-library"); + // probe for dialog.xlb: + else if (create_ucb_content( + 0, makeURL( url, OUSTR("dialog.xlb") ), + xCmdEnv, false /* no throw */ )) + mediaType = OUSTR("application/vnd.sun.star.dialog-library"); + } + if (mediaType.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + OUString dialogURL( makeURL( url, OUSTR("dialog.xlb") ) ); + if (! create_ucb_content( + 0, dialogURL, xCmdEnv, false /* no throw */ )) { + dialogURL = OUString(); + } + + if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.basic-library")) + { + OUString scriptURL( makeURL( url, OUSTR("script.xlb"))); + if (! create_ucb_content( + 0, scriptURL, xCmdEnv, false /* no throw */ )) { + scriptURL = OUString(); + } + + return new PackageImpl( + this, url, xCmdEnv, scriptURL, + dialogURL, bRemoved, identifier); + } + else if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.dialog-library")) { + return new PackageImpl( + this, url, xCmdEnv, + OUString() /* no script lib */, + dialogURL, + bRemoved, identifier); + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + + +// Package +BackendImpl * BackendImpl::PackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); + } + return pBackend; +} + +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::PackageImpl::isRegistered_( + ::osl::ResettableMutexGuard & /* guard */, + ::rtl::Reference<AbortChannel> const & /* abortChannel */, + Reference<XCommandEnvironment> const & /* xCmdEnv */ ) +{ + BackendImpl * that = getMyBackend(); + Reference< deployment::XPackage > xThisPackage( this ); + + bool registered = that->hasActiveEntry(getURL()); + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true /* IsPresent */, + beans::Ambiguous<sal_Bool>( registered, false /* IsAmbiguous */ ) ); +} + +void +lcl_maybeRemoveScript( + bool const bExists, + OUString const& rName, + OUString const& rScriptURL, + Reference<css::script::XLibraryContainer3> const& xScriptLibs) +{ + if (bExists && xScriptLibs.is() && xScriptLibs->hasByName(rName)) + { + const OUString sScriptUrl = xScriptLibs->getOriginalLibraryLinkURL(rName); + if (sScriptUrl.equals(rScriptURL)) + xScriptLibs->removeLibrary(rName); + } +} + +bool +lcl_maybeAddScript( + bool const bExists, + OUString const& rName, + OUString const& rScriptURL, + Reference<css::script::XLibraryContainer3> const& xScriptLibs) +{ + if (bExists && xScriptLibs.is()) + { + bool bCanAdd = true; + if (xScriptLibs->hasByName(rName)) + { + const OUString sOriginalUrl = xScriptLibs->getOriginalLibraryLinkURL(rName); + //We assume here that library names in extensions are unique, which may not be the case + //ToDo: If the script exist in another extension, then both extensions must have the + //same id + if (sOriginalUrl.match(OUSTR("vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE")) + || sOriginalUrl.match(OUSTR("vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE")) + || sOriginalUrl.match(OUSTR("vnd.sun.star.expand:$BUNDLED_EXTENSIONS"))) + { + xScriptLibs->removeLibrary(rName); + bCanAdd = true; + } + else + { + bCanAdd = false; + } + } + + if (bCanAdd) + { + xScriptLibs->createLibraryLink(rName, rScriptURL, false); + return xScriptLibs->hasByName(rName); + } + } + + return false; +} + +void BackendImpl::PackageImpl::processPackage_( + ::osl::ResettableMutexGuard & /* guard */, + bool doRegisterPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & /* abortChannel */, + Reference<XCommandEnvironment> const & /* xCmdEnv */ ) +{ + BackendImpl * that = getMyBackend(); + + Reference< deployment::XPackage > xThisPackage( this ); + Reference<XComponentContext> const & xComponentContext = that->getComponentContext(); + + bool bScript = (m_scriptURL.getLength() > 0); + Reference<css::script::XLibraryContainer3> xScriptLibs; + + bool bDialog = (m_dialogURL.getLength() > 0); + Reference<css::script::XLibraryContainer3> xDialogLibs; + + bool bRunning = office_is_running(); + if( bRunning ) + { + if( bScript ) + { + xScriptLibs.set( + xComponentContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.script.ApplicationScriptLibraryContainer"), + xComponentContext ), UNO_QUERY_THROW ); + } + + if( bDialog ) + { + xDialogLibs.set( + xComponentContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.script.ApplicationDialogLibraryContainer"), + xComponentContext ), UNO_QUERY_THROW ); + } + } + bool bRegistered = getMyBackend()->hasActiveEntry(getURL()); + if( !doRegisterPackage ) + { + //We cannot just call removeLibrary(name) because this could remove a + //script which was added by an extension in a different repository. For + //example, extension foo is contained in the bundled repository and then + //the user adds it it to the user repository. The extension manager will + //then register the new script and revoke the script from the bundled + //extension. removeLibrary(name) would now remove the script from the + //user repository. That is, the script of the newly added user extension does + //not work anymore. Therefore we must check if the currently active + //script comes in fact from the currently processed extension. + + if (bRegistered) + { + //we also prevent and live deployment at startup + if (!isRemoved() && !startup) + { + lcl_maybeRemoveScript(bScript, m_name, m_scriptURL, xScriptLibs); + lcl_maybeRemoveScript(bDialog, m_dialogName, m_dialogURL, xDialogLibs); + } + getMyBackend()->revokeEntryFromDb(getURL()); + return; + } + } + if (bRegistered) + return; // Already registered + + // Update LibraryContainer + bool bScriptSuccess = false; + bool bDialogSuccess = false; + if (!startup) + { + //If there is a bundled extension, and the user installes the same extension + //then the script from the bundled extension must be removed. If this does not work + //then live deployment does not work for scripts. + bScriptSuccess = lcl_maybeAddScript(bScript, m_name, m_scriptURL, xScriptLibs); + bDialogSuccess = lcl_maybeAddScript(bDialog, m_dialogName, m_dialogURL, xDialogLibs); + } + bool bSuccess = bScript || bDialog; // Something must have happened + if( bRunning && !startup) + if( (bScript && !bScriptSuccess) || (bDialog && !bDialogSuccess) ) + bSuccess = false; + + if (bSuccess) + getMyBackend()->addDataToDb(getURL()); +} + +} // anon namespace + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + "com.sun.star.comp.deployment.script.PackageRegistryBackend", + BACKEND_SERVICE_NAME ); + +} // namespace script +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/script/dp_script.hrc b/desktop/source/deployment/registry/script/dp_script.hrc new file mode 100755 index 000000000000..8ddfa6f51ffc --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_script.hrc @@ -0,0 +1,39 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_SCRIPT_HRC +#define INCLUDED_DP_SCRIPT_HRC + +#include "deployment.hrc" + +#define RID_STR_BASIC_LIB (RID_DEPLOYMENT_SCRIPT_START+10) +#define RID_STR_DIALOG_LIB (RID_DEPLOYMENT_SCRIPT_START+11) + +#define RID_STR_LIBNAME_ALREADY_EXISTS (RID_DEPLOYMENT_SCRIPT_START+15) +#define RID_STR_CANNOT_DETERMINE_LIBNAME (RID_DEPLOYMENT_SCRIPT_START+16) + +#endif diff --git a/desktop/source/deployment/registry/script/dp_script.src b/desktop/source/deployment/registry/script/dp_script.src new file mode 100644 index 000000000000..117f4eac945a --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_script.src @@ -0,0 +1,49 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_script.hrc" + +String RID_STR_BASIC_LIB +{ + Text [ en-US ] = "%PRODUCTNAME Basic Library"; +}; + +String RID_STR_DIALOG_LIB +{ + Text [ en-US ] = "Dialog Library"; +}; + +String RID_STR_CANNOT_DETERMINE_LIBNAME +{ + Text [ en-US ] = "The library name could not be determined."; +}; + +String RID_STR_LIBNAME_ALREADY_EXISTS +{ + Text [ en-US ] = "This library name already exists. Please choose a different name."; +}; + diff --git a/desktop/source/deployment/registry/script/dp_scriptbackenddb.cxx b/desktop/source/deployment/registry/script/dp_scriptbackenddb.cxx new file mode 100644 index 000000000000..8c6a4924212e --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_scriptbackenddb.cxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "rtl/string.h" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocument.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" +#include "dp_scriptbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/script-registry/2010" +#define NS_PREFIX "script" +#define ROOT_ELEMENT_NAME "script-backend-db" +#define KEY_ELEMENT_NAME "script" + +namespace dp_registry { +namespace backend { +namespace script { + +ScriptBackendDb::ScriptBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):RegisteredDb(xContext, url) +{ + +} + +OUString ScriptBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ScriptBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString ScriptBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString ScriptBackendDb::getKeyElementName() +{ + return OUSTR(KEY_ELEMENT_NAME); +} + + + +} // namespace executable +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/script/dp_scriptbackenddb.hxx b/desktop/source/deployment/registry/script/dp_scriptbackenddb.hxx new file mode 100644 index 000000000000..58a749480113 --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_scriptbackenddb.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_SCRIPTBACKENDDB_HXX +#define INCLUDED_DP_SCRIPTBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "dp_backenddb.hxx" +#include "boost/optional.hpp" +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } +}}} + +namespace dp_registry { +namespace backend { +namespace script { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + */ +class ScriptBackendDb: public dp_registry::backend::RegisteredDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + + virtual ::rtl::OUString getNSPrefix(); + + virtual ::rtl::OUString getRootElementName(); + + virtual ::rtl::OUString getKeyElementName(); + + +public: + + ScriptBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/script/makefile.mk b/desktop/source/deployment/registry/script/makefile.mk new file mode 100755 index 000000000000..708def358021 --- /dev/null +++ b/desktop/source/deployment/registry/script/makefile.mk @@ -0,0 +1,49 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_registry_script +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_script.src + +INCPRE += ..$/..$/inc + +SLOFILES = \ + $(SLO)$/dp_script.obj \ + $(SLO)$/dp_lib_container.obj \ + $(SLO)$/dp_scriptbackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/sfwk/dp_parceldesc.cxx b/desktop/source/deployment/registry/sfwk/dp_parceldesc.cxx new file mode 100644 index 000000000000..11835ddfa957 --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/dp_parceldesc.cxx @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_misc.h" +#include "dp_parceldesc.hxx" + + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +namespace css = ::com::sun::star; +namespace dp_registry +{ +namespace backend +{ +namespace sfwk +{ + + +// XDocumentHandler +void SAL_CALL +ParcelDescDocHandler::startDocument() +throw ( xml::sax::SAXException, RuntimeException ) +{ + m_bIsParsed = false; +} + +void SAL_CALL +ParcelDescDocHandler::endDocument() +throw ( xml::sax::SAXException, RuntimeException ) +{ + m_bIsParsed = true; +} + +void SAL_CALL +ParcelDescDocHandler::characters( const OUString & ) + throw ( xml::sax::SAXException, RuntimeException ) +{ +} + +void SAL_CALL +ParcelDescDocHandler::ignorableWhitespace( const OUString & ) + throw ( xml::sax::SAXException, RuntimeException ) +{ +} + +void SAL_CALL +ParcelDescDocHandler::processingInstruction( + const OUString &, const OUString & ) + throw ( xml::sax::SAXException, RuntimeException ) +{ +} + +void SAL_CALL +ParcelDescDocHandler::setDocumentLocator( + const Reference< xml::sax::XLocator >& ) + throw ( xml::sax::SAXException, RuntimeException ) +{ +} + +void SAL_CALL +ParcelDescDocHandler::startElement( const OUString& aName, + const Reference< xml::sax::XAttributeList > & xAttribs ) + throw ( xml::sax::SAXException, + RuntimeException ) +{ + + dp_misc::TRACE(OUSTR("ParcelDescDocHandler::startElement() for ") + + aName + OUSTR("\n")); + if ( !skipIndex ) + { + if ( aName.equals( OUString(RTL_CONSTASCII_USTRINGPARAM( "parcel" )) ) ) + { + m_sLang = xAttribs->getValueByName( OUString(RTL_CONSTASCII_USTRINGPARAM( "language" )) ); + } + ++skipIndex; + } + else + { + dp_misc::TRACE(OUSTR("ParcelDescDocHandler::startElement() skipping for ") + + aName + OUSTR("\n")); + } + +} + +void SAL_CALL ParcelDescDocHandler::endElement( const OUString & aName ) + throw ( xml::sax::SAXException, RuntimeException ) +{ + if ( skipIndex ) + { + --skipIndex; + dp_misc::TRACE(OUSTR("ParcelDescDocHandler::endElement() skipping for ") + + aName + OUSTR("\n")); + } +} + + +} +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/sfwk/dp_parceldesc.hxx b/desktop/source/deployment/registry/sfwk/dp_parceldesc.hxx new file mode 100644 index 000000000000..83ffddda1aff --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/dp_parceldesc.hxx @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <cppuhelper/implbase1.hxx> + +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> + +#include <com/sun/star/lang/NoSupportException.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +namespace css = ::com::sun::star; +namespace dp_registry +{ +namespace backend +{ +namespace sfwk +{ + +typedef ::cppu::WeakImplHelper1< css::xml::sax::XDocumentHandler > t_DocHandlerImpl; + +class ParcelDescDocHandler : public t_DocHandlerImpl +{ +private: + bool m_bIsParsed; + ::rtl::OUString m_sLang; + sal_Int32 skipIndex; +public: + ParcelDescDocHandler():m_bIsParsed( false ), skipIndex( 0 ){} + ::rtl::OUString getParcelLanguage() { return m_sLang; } + bool isParsed() { return m_bIsParsed; } + // XDocumentHandler + virtual void SAL_CALL startDocument() + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL endDocument() + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL startElement( const ::rtl::OUString& aName, + const css::uno::Reference< css::xml::sax::XAttributeList > & xAttribs ) + throw ( css::xml::sax::SAXException, + css::uno::RuntimeException ); + + virtual void SAL_CALL endElement( const ::rtl::OUString & aName ) + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL characters( const ::rtl::OUString & aChars ) + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString & aWhitespaces ) + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL processingInstruction( + const ::rtl::OUString & aTarget, const ::rtl::OUString & aData ) + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL setDocumentLocator( + const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); +}; +} +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/sfwk/dp_sfwk.cxx b/desktop/source/deployment/registry/sfwk/dp_sfwk.cxx new file mode 100644 index 000000000000..a93069465435 --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/dp_sfwk.cxx @@ -0,0 +1,396 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "dp_sfwk.hrc" +#include "dp_backend.h" +#include "dp_ucb.h" +#include "dp_parceldesc.hxx" +#include "rtl/uri.hxx" +#include "ucbhelper/content.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "comphelper/servicedecl.hxx" +#include "svl/inettype.hxx" +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/script/provider/XScriptProviderFactory.hpp> +#include <memory> + + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::script; + +using ::rtl::OUString; +namespace css = ::com::sun::star; + +namespace dp_registry +{ +namespace backend +{ +namespace sfwk +{ + +//============================================================================== +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + class PackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + Reference< container::XNameContainer > m_xNameCntrPkgHandler; + OUString m_descr; + + void initPackageHandler(); + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + public: + PackageImpl( + ::rtl::Reference<BackendImpl> const & myBackend, + OUString const & url, OUString const & libType, bool bRemoved, + OUString const & identifier); + // XPackage + virtual OUString SAL_CALL getDescription() throw (RuntimeException); + virtual OUString SAL_CALL getLicenseText() throw (RuntimeException); + }; + friend class PackageImpl; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ); + + const Reference<deployment::XPackageTypeInfo> m_xTypeInfo; + + +public: + BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) + throw (deployment::DeploymentException, + uno::RuntimeException); +}; + +BackendImpl * BackendImpl::PackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); + } + return pBackend; +} +//______________________________________________________________________________ +OUString BackendImpl::PackageImpl::getDescription() throw (RuntimeException) +{ + if (m_descr.getLength() == 0) + return Package::getDescription(); + else + return m_descr; +} + +//______________________________________________________________________________ +OUString BackendImpl::PackageImpl::getLicenseText() throw (RuntimeException) +{ + return Package::getDescription(); +} + +//______________________________________________________________________________ +BackendImpl::PackageImpl::PackageImpl( + ::rtl::Reference<BackendImpl> const & myBackend, + OUString const & url, OUString const & libType, bool bRemoved, + OUString const & identifier) + : Package( myBackend.get(), url, OUString(), OUString(), + myBackend->m_xTypeInfo, bRemoved, identifier), + m_descr(libType) +{ + initPackageHandler(); + + sal_Int32 segmEnd = url.getLength(); + if (url.getLength() > 0 && url[ url.getLength() - 1 ] == '/') + --segmEnd; + sal_Int32 segmStart = (url.lastIndexOf( '/', segmEnd ) + 1); + if (segmStart < 0) + segmStart = 0; + // name and display name default the same: + m_displayName = ::rtl::Uri::decode( + url.copy( segmStart, segmEnd - segmStart ), + rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + m_name = m_displayName; + + dp_misc::TRACE(OUSTR("PakageImpl displayName is ") + m_displayName); +} + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : PackageRegistryBackend( args, xComponentContext ), + m_xTypeInfo( new Package::TypeInfo( + OUSTR("application/vnd.sun.star.framework-script"), + OUString() /* no file filter */, + OUSTR("Scripting Framework Script Library"), + RID_IMG_SCRIPTLIB ) ) +{ + if (! transientMode()) + { + } +} + + + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return Sequence< Reference<deployment::XPackageTypeInfo> >(&m_xTypeInfo, 1); +} + +void BackendImpl::packageRemoved(OUString const & /*url*/, OUString const & /*mediaType*/) + throw (deployment::DeploymentException, + uno::RuntimeException) +{ +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ) +{ + OUString mediaType( mediaType_ ); + if (mediaType.getLength() == 0) + { + // detect media-type: + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, url, xCmdEnv ) && + ucbContent.isFolder()) + { + // probe for parcel-descriptor.xml: + if (create_ucb_content( + 0, makeURL( url, OUSTR("parcel-descriptor.xml") ), + xCmdEnv, false /* no throw */ )) + { + mediaType = OUSTR("application/vnd.sun.star.framework-script"); + } + } + if (mediaType.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.framework-script")) + { + OUString lang = OUString(RTL_CONSTASCII_USTRINGPARAM("Script")); + OUString sParcelDescURL = makeURL( + url, OUSTR("parcel-descriptor.xml") ); + + ::ucbhelper::Content ucb_content; + + if (create_ucb_content( &ucb_content, sParcelDescURL, + xCmdEnv, false /* no throw */ )) + { + ParcelDescDocHandler* pHandler = + new ParcelDescDocHandler(); + Reference< xml::sax::XDocumentHandler > + xDocHandler = pHandler; + + Reference<XComponentContext> + xContext( getComponentContext() ); + + Reference< xml::sax::XParser > xParser( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.sax.Parser"), xContext ), + UNO_QUERY_THROW ); + + xParser->setDocumentHandler( xDocHandler ); + xml::sax::InputSource source; + source.aInputStream = ucb_content.openStream(); + source.sSystemId = ucb_content.getURL(); + xParser->parseStream( source ); + + if ( pHandler->isParsed() ) + { + lang = pHandler->getParcelLanguage(); + } + } + + OUString sfwkLibType = getResourceString( RID_STR_SFWK_LIB ); + // replace %MACRONAME placeholder with language name + OUString MACRONAME( OUSTR("%MACROLANG" ) ); + sal_Int32 startOfReplace = sfwkLibType.indexOf( MACRONAME ); + sal_Int32 charsToReplace = MACRONAME.getLength(); + sfwkLibType = sfwkLibType.replaceAt( startOfReplace, charsToReplace, lang ); + dp_misc::TRACE("******************************\n"); + dp_misc::TRACE(OUSTR(" BackEnd detected lang = ") + lang + OUSTR("\n")); + dp_misc::TRACE(OUSTR(" for url ") + sParcelDescURL + OUSTR("\n") ); + dp_misc::TRACE("******************************\n"); + return new PackageImpl( this, url, sfwkLibType, bRemoved, identifier); + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + + +void BackendImpl::PackageImpl:: initPackageHandler() +{ + if (m_xNameCntrPkgHandler.is()) + return; + + BackendImpl * that = getMyBackend(); + Any aContext; + + if ( that->m_eContext == CONTEXT_USER ) + { + aContext <<= OUSTR("user"); + } + else if ( that->m_eContext == CONTEXT_SHARED ) + { + aContext <<= OUSTR("share"); + } + else if ( that->m_eContext == CONTEXT_BUNDLED ) + { + aContext <<= OUSTR("bundled"); + } + else if ( that->m_eContext == CONTEXT_BUNDLED_PREREG ) + { + aContext <<= OUSTR("bundled_prereg"); + } + + else + { + OSL_ASSERT( 0 ); + // NOT supported at the momemtn // TODO + } + + Reference< provider::XScriptProviderFactory > xFac( + that->getComponentContext()->getValueByName( + OUSTR( "/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory") ), UNO_QUERY ); + + if ( xFac.is() ) + { + Reference< container::XNameContainer > xName( xFac->createScriptProvider( aContext ), UNO_QUERY ); + if ( xName.is() ) + { + m_xNameCntrPkgHandler.set( xName ); + } + } + // TODO what happens if above fails?? +} + +// Package +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::PackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true /* IsPresent */, + beans::Ambiguous<sal_Bool>( + m_xNameCntrPkgHandler.is() && m_xNameCntrPkgHandler->hasByName( + m_url ), + false /* IsAmbiguous */ ) ); +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool /* startup */, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + if ( !m_xNameCntrPkgHandler.is() ) + { + dp_misc::TRACE("no package handler!!!!\n"); + throw RuntimeException( OUSTR("No package Handler " ), + Reference< XInterface >() ); + } + + if (doRegisterPackage) + { + // will throw if it fails + m_xNameCntrPkgHandler->insertByName( m_url, makeAny( Reference< XPackage >(this) ) ); + + } + else // revokePackage() + { + m_xNameCntrPkgHandler->removeByName( m_url ); + } +} + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + "com.sun.star.comp.deployment.sfwk.PackageRegistryBackend", + BACKEND_SERVICE_NAME ); + +} // namespace sfwk +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/sfwk/dp_sfwk.hrc b/desktop/source/deployment/registry/sfwk/dp_sfwk.hrc new file mode 100755 index 000000000000..0eb619e839e3 --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/dp_sfwk.hrc @@ -0,0 +1,35 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_SFWK_HRC +#define INCLUDED_DP_SFWK_HRC + +#include "deployment.hrc" + +#define RID_STR_SFWK_LIB (RID_DEPLOYMENT_SCRIPT_START+20) + +#endif diff --git a/desktop/source/deployment/registry/sfwk/dp_sfwk.src b/desktop/source/deployment/registry/sfwk/dp_sfwk.src new file mode 100644 index 000000000000..c8d37ce067ac --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/dp_sfwk.src @@ -0,0 +1,35 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_sfwk.hrc" + +String RID_STR_SFWK_LIB +{ + Text [ en-US ] = "%MACROLANG Library"; +}; + + diff --git a/desktop/source/deployment/registry/sfwk/makefile.mk b/desktop/source/deployment/registry/sfwk/makefile.mk new file mode 100755 index 000000000000..a052296d5c21 --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_registry_sfwk +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk +SRS1NAME = $(TARGET) + +SRC1FILES = \ + dp_sfwk.src + +INCPRE += ..$/..$/inc + +SLOFILES = \ + $(SLO)$/dp_parceldesc.obj \ + $(SLO)$/dp_sfwk.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/target.pmk b/desktop/source/deployment/target.pmk new file mode 100755 index 000000000000..82b41766b253 --- /dev/null +++ b/desktop/source/deployment/target.pmk @@ -0,0 +1,36 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +.IF "$(debug)" != "" + +# MSVC: no inlining +.IF "$(COM)" == "MSC" +CFLAGS += /Ob0 +.ENDIF + +.ENDIF + diff --git a/desktop/source/deployment/unopkg/makefile.mk b/desktop/source/deployment/unopkg/makefile.mk new file mode 100755 index 000000000000..64fe173f4597 --- /dev/null +++ b/desktop/source/deployment/unopkg/makefile.mk @@ -0,0 +1,44 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = deployment_unopkg +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +SRS1NAME = $(TARGET) +SRC1FILES = \ + unopkg.src + +SLOFILES = + +.INCLUDE : ..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/unopkg/unopkg.src b/desktop/source/deployment/unopkg/unopkg.src new file mode 100644 index 000000000000..dc204e265ec6 --- /dev/null +++ b/desktop/source/deployment/unopkg/unopkg.src @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "deployment.hrc" + + +String RID_STR_UNOPKG_ACCEPT_LIC_1 +{ + Text [ en-US ] = "Extension Software License Agreement of $NAME:"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_2 +{ + Text [ en-US ] = "Read the complete License Agreement displayed above. " + "Accept the License Agreement by typing \"yes\" on the console " + "then press the Return key. Type \"no\" to decline and to abort the " + "extension setup."; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_3 +{ + Text [ en-US ] = "[Enter \"yes\" or \"no\"]:"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_4 +{ + Text [ en-US ] = "Your input was not correct. Please enter \"yes\" or \"no\":"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_YES +{ + Text [ en-US ] = "YES"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_Y +{ + Text [ en-US ] = "Y"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_NO +{ + Text [ en-US ] = "NO"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_N +{ + Text [ en-US ] = "N"; +}; + +String RID_STR_CONCURRENTINSTANCE +{ + Text [ en-US ] = "unopkg cannot be started. The lock file indicates it as already running. " + "If this does not apply, delete the lock file at:"; +}; + +String RID_STR_UNOPKG_ERROR +{ + Text [ en-US ] = "ERROR: "; +}; + diff --git a/desktop/source/inc/exithelper.hxx b/desktop/source/inc/exithelper.hxx new file mode 100644 index 000000000000..25cdc3e1b722 --- /dev/null +++ b/desktop/source/inc/exithelper.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_EXITHELPER_HXX_ +#define _DESKTOP_EXITHELPER_HXX_ + +namespace desktop +{ + +//============================================================================= +/** @short provide helper functions to handle a abnormal exit + and contain a list of all "well known" exit codes. + */ +class ExitHelper +{ + //------------------------------------------------------------------------- + // const + public: + + //--------------------------------------------------------------------- + /** @short list of all well known exit codes. + + @descr Its not allowed to use exit codes hard coded + inside office. All places must use these list to + be synchron. + */ + enum EExitCodes + { + /// e.g. used to force showing of the command line help + E_NO_ERROR = 0, + /// pipe was detected - second office must terminate itself + E_SECOND_OFFICE = 1, + /// an uno exception was catched during startup + E_FATAL_ERROR = 333, // Only the low 8 bits are significant 333 % 256 = 77 + /// user force automatic restart after crash + E_CRASH_WITH_RESTART = 79, + /// the office restarts itself + E_NORMAL_RESTART = 81 + }; +}; + +} // namespace desktop + +#endif // #ifndef _DESKTOP_EXITHELPER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/inc/helpid.hrc b/desktop/source/inc/helpid.hrc new file mode 100755 index 000000000000..d96b12196342 --- /dev/null +++ b/desktop/source/inc/helpid.hrc @@ -0,0 +1,67 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DESKTOP_HELPID_HRC +#define INCLUDED_DESKTOP_HELPID_HRC + +#define HID_PACKAGE_MANAGER "DESKTOP_HID_PACKAGE_MANAGER" +#define HID_PACKAGE_MANAGER_TREELISTBOX "DESKTOP_HID_PACKAGE_MANAGER_TREELISTBOX" +#define HID_PACKAGE_MANAGER_PROGRESS "DESKTOP_HID_PACKAGE_MANAGER_PROGRESS" +#define HID_PACKAGE_MANAGER_PROGRESS_CANCEL "DESKTOP_HID_PACKAGE_MANAGER_PROGRESS_CANCEL" +#define HID_PACKAGE_MANAGER_MENU_ITEM "DESKTOP_HID_PACKAGE_MANAGER_MENU_ITEM" + +#define HID_FIRSTSTART_DIALOG "DESKTOP_HID_FIRSTSTART_DIALOG" +#define HID_FIRSTSTART_WELCOME "DESKTOP_HID_FIRSTSTART_WELCOME" +#define HID_FIRSTSTART_LICENSE "DESKTOP_HID_FIRSTSTART_LICENSE" +#define HID_FIRSTSTART_MIGRATION "DESKTOP_HID_FIRSTSTART_MIGRATION" +#define HID_FIRSTSTART_REGISTRATION "DESKTOP_HID_FIRSTSTART_REGISTRATION" +#define HID_FIRSTSTART_USER "DESKTOP_HID_FIRSTSTART_USER" +#define HID_FIRSTSTART_PREV "DESKTOP_HID_FIRSTSTART_PREV" +#define HID_FIRSTSTART_NEXT "DESKTOP_HID_FIRSTSTART_NEXT" +#define HID_FIRSTSTART_CANCEL "DESKTOP_HID_FIRSTSTART_CANCEL" +#define HID_FIRSTSTART_FINISH "DESKTOP_HID_FIRSTSTART_FINISH" +#define UID_FIRSTSTART_HELP "DESKTOP_UID_FIRSTSTART_HELP" +#define UID_BTN_LICENSE_ACCEPT "DESKTOP_UID_BTN_LICENSE_ACCEPT" +#define HID_FIRSTSTART_UPDATE_CHECK "DESKTOP_HID_FIRSTSTART_UPDATE_CHECK" +#define HID_DEPLOYMENT_GUI_UPDATE "DESKTOP_HID_DEPLOYMENT_GUI_UPDATE" +#define HID_DEPLOYMENT_GUI_UPDATEINSTALL "DESKTOP_HID_DEPLOYMENT_GUI_UPDATEINSTALL" +#define HID_DEPLOYMENT_GUI_UPDATE_PUBLISHER "DESKTOP_HID_DEPLOYMENT_GUI_UPDATE_PUBLISHER" +#define HID_DEPLOYMENT_GUI_UPDATE_RELEASENOTES "DESKTOP_HID_DEPLOYMENT_GUI_UPDATE_RELEASENOTES" +#define HID_DEPLOYMENT_GUI_UPDATE_AVAILABLE_UPDATES "DESKTOP_HID_DEPLOYMENT_GUI_UPDATE_AVAILABLE_UPDATES" + +#define HID_EXTENSION_MANAGER_LISTBOX "DESKTOP_HID_EXTENSION_MANAGER_LISTBOX" +#define HID_EXTENSION_MANAGER_LISTBOX_OPTIONS "DESKTOP_HID_EXTENSION_MANAGER_LISTBOX_OPTIONS" +#define HID_EXTENSION_MANAGER_LISTBOX_ENABLE "DESKTOP_HID_EXTENSION_MANAGER_LISTBOX_ENABLE" +#define HID_EXTENSION_MANAGER_LISTBOX_DISABLE "DESKTOP_HID_EXTENSION_MANAGER_LISTBOX_DISABLE" +#define HID_EXTENSION_MANAGER_LISTBOX_REMOVE "DESKTOP_HID_EXTENSION_MANAGER_LISTBOX_REMOVE" + +#define HID_EXTENSION_DEPENDENCIES "DESKTOP_HID_EXTENSION_DEPENDENCIES" + +#define HID_PACKAGE_MANAGER_UPD_REQ "DESKTOP_HID_PACKAGE_MANAGER_UPD_REQ" + +#endif + diff --git a/desktop/source/migration/makefile.mk b/desktop/source/migration/makefile.mk new file mode 100755 index 000000000000..b20b4c57974f --- /dev/null +++ b/desktop/source/migration/makefile.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=mig +AUTOSEG=true +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +RSCEXTINC=..$/app + +# hacky - is no define +CDEFS+=-I..$/app +CDEFS+=-I$(PRJ)/inc + +SLOFILES = \ + $(SLO)$/migration.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/source/migration/migration.cxx b/desktop/source/migration/migration.cxx new file mode 100644 index 000000000000..465993c70e1c --- /dev/null +++ b/desktop/source/migration/migration.cxx @@ -0,0 +1,1381 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <map> +#include <new> +#include <set> + +#include "migration.hxx" +#include "migration_impl.hxx" + +#include <unotools/textsearch.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> +#include <unotools/bootstrap.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/uri.hxx> +#include <tools/config.hxx> +#include <i18npool/lang.h> +#include <tools/urlobj.hxx> +#include <osl/file.hxx> +#include <osl/mutex.hxx> +#include <ucbhelper/content.hxx> +#include <osl/security.hxx> +#include <unotools/configmgr.hxx> + +#include <com/sun/star/configuration/Update.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/util/XRefreshable.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/util/XStringSubstitution.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/ui/XUIConfiguration.hpp> +#include <com/sun/star/ui/XUIConfigurationStorage.hpp> +#include <com/sun/star/ui/XUIConfigurationPersistence.hpp> + +using namespace osl; +using namespace std; +using namespace com::sun::star::task; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; +using namespace com::sun::star::container; +using com::sun::star::uno::Exception; +using namespace com::sun::star; + +using ::rtl::OUString; +using ::rtl::OString; + +namespace desktop { + +static const ::rtl::OUString ITEM_DESCRIPTOR_COMMANDURL(RTL_CONSTASCII_USTRINGPARAM("CommandURL")); +static const ::rtl::OUString ITEM_DESCRIPTOR_CONTAINER(RTL_CONSTASCII_USTRINGPARAM("ItemDescriptorContainer")); +static const ::rtl::OUString ITEM_DESCRIPTOR_LABEL(RTL_CONSTASCII_USTRINGPARAM("Label")); + +static const ::rtl::OUString MENU_SEPERATOR(RTL_CONSTASCII_USTRINGPARAM(" | ")); +static const ::rtl::OUString MENU_SUBMENU(RTL_CONSTASCII_USTRINGPARAM("...")); +static const ::rtl::OUString MIGRATION_STAMP_NAME(RTL_CONSTASCII_USTRINGPARAM("/MIGRATED")); + + +static const char XDG_CONFIG_PART[] = "/.config"; + +::rtl::OUString retrieveLabelFromCommand(const ::rtl::OUString& sCommand, const ::rtl::OUString& sModuleIdentifier) +{ + ::rtl::OUString sLabel; + + uno::Reference< container::XNameAccess > xUICommands; + uno::Reference< container::XNameAccess > xNameAccess( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.UICommandDescription")) ), uno::UNO_QUERY ); + if ( xNameAccess.is() ) + { + uno::Any a = xNameAccess->getByName( sModuleIdentifier ); + a >>= xUICommands; + } + if (xUICommands.is()) + { + if ( sCommand.getLength() > 0 ) + { + rtl::OUString aStr; + ::uno::Sequence< beans::PropertyValue > aPropSeq; + try + { + uno::Any a( xUICommands->getByName( sCommand )); + if ( a >>= aPropSeq ) + { + for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Label" ) )) + { + aPropSeq[i].Value >>= aStr; + break; + } + } + } + + sLabel = aStr; + } + catch (const container::NoSuchElementException&) + { + sLabel = sCommand; + sal_Int32 nIndex = sLabel.indexOf(':'); + if (nIndex>=0 && nIndex <= sLabel.getLength()-1) + sLabel = sLabel.copy(nIndex+1); + } + + } + } + + return sLabel; +} + +::rtl::OUString mapModuleShortNameToIdentifier(const ::rtl::OUString& sShortName) +{ + ::rtl::OUString sIdentifier; + + if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StartModule")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("swriter")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("scalc")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SpreadsheetDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdraw")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("simpress")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.PresentationDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("smath")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.formula.FormulaProperties")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("schart")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.chart2.ChartDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BasicIDE")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.BasicIDE")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("dbapp")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.OfficeDatabaseDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sglobal")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.GlobalDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sweb")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.WebDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("swxform")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xforms.XMLFormDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sbibliography")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Bibliography")); + + return sIdentifier; +} + +bool MigrationImpl::alreadyMigrated() +{ + rtl::OUString aStr = m_aInfo.userdata + MIGRATION_STAMP_NAME; + File aFile(aStr); + // create migration stamp, and/or check its existence + bool bRet = aFile.open (osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock) == FileBase::E_EXIST; + OSL_TRACE( "File '%s' exists? %d\n", + rtl::OUStringToOString(aStr, RTL_TEXTENCODING_ASCII_US).getStr(), + bRet ); + return bRet; +} + +bool MigrationImpl::initializeMigration() +{ + bool bRet = false; + + if (!checkMigrationCompleted()) { + readAvailableMigrations(m_vMigrationsAvailable); + sal_Int32 nIndex = findPreferedMigrationProcess(m_vMigrationsAvailable); + // m_aInfo is now set to the preferred migration source + if ( nIndex >= 0 ) { + if (alreadyMigrated()) + return false; + m_vrMigrations = readMigrationSteps(m_vMigrationsAvailable[nIndex].name); + } + + bRet = m_aInfo.userdata.getLength() > 0; + } + + OSL_TRACE( "Migration %s\n", bRet ? "needed" : "not required" ); + + return bRet; +} + +void Migration::migrateSettingsIfNecessary() +{ + MigrationImpl aImpl( comphelper::getProcessServiceFactory() ); + + if (! aImpl.initializeMigration() ) + return; + + sal_Bool bResult = sal_False; + try + { + bResult = aImpl.doMigration(); + } + catch (const Exception& e) + { + OString aMsg("doMigration() exception: "); + aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(aMsg.getStr()); + } + OSL_ENSURE(bResult, "Migration has not been successfull"); + (void)bResult; +} + +MigrationImpl::MigrationImpl(const uno::Reference< XMultiServiceFactory >& xFactory) + : m_vrVersions(new strings_v) + , m_xFactory(xFactory) +{ +} + +MigrationImpl::~MigrationImpl() +{ +} + +// The main entry point for migrating settings +sal_Bool MigrationImpl::doMigration() +{ + // compile file list for migration + m_vrFileList = compileFileList(); + + sal_Bool result = sal_False; + try + { + NewVersionUIInfo aNewVersionUIInfo; + ::std::vector< MigrationModuleInfo > vModulesInfo = dectectUIChangesForAllModules(); + aNewVersionUIInfo.init(vModulesInfo); + + copyFiles(); + + const ::rtl::OUString sMenubarResourceURL(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar")); + const ::rtl::OUString sToolbarResourcePre(RTL_CONSTASCII_USTRINGPARAM("private:resource/toolbar/")); + for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i) + { + ::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName); + if (sModuleIdentifier.getLength()==0) + continue; + + uno::Sequence< uno::Any > lArgs(2); + ::rtl::OUString aOldCfgDataPath = m_aInfo.userdata + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/user/config/soffice.cfg/modules/")); + lArgs[0] <<= aOldCfgDataPath + vModulesInfo[i].sModuleShortName; + lArgs[1] <<= embed::ElementModes::READ; + + uno::Reference< lang::XSingleServiceFactory > xStorageFactory(m_xFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.FileSystemStorageFactory"))), uno::UNO_QUERY); + uno::Reference< embed::XStorage > xModules; + + xModules = uno::Reference< embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY); + uno::Reference< ui::XUIConfigurationManager > xOldCfgManager( m_xFactory->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.UIConfigurationManager"))), uno::UNO_QUERY ); + uno::Reference< ui::XUIConfigurationStorage > xOldCfgStorage( xOldCfgManager, uno::UNO_QUERY ); + uno::Reference< ui::XUIConfigurationPersistence > xOldCfgPersistence( xOldCfgManager, uno::UNO_QUERY ); + + if ( xOldCfgStorage.is() && xOldCfgPersistence.is() && xModules.is() ) + { + xOldCfgStorage->setStorage( xModules ); + xOldCfgPersistence->reload(); + } + + uno::Reference< ui::XUIConfigurationManager > xCfgManager = aNewVersionUIInfo.getConfigManager(vModulesInfo[i].sModuleShortName); + + if (vModulesInfo[i].bHasMenubar) + { + uno::Reference< container::XIndexContainer > xOldVersionMenuSettings = uno::Reference< container::XIndexContainer >(xOldCfgManager->getSettings(sMenubarResourceURL, sal_True), uno::UNO_QUERY); + uno::Reference< container::XIndexContainer > xNewVersionMenuSettings = aNewVersionUIInfo.getNewMenubarSettings(vModulesInfo[i].sModuleShortName); + ::rtl::OUString sParent; + compareOldAndNewConfig(sParent, xOldVersionMenuSettings, xNewVersionMenuSettings, sMenubarResourceURL); + mergeOldToNewVersion(xCfgManager, xNewVersionMenuSettings, sModuleIdentifier, sMenubarResourceURL); + } + + sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size(); + if (nToolbars >0) + { + for (sal_Int32 j=0; j<nToolbars; ++j) + { + ::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j]; + ::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName; + + uno::Reference< container::XIndexContainer > xOldVersionToolbarSettings = uno::Reference< container::XIndexContainer >(xOldCfgManager->getSettings(sToolbarResourceURL, sal_True), uno::UNO_QUERY); + uno::Reference< container::XIndexContainer > xNewVersionToolbarSettings = aNewVersionUIInfo.getNewToolbarSettings(vModulesInfo[i].sModuleShortName, sToolbarName); + ::rtl::OUString sParent; + compareOldAndNewConfig(sParent, xOldVersionToolbarSettings, xNewVersionToolbarSettings, sToolbarResourceURL); + mergeOldToNewVersion(xCfgManager, xNewVersionToolbarSettings, sModuleIdentifier, sToolbarResourceURL); + } + } + + m_aOldVersionItemsHashMap.clear(); + m_aNewVersionItemsHashMap.clear(); + } + + // execute the migration items from Setup.xcu + copyConfig(); + + // execute custom migration services from Setup.xcu + // and refresh the cache + runServices(); + refresh(); + + result = sal_True; + } + catch (...) + { + OString aMsg("An unexpected exception was thrown during migration"); + aMsg += "\nOldVersion: " + OUStringToOString(m_aInfo.productname, RTL_TEXTENCODING_ASCII_US); + aMsg += "\nDataPath : " + OUStringToOString(m_aInfo.userdata, RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(aMsg.getStr()); + } + + // prevent running the migration multiple times + setMigrationCompleted(); + return result; +} + +void MigrationImpl::refresh() +{ + uno::Reference< XRefreshable > xRefresh(m_xFactory->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider"))), uno::UNO_QUERY); + if (xRefresh.is()) + xRefresh->refresh(); + else + OSL_FAIL("could not get XRefresh interface from default config provider. No refresh done."); + +} + +void MigrationImpl::setMigrationCompleted() +{ + try + { + uno::Reference< XPropertySet > aPropertySet(getConfigAccess("org.openoffice.Setup/Office", true), uno::UNO_QUERY_THROW); + aPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("MigrationCompleted")), uno::makeAny(sal_True)); + uno::Reference< XChangesBatch >(aPropertySet, uno::UNO_QUERY_THROW)->commitChanges(); + } + catch (...) + { + // fail silently + } +} + +bool MigrationImpl::checkMigrationCompleted() +{ + sal_Bool bMigrationCompleted = sal_False; + try { + uno::Reference< XPropertySet > aPropertySet( + getConfigAccess("org.openoffice.Setup/Office"), uno::UNO_QUERY_THROW); + aPropertySet->getPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("MigrationCompleted"))) >>= bMigrationCompleted; + + if( !bMigrationCompleted && getenv("SAL_DISABLE_USERMIGRATION" ) ) + { + // migration prevented - fake it's success + setMigrationCompleted(); + bMigrationCompleted = sal_True; + } + } + catch (const Exception&) + { + // just return false... + } + OSL_TRACE( "Migration %s", bMigrationCompleted ? "already completed" : "not done" ); + + return bMigrationCompleted; +} + +static void insertSorted(migrations_available& rAvailableMigrations, supported_migration& aSupportedMigration) +{ + bool bInserted( false ); + migrations_available::iterator pIter = rAvailableMigrations.begin(); + while ( !bInserted && pIter != rAvailableMigrations.end()) + { + if ( pIter->nPriority < aSupportedMigration.nPriority ) + { + rAvailableMigrations.insert(pIter, aSupportedMigration ); + bInserted = true; + break; // i111193: insert invalidates iterator! + } + ++pIter; + } + if ( !bInserted ) + rAvailableMigrations.push_back( aSupportedMigration ); +} + +bool MigrationImpl::readAvailableMigrations(migrations_available& rAvailableMigrations) +{ + // get supported version names + uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW); + uno::Sequence< OUString > seqSupportedVersions = aMigrationAccess->getElementNames(); + + const OUString aVersionIdentifiers( RTL_CONSTASCII_USTRINGPARAM( "VersionIdentifiers" )); + const OUString aPriorityIdentifier( RTL_CONSTASCII_USTRINGPARAM( "Priority" )); + + for (sal_Int32 i=0; i<seqSupportedVersions.getLength(); i++) + { + sal_Int32 nPriority( 0 ); + uno::Sequence< OUString > seqVersions; + uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(seqSupportedVersions[i]), uno::UNO_QUERY_THROW ); + xMigrationData->getByName( aVersionIdentifiers ) >>= seqVersions; + xMigrationData->getByName( aPriorityIdentifier ) >>= nPriority; + + supported_migration aSupportedMigration; + aSupportedMigration.name = seqSupportedVersions[i]; + aSupportedMigration.nPriority = nPriority; + for (sal_Int32 j=0; j<seqVersions.getLength(); j++) + aSupportedMigration.supported_versions.push_back(seqVersions[j].trim()); + insertSorted( rAvailableMigrations, aSupportedMigration ); + OSL_TRACE( " available migration '%s'\n", + rtl::OUStringToOString( aSupportedMigration.name, RTL_TEXTENCODING_ASCII_US ).getStr() ); + } + + return true; +} + +migrations_vr MigrationImpl::readMigrationSteps(const ::rtl::OUString& rMigrationName) +{ + // get migration access + uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW); + uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(rMigrationName), uno::UNO_QUERY_THROW ); + + // get migration description from from org.openoffice.Setup/Migration + // and build vector of migration steps + OUString aMigrationSteps( RTL_CONSTASCII_USTRINGPARAM( "MigrationSteps" )); + uno::Reference< XNameAccess > theNameAccess(xMigrationData->getByName(aMigrationSteps), uno::UNO_QUERY_THROW); + uno::Sequence< OUString > seqMigrations = theNameAccess->getElementNames(); + uno::Reference< XNameAccess > tmpAccess; + uno::Reference< XNameAccess > tmpAccess2; + uno::Sequence< OUString > tmpSeq; + migrations_vr vrMigrations(new migrations_v); + for (sal_Int32 i = 0; i < seqMigrations.getLength(); i++) + { + // get current migration step + theNameAccess->getByName(seqMigrations[i]) >>= tmpAccess; + migration_step tmpStep; + tmpStep.name = seqMigrations[i]; + + // read included files from current step description + ::rtl::OUString aSeqEntry; + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IncludedFiles"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + { + aSeqEntry = tmpSeq[j]; + tmpStep.includeFiles.push_back(aSeqEntry); + } + } + + // exluded files... + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("ExcludedFiles"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + tmpStep.excludeFiles.push_back(tmpSeq[j]); + } + + // included nodes... + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IncludedNodes"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + tmpStep.includeConfig.push_back(tmpSeq[j]); + } + + // excluded nodes... + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("ExcludedNodes"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + tmpStep.excludeConfig.push_back(tmpSeq[j]); + } + + // included extensions... + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IncludedExtensions"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + tmpStep.includeExtensions.push_back(tmpSeq[j]); + } + + // excluded extensions... + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("ExcludedExtensions"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + { + aSeqEntry = tmpSeq[j]; + tmpStep.excludeExtensions.push_back(aSeqEntry); + } + } + + // generic service + tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("MigrationService"))) >>= tmpStep.service; + + vrMigrations->push_back(tmpStep); + } + return vrMigrations; +} + +static FileBase::RC _checkAndCreateDirectory(INetURLObject& dirURL) +{ + FileBase::RC result = Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI)); + if (result == FileBase::E_NOENT) + { + INetURLObject baseURL(dirURL); + baseURL.removeSegment(); + _checkAndCreateDirectory(baseURL); + return Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI)); + } else + return result; +} + +install_info MigrationImpl::findInstallation(const strings_v& rVersions) +{ + rtl::OUString aProductName; + uno::Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ); + aRet >>= aProductName; + aProductName = aProductName.toAsciiLowerCase(); + + install_info aInfo; + strings_v::const_iterator i_ver = rVersions.begin(); + while (i_ver != rVersions.end()) + { + ::rtl::OUString aVersion, aProfileName; + sal_Int32 nSeparatorIndex = (*i_ver).indexOf('='); + if ( nSeparatorIndex != -1 ) + { + aVersion = (*i_ver).copy( 0, nSeparatorIndex ); + aProfileName = (*i_ver).copy( nSeparatorIndex+1 ); + } + + if ( aVersion.getLength() && aProfileName.getLength() && + ( !aInfo.userdata.getLength() || !aProfileName.toAsciiLowerCase().compareTo( aProductName, aProductName.getLength() ) ) + ) + { + ::rtl::OUString aUserInst; + osl::Security().getConfigDir( aUserInst ); +#if defined UNX && ! defined MACOSX + const char* pXDGCfgHome = getenv("XDG_CONFIG_HOME"); + // cater for XDG_CONFIG_HOME change + // If XDG_CONFIG_HOME is set then we; + // assume the user knows what they are doing ( room for improvement here, we could + // of course search the default config dir etc. also - but this is more complex, + // we would need to weigh results from the current config dir against matches in + // the 'old' config dir etc. ) - currently we just use the returned config dir. + // If XDG_CONFIG_HOME is NOT set; + // assume then we should now using the default $HOME/,config config location for + // our user profiles, however *all* previous libreoffice and openoffice.org + // configurations will be in the 'old' config directory and that's where we need + // to search - we convert the returned config dir to the 'old' dir + if ( !pXDGCfgHome && aUserInst.endsWithAsciiL( XDG_CONFIG_PART, sizeof( XDG_CONFIG_PART ) - 1 ) ) + aUserInst = aUserInst.copy( 0, aUserInst.getLength() - sizeof( XDG_CONFIG_PART ) + 2 ); // remove trailing '.config' ( but leave the terminating '/' ) +#endif + if ( aUserInst.getLength() && aUserInst[ aUserInst.getLength()-1 ] != '/' ) + aUserInst += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")); +#if defined UNX && ! defined MACOSX + // tribute to whoever had the "great" idea to use different names on Windows and Unix + aUserInst += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".")); +#endif + aUserInst += aProfileName; + try + { + INetURLObject aObj(aUserInst); + ::ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment > () ); + aCnt.isDocument(); + aInfo.userdata = aObj.GetMainURL( INetURLObject::NO_DECODE ); + aInfo.productname = aVersion; + } + catch (const uno::Exception&) + { + } + } + ++i_ver; + } + + return aInfo; +} + +sal_Int32 MigrationImpl::findPreferedMigrationProcess(const migrations_available& rAvailableMigrations) +{ + sal_Int32 nIndex( -1 ); + sal_Int32 i( 0 ); + + migrations_available::const_iterator rIter = rAvailableMigrations.begin(); + while ( rIter != rAvailableMigrations.end() ) + { + install_info aInstallInfo = findInstallation(rIter->supported_versions); + if (aInstallInfo.productname.getLength() > 0 ) + { + m_aInfo = aInstallInfo; + nIndex = i; + break; + } + ++i; + ++rIter; + } + + OSL_TRACE( " preferred migration is from product '%s'\n", + rtl::OUStringToOString( m_aInfo.productname, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( " and settings directory '%s'\n", + rtl::OUStringToOString( m_aInfo.userdata, RTL_TEXTENCODING_ASCII_US ).getStr() ); + + return nIndex; +} + +strings_vr MigrationImpl::applyPatterns(const strings_v& vSet, const strings_v& vPatterns) const +{ + using namespace utl; + strings_vr vrResult(new strings_v); + strings_v::const_iterator i_set; + strings_v::const_iterator i_pat = vPatterns.begin(); + while (i_pat != vPatterns.end()) + { + // find matches for this pattern in input set + // and copy them to the result + SearchParam param(*i_pat, SearchParam::SRCH_REGEXP); + TextSearch ts(param, LANGUAGE_DONTKNOW); + i_set = vSet.begin(); + xub_StrLen start = 0; + xub_StrLen end = 0; + while (i_set != vSet.end()) + { + end = (xub_StrLen)(i_set->getLength()); + if (ts.SearchFrwrd(*i_set, &start, &end)) + vrResult->push_back(*i_set); + ++i_set; + } + ++i_pat; + } + return vrResult; +} + +strings_vr MigrationImpl::getAllFiles(const OUString& baseURL) const +{ + using namespace osl; + strings_vr vrResult(new strings_v); + + // get sub dirs + Directory dir(baseURL); + if (dir.open() == FileBase::E_None) + { + strings_v vSubDirs; + strings_vr vrSubResult; + + // work through directory contents... + DirectoryItem item; + FileStatus fs(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL); + while (dir.getNextItem(item) == FileBase::E_None) + { + if (item.getFileStatus(fs) == FileBase::E_None) + { + if (fs.getFileType() == FileStatus::Directory) + vSubDirs.push_back(fs.getFileURL()); + else + vrResult->push_back(fs.getFileURL()); + } + } + + // recurse subfolders + strings_v::const_iterator i = vSubDirs.begin(); + while (i != vSubDirs.end()) + { + vrSubResult = getAllFiles(*i); + vrResult->insert(vrResult->end(), vrSubResult->begin(), vrSubResult->end()); + ++i; + } + } + return vrResult; +} + +strings_vr MigrationImpl::compileFileList() +{ + + strings_vr vrResult(new strings_v); + strings_vr vrInclude; + strings_vr vrExclude; + strings_vr vrTemp; + + // get a list of all files: + strings_vr vrFiles = getAllFiles(m_aInfo.userdata); + + // get a file list result for each migration step + migrations_v::const_iterator i_migr = m_vrMigrations->begin(); + while (i_migr != m_vrMigrations->end()) + { + vrInclude = applyPatterns(*vrFiles, i_migr->includeFiles); + vrExclude = applyPatterns(*vrFiles, i_migr->excludeFiles); + subtract(*vrInclude, *vrExclude); + vrResult->insert(vrResult->end(), vrInclude->begin(), vrInclude->end()); + ++i_migr; + } + return vrResult; +} + +namespace { + +struct componentParts { + std::set< rtl::OUString > includedPaths; + std::set< rtl::OUString > excludedPaths; +}; + +typedef std::map< rtl::OUString, componentParts > Components; + +bool getComponent(rtl::OUString const & path, rtl::OUString * component) { + OSL_ASSERT(component != 0); + if (path.getLength() == 0 || path[0] != '/') { + OSL_TRACE( + ("configuration migration in/exclude path %s ignored (does not" + " start with slash)"), + rtl::OUStringToOString(path, RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + sal_Int32 i = path.indexOf('/', 1); + *component = i < 0 ? path.copy(1) : path.copy(1, i - 1); + return true; +} + +uno::Sequence< rtl::OUString > setToSeq(std::set< rtl::OUString > const & set) { + std::set< rtl::OUString >::size_type n = set.size(); + if (n > SAL_MAX_INT32) { + throw std::bad_alloc(); + } + uno::Sequence< rtl::OUString > seq(static_cast< sal_Int32 >(n)); + sal_Int32 i = 0; + for (std::set< rtl::OUString >::const_iterator j(set.begin()); + j != set.end(); ++j) + { + seq[i++] = *j; + } + return seq; +} + +} + +void MigrationImpl::copyConfig() { + Components comps; + for (migrations_v::const_iterator i(m_vrMigrations->begin()); + i != m_vrMigrations->end(); ++i) + { + for (strings_v::const_iterator j(i->includeConfig.begin()); + j != i->includeConfig.end(); ++j) + { + rtl::OUString comp; + if (getComponent(*j, &comp)) { + comps[comp].includedPaths.insert(*j); + } + } + for (strings_v::const_iterator j(i->excludeConfig.begin()); + j != i->excludeConfig.end(); ++j) + { + rtl::OUString comp; + if (getComponent(*j, &comp)) { + comps[comp].excludedPaths.insert(*j); + } + } + } + for (Components::const_iterator i(comps.begin()); i != comps.end(); ++i) { + if (!i->second.includedPaths.empty()) { + rtl::OUStringBuffer buf(m_aInfo.userdata); + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/user/registry/data")); + sal_Int32 n = 0; + do { + rtl::OUString seg(i->first.getToken(0, '.', n)); + rtl::OUString enc( + rtl::Uri::encode( + seg, rtl_UriCharClassPchar, rtl_UriEncodeStrict, + RTL_TEXTENCODING_UTF8)); + if (enc.getLength() == 0 && seg.getLength() != 0) { + OSL_TRACE( + ("configuration migration component %s ignored (cannot" + " be encoded as file path)"), + rtl::OUStringToOString( + i->first, RTL_TEXTENCODING_UTF8).getStr()); + goto next; + } + buf.append(sal_Unicode('/')); + buf.append(enc); + } while (n >= 0); + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(".xcu")); + configuration::Update::get( + comphelper::getProcessComponentContext())-> + insertModificationXcuFile( + buf.makeStringAndClear(), setToSeq(i->second.includedPaths), + setToSeq(i->second.excludedPaths)); + } else { + OSL_TRACE( + ("configuration migration component %s ignored (only excludes," + " no includes)"), + rtl::OUStringToOString( + i->first, RTL_TEXTENCODING_UTF8).getStr()); + } + next:; + } +} + +// removes elements of vector 2 in vector 1 +void MigrationImpl::subtract(strings_v& va, const strings_v& vb_c) const +{ + strings_v vb(vb_c); + // ensure uniqueness of entries + sort(va.begin(), va.end()); + sort(vb.begin(), vb.end()); + unique(va.begin(), va.end()); + unique(vb.begin(), vb.end()); + + strings_v::const_iterator i_ex = vb.begin(); + strings_v::iterator i_in; + strings_v::iterator i_next; + while (i_ex != vb.end()) + { + i_in = va.begin(); + while (i_in != va.end()) + { + if ( *i_in == *i_ex) + { + i_next = i_in+1; + va.erase(i_in); + i_in = i_next; + // we can only find one match since we + // ensured uniquness of the entries. ergo: + break; + } + else + ++i_in; + } + ++i_ex; + } +} + +uno::Reference< XNameAccess > MigrationImpl::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate) +{ + uno::Reference< XNameAccess > xNameAccess; + try{ + OUString sConfigSrvc(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")); + OUString sAccessSrvc; + if (bUpdate) + sAccessSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationUpdateAccess")); + else + sAccessSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")); + + OUString sConfigURL = OUString::createFromAscii(pPath); + + // get configuration provider + uno::Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory(); + uno::Reference< XMultiServiceFactory > theConfigProvider = uno::Reference< XMultiServiceFactory > ( + theMSF->createInstance( sConfigSrvc ),uno::UNO_QUERY_THROW ); + + // access the provider + uno::Sequence< uno::Any > theArgs(1); + theArgs[ 0 ] <<= sConfigURL; + xNameAccess = uno::Reference< XNameAccess > ( + theConfigProvider->createInstanceWithArguments( + sAccessSrvc, theArgs ), uno::UNO_QUERY_THROW ); + } + catch (const com::sun::star::uno::Exception& e) + { + OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(aMsg.getStr()); + } + return xNameAccess; +} + +void MigrationImpl::copyFiles() +{ + strings_v::const_iterator i_file = m_vrFileList->begin(); + OUString localName; + OUString destName; + OUString userInstall; + utl::Bootstrap::PathStatus aStatus; + aStatus = utl::Bootstrap::locateUserInstallation(userInstall); + if (aStatus == utl::Bootstrap::PATH_EXISTS) + { + while (i_file != m_vrFileList->end()) + { + // remove installation prefix from file + localName = i_file->copy(m_aInfo.userdata.getLength()); + destName = userInstall + localName; + INetURLObject aURL(destName); + // check whether destination directory exists + aURL.removeSegment(); + _checkAndCreateDirectory(aURL); + FileBase::RC copyResult = File::copy(*i_file, destName); + if (copyResult != FileBase::E_None) + { + OString msg("Cannot copy "); + msg += OUStringToOString(*i_file, RTL_TEXTENCODING_UTF8) + " to " + + OUStringToOString(destName, RTL_TEXTENCODING_UTF8); + OSL_FAIL(msg.getStr()); + } + ++i_file; + } + } + else + { + OSL_FAIL("copyFiles: UserInstall does not exist"); + } +} + +void MigrationImpl::runServices() +{ + // Build argument array + uno::Sequence< uno::Any > seqArguments(3); + seqArguments[0] = uno::makeAny(NamedValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("Productname")), + uno::makeAny(m_aInfo.productname))); + seqArguments[1] = uno::makeAny(NamedValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("UserData")), + uno::makeAny(m_aInfo.userdata))); + + + // create an instance of every migration service + // and execute the migration job + uno::Reference< XJob > xMigrationJob; + + migrations_v::const_iterator i_mig = m_vrMigrations->begin(); + while (i_mig != m_vrMigrations->end()) + { + if( i_mig->service.getLength() > 0) + { + + try + { + // set black list for extension migration + uno::Sequence< rtl::OUString > seqExtBlackList; + sal_uInt32 nSize = i_mig->excludeExtensions.size(); + if ( nSize > 0 ) + seqExtBlackList = comphelper::arrayToSequence< ::rtl::OUString >( + &i_mig->excludeExtensions[0], nSize ); + seqArguments[2] = uno::makeAny(NamedValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("ExtensionBlackList")), + uno::makeAny( seqExtBlackList ))); + + xMigrationJob = uno::Reference< XJob >(m_xFactory->createInstanceWithArguments( + i_mig->service, seqArguments), uno::UNO_QUERY_THROW); + + xMigrationJob->execute(uno::Sequence< NamedValue >()); + + + } + catch (const Exception& e) + { + OString aMsg("Execution of migration service failed (Exception caught).\nService: "); + aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) + "\nMessage: "; + aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_FAIL(aMsg.getStr()); + } + catch (...) + { + OString aMsg("Execution of migration service failed (Exception caught).\nService: "); + aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) + + "\nNo message available"; + OSL_FAIL(aMsg.getStr()); + } + + } + ++i_mig; + } +} + +::std::vector< MigrationModuleInfo > MigrationImpl::dectectUIChangesForAllModules() const +{ + ::std::vector< MigrationModuleInfo > vModulesInfo; + const ::rtl::OUString MENUBAR(RTL_CONSTASCII_USTRINGPARAM("menubar")); + const ::rtl::OUString TOOLBAR(RTL_CONSTASCII_USTRINGPARAM("toolbar")); + + uno::Sequence< uno::Any > lArgs(2); + lArgs[0] <<= m_aInfo.userdata + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/user/config/soffice.cfg/modules")); + lArgs[1] <<= embed::ElementModes::READ; + + uno::Reference< lang::XSingleServiceFactory > xStorageFactory(m_xFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.FileSystemStorageFactory"))), uno::UNO_QUERY); + uno::Reference< embed::XStorage > xModules; + + xModules = uno::Reference< embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY); + if (!xModules.is()) + return vModulesInfo; + + uno::Reference< container::XNameAccess > xAccess = uno::Reference< container::XNameAccess >(xModules, uno::UNO_QUERY); + uno::Sequence< ::rtl::OUString > lNames = xAccess->getElementNames(); + sal_Int32 nLength = lNames.getLength(); + for (sal_Int32 i=0; i<nLength; ++i) + { + ::rtl::OUString sModuleShortName = lNames[i]; + uno::Reference< embed::XStorage > xModule = xModules->openStorageElement(sModuleShortName, embed::ElementModes::READ); + if (xModule.is()) + { + MigrationModuleInfo aModuleInfo; + + uno::Reference< embed::XStorage > xMenubar = xModule->openStorageElement(MENUBAR, embed::ElementModes::READ); + if (xMenubar.is()) + { + uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xMenubar, uno::UNO_QUERY); + if (xNameAccess->getElementNames().getLength() > 0) + { + aModuleInfo.sModuleShortName = sModuleShortName; + aModuleInfo.bHasMenubar = sal_True; + } + } + + uno::Reference< embed::XStorage > xToolbar = xModule->openStorageElement(TOOLBAR, embed::ElementModes::READ); + if (xToolbar.is()) + { + const ::rtl::OUString RESOURCEURL_CUSTOM_ELEMENT(RTL_CONSTASCII_USTRINGPARAM("custom_")); + sal_Int32 nCustomLen = 7; + + uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xToolbar, uno::UNO_QUERY); + ::uno::Sequence< ::rtl::OUString > lToolbars = xNameAccess->getElementNames(); + for (sal_Int32 j=0; j<lToolbars.getLength(); ++j) + { + ::rtl::OUString sToolbarName = lToolbars[j]; + if (sToolbarName.getLength()>=nCustomLen && + sToolbarName.copy(0, nCustomLen).equals(RESOURCEURL_CUSTOM_ELEMENT)) + continue; + + aModuleInfo.sModuleShortName = sModuleShortName; + sal_Int32 nIndex = sToolbarName.lastIndexOf('.'); + if (nIndex > 0) + { + ::rtl::OUString sExtension(sToolbarName.copy(nIndex)); + ::rtl::OUString sToolbarResourceName(sToolbarName.copy(0, nIndex)); + if (sToolbarResourceName.getLength()>0 && sExtension.equalsAsciiL(".xml", 4)) + aModuleInfo.m_vToolbars.push_back(sToolbarResourceName); + } + } + } + + if (aModuleInfo.sModuleShortName.getLength()>0) + vModulesInfo.push_back(aModuleInfo); + } + } + + return vModulesInfo; +} + +void MigrationImpl::compareOldAndNewConfig(const ::rtl::OUString& sParent, + const uno::Reference< container::XIndexContainer >& xIndexOld, + const uno::Reference< container::XIndexContainer >& xIndexNew, + const ::rtl::OUString& sResourceURL) +{ + ::std::vector< MigrationItem > vOldItems; + ::std::vector< MigrationItem > vNewItems; + uno::Sequence< beans::PropertyValue > aProp; + sal_Int32 nOldCount = xIndexOld->getCount(); + sal_Int32 nNewCount = xIndexNew->getCount(); + + for (int n=0; n<nOldCount; ++n) + { + MigrationItem aMigrationItem; + if (xIndexOld->getByIndex(n) >>= aProp) + { + for(int i=0; i<aProp.getLength(); ++i) + { + if (aProp[i].Name.equals(ITEM_DESCRIPTOR_COMMANDURL)) + aProp[i].Value >>= aMigrationItem.m_sCommandURL; + else if (aProp[i].Name.equals(ITEM_DESCRIPTOR_CONTAINER)) + aProp[i].Value >>= aMigrationItem.m_xPopupMenu; + } + + if (aMigrationItem.m_sCommandURL.getLength()) + vOldItems.push_back(aMigrationItem); + } + } + + for (int n=0; n<nNewCount; ++n) + { + MigrationItem aMigrationItem; + if (xIndexNew->getByIndex(n) >>= aProp) + { + for(int i=0; i<aProp.getLength(); ++i) + { + if (aProp[i].Name.equals(ITEM_DESCRIPTOR_COMMANDURL)) + aProp[i].Value >>= aMigrationItem.m_sCommandURL; + else if (aProp[i].Name.equals(ITEM_DESCRIPTOR_CONTAINER)) + aProp[i].Value >>= aMigrationItem.m_xPopupMenu; + } + + if (aMigrationItem.m_sCommandURL.getLength()) + vNewItems.push_back(aMigrationItem); + } + } + + ::std::vector< MigrationItem >::iterator it; + + ::rtl::OUString sSibling; + for (it = vOldItems.begin(); it!=vOldItems.end(); ++it) + { + ::std::vector< MigrationItem >::iterator pFound = ::std::find(vNewItems.begin(), vNewItems.end(), *it); + if (pFound != vNewItems.end() && it->m_xPopupMenu.is()) + { + ::rtl::OUString sName; + if (sParent.getLength()>0) + sName = sParent + MENU_SEPERATOR + it->m_sCommandURL; + else + sName = it->m_sCommandURL; + compareOldAndNewConfig(sName, it->m_xPopupMenu, pFound->m_xPopupMenu, sResourceURL); + } + else if (pFound == vNewItems.end()) + { + MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu); + if (m_aOldVersionItemsHashMap.find(sResourceURL)==m_aOldVersionItemsHashMap.end()) + { + ::std::vector< MigrationItem > vMigrationItems; + m_aOldVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems)); + m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem); + } + else + { + if (::std::find(m_aOldVersionItemsHashMap[sResourceURL].begin(), m_aOldVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aOldVersionItemsHashMap[sResourceURL].end()) + m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem); + } + } + + sSibling = it->m_sCommandURL; + } + + ::rtl::OUString sNewSibling; + uno::Reference< container::XIndexContainer > xPopup; + for (it = vNewItems.begin(); it!=vNewItems.end(); ++it) + { + ::std::vector< MigrationItem >::iterator pFound = ::std::find(vOldItems.begin(), vOldItems.end(), *it); + if (pFound != vOldItems.end() && it->m_xPopupMenu.is()) + { + ::rtl::OUString sName; + if (sParent.getLength()>0) + sName = sParent + MENU_SEPERATOR + it->m_sCommandURL; + else + sName = it->m_sCommandURL; + compareOldAndNewConfig(sName, pFound->m_xPopupMenu, it->m_xPopupMenu, sResourceURL); + } + else if (::std::find(vOldItems.begin(), vOldItems.end(), *it) == vOldItems.end()) + { + MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu); + if (m_aNewVersionItemsHashMap.find(sResourceURL)==m_aNewVersionItemsHashMap.end()) + { + ::std::vector< MigrationItem > vMigrationItems; + m_aNewVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems)); + m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem); + } + else + { + if (::std::find(m_aNewVersionItemsHashMap[sResourceURL].begin(), m_aNewVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aNewVersionItemsHashMap[sResourceURL].end()) + m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem); + } + } + } +} + +void MigrationImpl::mergeOldToNewVersion(const uno::Reference< ui::XUIConfigurationManager >& xCfgManager, + const uno::Reference< container::XIndexContainer>& xIndexContainer, + const ::rtl::OUString& sModuleIdentifier, + const ::rtl::OUString& sResourceURL) +{ + MigrationHashMap::iterator pFound = m_aOldVersionItemsHashMap.find(sResourceURL); + if (pFound==m_aOldVersionItemsHashMap.end()) + return; + + ::std::vector< MigrationItem >::iterator it; + for (it=pFound->second.begin(); it!=pFound->second.end(); ++it) + { + uno::Reference< container::XIndexContainer > xTemp = xIndexContainer; + + ::rtl::OUString sParentNodeName = it->m_sParentNodeName; + sal_Int32 nIndex = 0; + do + { + ::rtl::OUString sToken = sParentNodeName.getToken(0, '|', nIndex).trim(); + if (sToken.getLength()<=0) + break; + + sal_Int32 nCount = xTemp->getCount(); + for (sal_Int32 i=0; i<nCount; ++i) + { + ::rtl::OUString sCommandURL; + ::rtl::OUString sLabel; + uno::Reference< container::XIndexContainer > xChild; + + uno::Sequence< beans::PropertyValue > aPropSeq; + xTemp->getByIndex(i) >>= aPropSeq; + for (sal_Int32 j=0; j<aPropSeq.getLength(); ++j) + { + ::rtl::OUString sPropName = aPropSeq[j].Name; + if (sPropName.equals(ITEM_DESCRIPTOR_COMMANDURL)) + aPropSeq[j].Value >>= sCommandURL; + else if (sPropName.equals(ITEM_DESCRIPTOR_LABEL)) + aPropSeq[j].Value >>= sLabel; + else if (sPropName.equals(ITEM_DESCRIPTOR_CONTAINER)) + aPropSeq[j].Value >>= xChild; + } + + if (sCommandURL == sToken) + { + xTemp = xChild; + break; + } + } + + } while (nIndex>=0); + + if (nIndex == -1) + { + uno::Sequence< beans::PropertyValue > aPropSeq(3); + + aPropSeq[0].Name = ITEM_DESCRIPTOR_COMMANDURL; + aPropSeq[0].Value <<= it->m_sCommandURL; + aPropSeq[1].Name = ITEM_DESCRIPTOR_LABEL; + aPropSeq[1].Value <<= retrieveLabelFromCommand(it->m_sCommandURL, sModuleIdentifier); + aPropSeq[2].Name = ITEM_DESCRIPTOR_CONTAINER; + aPropSeq[2].Value <<= it->m_xPopupMenu; + + if (it->m_sPrevSibling.getLength() == 0) + xTemp->insertByIndex(0, uno::makeAny(aPropSeq)); + else if (it->m_sPrevSibling.getLength() > 0) + { + sal_Int32 nCount = xTemp->getCount(); + sal_Int32 i = 0; + for (; i<nCount; ++i) + { + ::rtl::OUString sCmd; + uno::Sequence< beans::PropertyValue > aTempPropSeq; + xTemp->getByIndex(i) >>= aTempPropSeq; + for (sal_Int32 j=0; j<aTempPropSeq.getLength(); ++j) + { + if (aTempPropSeq[j].Name.equals(ITEM_DESCRIPTOR_COMMANDURL)) + { + aTempPropSeq[j].Value >>= sCmd; + break; + } + } + + if (sCmd.equals(it->m_sPrevSibling)) + break; + } + + xTemp->insertByIndex(i+1, uno::makeAny(aPropSeq)); + } + } + } + + uno::Reference< container::XIndexAccess > xIndexAccess(xIndexContainer, uno::UNO_QUERY); + if (xIndexAccess.is()) + xCfgManager->replaceSettings(sResourceURL, xIndexAccess); + + uno::Reference< ui::XUIConfigurationPersistence > xUIConfigurationPersistence(xCfgManager, uno::UNO_QUERY); + if (xUIConfigurationPersistence.is()) + xUIConfigurationPersistence->store(); +} + +uno::Reference< ui::XUIConfigurationManager > NewVersionUIInfo::getConfigManager(const ::rtl::OUString& sModuleShortName) const +{ + uno::Reference< ui::XUIConfigurationManager > xCfgManager; + + for (sal_Int32 i=0; i<m_lCfgManagerSeq.getLength(); ++i) + { + if (m_lCfgManagerSeq[i].Name.equals(sModuleShortName)) + { + m_lCfgManagerSeq[i].Value >>= xCfgManager; + break; + } + } + + return xCfgManager; +} + +uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewMenubarSettings(const ::rtl::OUString& sModuleShortName) const +{ + uno::Reference< container::XIndexContainer > xNewMenuSettings; + + for (sal_Int32 i=0; i<m_lNewVersionMenubarSettingsSeq.getLength(); ++i) + { + if (m_lNewVersionMenubarSettingsSeq[i].Name.equals(sModuleShortName)) + { + m_lNewVersionMenubarSettingsSeq[i].Value >>= xNewMenuSettings; + break; + } + } + + return xNewMenuSettings; +} + +uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewToolbarSettings(const ::rtl::OUString& sModuleShortName, const ::rtl::OUString& sToolbarName) const +{ + uno::Reference< container::XIndexContainer > xNewToolbarSettings; + + for (sal_Int32 i=0; i<m_lNewVersionToolbarSettingsSeq.getLength(); ++i) + { + if (m_lNewVersionToolbarSettingsSeq[i].Name.equals(sModuleShortName)) + { + uno::Sequence< beans::PropertyValue > lToolbarSettingsSeq; + m_lNewVersionToolbarSettingsSeq[i].Value >>= lToolbarSettingsSeq; + for (sal_Int32 j=0; j<lToolbarSettingsSeq.getLength(); ++j) + { + if (lToolbarSettingsSeq[j].Name.equals(sToolbarName)) + { + lToolbarSettingsSeq[j].Value >>= xNewToolbarSettings; + break; + } + } + + break; + } + } + + return xNewToolbarSettings; +} + +void NewVersionUIInfo::init(const ::std::vector< MigrationModuleInfo >& vModulesInfo) +{ + m_lCfgManagerSeq.realloc(vModulesInfo.size()); + m_lNewVersionMenubarSettingsSeq.realloc(vModulesInfo.size()); + m_lNewVersionToolbarSettingsSeq.realloc(vModulesInfo.size()); + + const ::rtl::OUString sModuleCfgSupplier(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.ModuleUIConfigurationManagerSupplier")); + const ::rtl::OUString sMenubarResourceURL(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar")); + const ::rtl::OUString sToolbarResourcePre(RTL_CONSTASCII_USTRINGPARAM("private:resource/toolbar/")); + + uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier = uno::Reference< ui::XModuleUIConfigurationManagerSupplier >(::comphelper::getProcessServiceFactory()->createInstance(sModuleCfgSupplier), uno::UNO_QUERY); + + for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i) + { + ::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName); + if (sModuleIdentifier.getLength() > 0) + { + uno::Reference< ui::XUIConfigurationManager > xCfgManager = xModuleCfgSupplier->getUIConfigurationManager(sModuleIdentifier); + m_lCfgManagerSeq[i].Name = vModulesInfo[i].sModuleShortName; + m_lCfgManagerSeq[i].Value <<= xCfgManager; + + if (vModulesInfo[i].bHasMenubar) + { + m_lNewVersionMenubarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName; + m_lNewVersionMenubarSettingsSeq[i].Value <<= xCfgManager->getSettings(sMenubarResourceURL, sal_True); + } + + sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size(); + if (nToolbars > 0) + { + uno::Sequence< beans::PropertyValue > lPropSeq(nToolbars); + for (sal_Int32 j=0; j<nToolbars; ++j) + { + ::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j]; + ::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName; + + lPropSeq[j].Name = sToolbarName; + lPropSeq[j].Value <<= xCfgManager->getSettings(sToolbarResourceURL, sal_True); + } + + m_lNewVersionToolbarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName; + m_lNewVersionToolbarSettingsSeq[i].Value <<= lPropSeq; + } + } + } +} + +} // namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/migration_impl.hxx b/desktop/source/migration/migration_impl.hxx new file mode 100644 index 000000000000..2d079aeb99a5 --- /dev/null +++ b/desktop/source/migration/migration_impl.hxx @@ -0,0 +1,254 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_MIGRATION_IMPL_HXX_ +#define _DESKTOP_MIGRATION_IMPL_HXX_ + +#include <vector> +#include <algorithm> +#include <memory> +#include <boost/unordered_map.hpp> + +#include "migration.hxx" + +#include <sal/types.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> + +#include <com/sun/star/uno/Reference.hxx> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/lang/XSingleComponentFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XUIConfigurationManager.hpp> +#include <com/sun/star/ui/XUIConfigurationPersistence.hpp> + +#define NS_CSS com::sun::star +#define NS_UNO com::sun::star::uno + +namespace desktop +{ + +struct install_info +{ + rtl::OUString productname; // human readeable product name + rtl::OUString userdata; // file: url for user installation +}; + +typedef std::vector< rtl::OUString > strings_v; +typedef std::auto_ptr< strings_v > strings_vr; + +struct migration_step +{ + rtl::OUString name; + strings_v includeFiles; + strings_v excludeFiles; + strings_v includeConfig; + strings_v excludeConfig; + strings_v includeExtensions; + strings_v excludeExtensions; + rtl::OUString service; +}; + +struct supported_migration +{ + rtl::OUString name; + sal_Int32 nPriority; + strings_v supported_versions; +}; + +typedef std::vector< migration_step > migrations_v; +typedef std::auto_ptr< migrations_v > migrations_vr; +typedef std::vector< supported_migration > migrations_available; + +//__________________________________________ +/** + define the item, e.g.:menuitem, toolbaritem, to be migrated. we keep the information + of the command URL, the previous sibling node and the parent node of a item +*/ +struct MigrationItem +{ + ::rtl::OUString m_sParentNodeName; + ::rtl::OUString m_sPrevSibling; + ::rtl::OUString m_sCommandURL; + NS_UNO::Reference< NS_CSS::container::XIndexContainer > m_xPopupMenu; + + MigrationItem() + :m_xPopupMenu(0) + { + } + + MigrationItem(const ::rtl::OUString& sParentNodeName, + const ::rtl::OUString& sPrevSibling, + const ::rtl::OUString& sCommandURL, + const NS_UNO::Reference< NS_CSS::container::XIndexContainer > xPopupMenu) + { + m_sParentNodeName = sParentNodeName; + m_sPrevSibling = sPrevSibling; + m_sCommandURL = sCommandURL; + m_xPopupMenu = xPopupMenu; + } + + MigrationItem& operator=(const MigrationItem& aMigrationItem) + { + m_sParentNodeName = aMigrationItem.m_sParentNodeName; + m_sPrevSibling = aMigrationItem.m_sPrevSibling; + m_sCommandURL = aMigrationItem.m_sCommandURL; + m_xPopupMenu = aMigrationItem.m_xPopupMenu; + + return *this; + } + + sal_Bool operator==(const MigrationItem& aMigrationItem) + { + return ( aMigrationItem.m_sParentNodeName == m_sParentNodeName && + aMigrationItem.m_sPrevSibling == m_sPrevSibling && + aMigrationItem.m_sCommandURL == m_sCommandURL && + aMigrationItem.m_xPopupMenu.is() == m_xPopupMenu.is() ); + } + + ::rtl::OUString GetPrevSibling() const { return m_sPrevSibling; } +}; + +typedef ::boost::unordered_map< ::rtl::OUString, + ::std::vector< MigrationItem >, + ::rtl::OUStringHash, + ::std::equal_to< ::rtl::OUString > > MigrationHashMap; + +struct MigrationItemInfo +{ + ::rtl::OUString m_sResourceURL; + MigrationItem m_aMigrationItem; + + MigrationItemInfo(){} + + MigrationItemInfo(const ::rtl::OUString& sResourceURL, const MigrationItem& aMigratiionItem) + { + m_sResourceURL = sResourceURL; + m_aMigrationItem = aMigratiionItem; + } +}; + +//__________________________________________ +/** + information for the UI elements to be migrated for one module +*/ +struct MigrationModuleInfo +{ + ::rtl::OUString sModuleShortName; + sal_Bool bHasMenubar; + ::std::vector< ::rtl::OUString > m_vToolbars; + + MigrationModuleInfo():bHasMenubar(sal_False){}; +}; + +//__________________________________________ +/** + get the information before copying the ui configuration files of old version to new version +*/ +class NewVersionUIInfo +{ +public: + + NS_UNO::Reference< NS_CSS::ui::XUIConfigurationManager > getConfigManager(const ::rtl::OUString& sModuleShortName) const; + NS_UNO::Reference< NS_CSS::container::XIndexContainer > getNewMenubarSettings(const ::rtl::OUString& sModuleShortName) const; + NS_UNO::Reference< NS_CSS::container::XIndexContainer > getNewToolbarSettings(const ::rtl::OUString& sModuleShortName, const ::rtl::OUString& sToolbarName) const; + void init(const ::std::vector< MigrationModuleInfo >& vModulesInfo); + +private: + + NS_UNO::Sequence< NS_CSS::beans::PropertyValue > m_lCfgManagerSeq; + NS_UNO::Sequence< NS_CSS::beans::PropertyValue > m_lNewVersionMenubarSettingsSeq; + NS_UNO::Sequence< NS_CSS::beans::PropertyValue > m_lNewVersionToolbarSettingsSeq; +}; + +class MigrationImpl +{ + +private: + strings_vr m_vrVersions; + NS_UNO::Reference< NS_CSS::lang::XMultiServiceFactory > m_xFactory; + + migrations_available m_vMigrationsAvailable; // list of all available migrations + migrations_vr m_vrMigrations; // list of all migration specs from config + install_info m_aInfo; // info about the version being migrated + strings_vr m_vrFileList; // final list of files to be copied + MigrationHashMap m_aOldVersionItemsHashMap; + MigrationHashMap m_aNewVersionItemsHashMap; + ::rtl::OUString m_sModuleIdentifier; + + // functions to control the migration process + bool readAvailableMigrations(migrations_available&); + bool alreadyMigrated(); + migrations_vr readMigrationSteps(const ::rtl::OUString& rMigrationName); + sal_Int32 findPreferedMigrationProcess(const migrations_available&); + install_info findInstallation(const strings_v& rVersions); + strings_vr compileFileList(); + + // helpers + void subtract(strings_v& va, const strings_v& vb_c) const; + strings_vr getAllFiles(const rtl::OUString& baseURL) const; + strings_vr applyPatterns(const strings_v& vSet, const strings_v& vPatterns) const; + NS_UNO::Reference< NS_CSS::container::XNameAccess > getConfigAccess(const sal_Char* path, sal_Bool rw=sal_False); + + ::std::vector< MigrationModuleInfo > dectectUIChangesForAllModules() const; + void compareOldAndNewConfig(const ::rtl::OUString& sParentNodeName, + const NS_UNO::Reference< NS_CSS::container::XIndexContainer >& xOldIndexContainer, + const NS_UNO::Reference< NS_CSS::container::XIndexContainer >& xNewIndexContainer, + const ::rtl::OUString& sToolbarName); + void mergeOldToNewVersion(const NS_UNO::Reference< NS_CSS::ui::XUIConfigurationManager >& xCfgManager, + const NS_UNO::Reference< NS_CSS::container::XIndexContainer>& xIndexContainer, + const ::rtl::OUString& sModuleIdentifier, + const ::rtl::OUString& sResourceURL); + + // actual processing function that perform the migration steps + void copyFiles(); + void copyConfig(); + void runServices(); + void refresh(); + + void setMigrationCompleted(); + bool checkMigrationCompleted(); + +public: + MigrationImpl(const NS_UNO::Reference< NS_CSS::lang::XMultiServiceFactory >&); + ~MigrationImpl(); + bool initializeMigration(); + sal_Bool doMigration(); + rtl::OUString getOldVersionName(); +}; +} +#undef NS_CSS +#undef NS_UNO + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/autocorrmigration.cxx b/desktop/source/migration/services/autocorrmigration.cxx new file mode 100644 index 000000000000..c3d24e941375 --- /dev/null +++ b/desktop/source/migration/services/autocorrmigration.cxx @@ -0,0 +1,288 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "autocorrmigration.hxx" +#include <i18npool/mslangid.hxx> +#include <tools/urlobj.hxx> +#include <unotools/bootstrap.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + + static ::rtl::OUString sSourceSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/autocorr" ) ); + static ::rtl::OUString sTargetSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/autocorr" ) ); + static ::rtl::OUString sBaseName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/acor" ) ); + static ::rtl::OUString sSuffix = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".dat" ) ); + + + // ============================================================================= + // component operations + // ============================================================================= + + ::rtl::OUString AutocorrectionMigration_getImplementationName() + { + static ::rtl::OUString* pImplName = 0; + if ( !pImplName ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pImplName ) + { + static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.desktop.migration.Autocorrection" ) ); + pImplName = &aImplName; + } + } + return *pImplName; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > AutocorrectionMigration_getSupportedServiceNames() + { + static Sequence< ::rtl::OUString >* pNames = 0; + if ( !pNames ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pNames ) + { + static Sequence< ::rtl::OUString > aNames(1); + aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Autocorrection" ) ); + pNames = &aNames; + } + } + return *pNames; + } + + // ============================================================================= + // AutocorrectionMigration + // ============================================================================= + + AutocorrectionMigration::AutocorrectionMigration() + { + } + + // ----------------------------------------------------------------------------- + + AutocorrectionMigration::~AutocorrectionMigration() + { + } + + // ----------------------------------------------------------------------------- + + TStringVectorPtr AutocorrectionMigration::getFiles( const ::rtl::OUString& rBaseURL ) const + { + TStringVectorPtr aResult( new TStringVector ); + ::osl::Directory aDir( rBaseURL); + + if ( aDir.open() == ::osl::FileBase::E_None ) + { + // iterate over directory content + TStringVector aSubDirs; + ::osl::DirectoryItem aItem; + while ( aDir.getNextItem( aItem ) == ::osl::FileBase::E_None ) + { + ::osl::FileStatus aFileStatus( osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL ); + if ( aItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None ) + { + if ( aFileStatus.getFileType() == ::osl::FileStatus::Directory ) + aSubDirs.push_back( aFileStatus.getFileURL() ); + else + aResult->push_back( aFileStatus.getFileURL() ); + } + } + + // iterate recursive over subfolders + TStringVector::const_iterator aI = aSubDirs.begin(); + while ( aI != aSubDirs.end() ) + { + TStringVectorPtr aSubResult = getFiles( *aI ); + aResult->insert( aResult->end(), aSubResult->begin(), aSubResult->end() ); + ++aI; + } + } + + return aResult; + } + + // ----------------------------------------------------------------------------- + + ::osl::FileBase::RC AutocorrectionMigration::checkAndCreateDirectory( INetURLObject& rDirURL ) + { + ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + if ( aResult == ::osl::FileBase::E_NOENT ) + { + INetURLObject aBaseURL( rDirURL ); + aBaseURL.removeSegment(); + checkAndCreateDirectory( aBaseURL ); + return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + } + else + { + return aResult; + } + } + + // ----------------------------------------------------------------------------- + + void AutocorrectionMigration::copyFiles() + { + ::rtl::OUString sTargetDir; + ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( sTargetDir ); + if ( aStatus == ::utl::Bootstrap::PATH_EXISTS ) + { + sTargetDir += sTargetSubDir; + TStringVectorPtr aFileList = getFiles( m_sSourceDir ); + TStringVector::const_iterator aI = aFileList->begin(); + while ( aI != aFileList->end() ) + { + ::rtl::OUString sSourceLocalName = aI->copy( m_sSourceDir.getLength() ); + sal_Int32 nStart = sBaseName.getLength(); + sal_Int32 nEnd = sSourceLocalName.lastIndexOf ( sSuffix ); + ::rtl::OUString sLanguageType = sSourceLocalName.copy( nStart, nEnd - nStart ); + ::rtl::OUString sIsoName = MsLangId::convertLanguageToIsoString( (LanguageType) sLanguageType.toInt32() ); + ::rtl::OUString sTargetLocalName = sBaseName; + sTargetLocalName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "_" )); + sTargetLocalName += sIsoName; + sTargetLocalName += sSuffix; + ::rtl::OUString sTargetName = sTargetDir + sTargetLocalName; + INetURLObject aURL( sTargetName ); + aURL.removeSegment(); + checkAndCreateDirectory( aURL ); + ::osl::FileBase::RC aResult = ::osl::File::copy( *aI, sTargetName ); + if ( aResult != ::osl::FileBase::E_None ) + { + ::rtl::OString aMsg( "AutocorrectionMigration::copyFiles: cannot copy " ); + aMsg += ::rtl::OUStringToOString( *aI, RTL_TEXTENCODING_UTF8 ) + " to " + + ::rtl::OUStringToOString( sTargetName, RTL_TEXTENCODING_UTF8 ); + OSL_FAIL( aMsg.getStr() ); + } + ++aI; + } + } + else + { + OSL_FAIL( "AutocorrectionMigration::copyFiles: no user installation!" ); + } + } + + // ----------------------------------------------------------------------------- + // XServiceInfo + // ----------------------------------------------------------------------------- + + ::rtl::OUString AutocorrectionMigration::getImplementationName() throw (RuntimeException) + { + return AutocorrectionMigration_getImplementationName(); + } + + // ----------------------------------------------------------------------------- + + sal_Bool AutocorrectionMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); + const ::rtl::OUString* pNames = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pNames + aNames.getLength(); + for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) + ; + + return pNames != pEnd; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > AutocorrectionMigration::getSupportedServiceNames() throw (RuntimeException) + { + return AutocorrectionMigration_getSupportedServiceNames(); + } + + // ----------------------------------------------------------------------------- + // XInitialization + // ----------------------------------------------------------------------------- + + void AutocorrectionMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + const Any* pIter = aArguments.getConstArray(); + const Any* pEnd = pIter + aArguments.getLength(); + for ( ; pIter != pEnd ; ++pIter ) + { + beans::NamedValue aValue; + *pIter >>= aValue; + if ( aValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "UserData" ) ) ) + { + if ( !(aValue.Value >>= m_sSourceDir) ) + { + OSL_FAIL( "AutocorrectionMigration::initialize: argument UserData has wrong type!" ); + } + m_sSourceDir += sSourceSubDir; + break; + } + } + } + + // ----------------------------------------------------------------------------- + // XJob + // ----------------------------------------------------------------------------- + + Any AutocorrectionMigration::execute( const Sequence< beans::NamedValue >& ) + throw (lang::IllegalArgumentException, Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + copyFiles(); + + return Any(); + } + + // ============================================================================= + // component operations + // ============================================================================= + + Reference< XInterface > SAL_CALL AutocorrectionMigration_create( + Reference< XComponentContext > const & ) + SAL_THROW( () ) + { + return static_cast< lang::XTypeProvider * >( new AutocorrectionMigration() ); + } + + // ----------------------------------------------------------------------------- + +//......................................................................... +} // namespace migration +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/autocorrmigration.hxx b/desktop/source/migration/services/autocorrmigration.hxx new file mode 100644 index 000000000000..20021ceb100a --- /dev/null +++ b/desktop/source/migration/services/autocorrmigration.hxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_AUTOCORRMIGRATION_HXX_ +#define _DESKTOP_AUTOCORRMIGRATION_HXX_ + +#include "misc.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase3.hxx> +#include <osl/mutex.hxx> +#include <osl/file.hxx> + + +class INetURLObject; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + ::rtl::OUString SAL_CALL AutocorrectionMigration_getImplementationName(); + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL AutocorrectionMigration_getSupportedServiceNames(); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL AutocorrectionMigration_create( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xContext ) + SAL_THROW( (::com::sun::star::uno::Exception) ); + + + // ============================================================================= + // class AutocorrectionMigration + // ============================================================================= + + typedef ::cppu::WeakImplHelper3< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::task::XJob > AutocorrectionMigration_BASE; + + class AutocorrectionMigration : public AutocorrectionMigration_BASE + { + private: + ::osl::Mutex m_aMutex; + ::rtl::OUString m_sSourceDir; + + TStringVectorPtr getFiles( const ::rtl::OUString& rBaseURL ) const; + ::osl::FileBase::RC checkAndCreateDirectory( INetURLObject& rDirURL ); + void copyFiles(); + + public: + AutocorrectionMigration(); + virtual ~AutocorrectionMigration(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XJob + virtual ::com::sun::star::uno::Any SAL_CALL execute( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& Arguments ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + }; + +//......................................................................... +} // namespace migration +//......................................................................... + +#endif // _DESKTOP_AUTOCORRMIGRATION_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/basicmigration.cxx b/desktop/source/migration/services/basicmigration.cxx new file mode 100644 index 000000000000..40474a23d25e --- /dev/null +++ b/desktop/source/migration/services/basicmigration.cxx @@ -0,0 +1,257 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "basicmigration.hxx" +#include <tools/urlobj.hxx> +#include <unotools/bootstrap.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + + #define sSourceUserBasic ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/user/basic")) + #define sTargetUserBasic ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/user/__basic_80")) + + // ============================================================================= + // component operations + // ============================================================================= + + ::rtl::OUString BasicMigration_getImplementationName() + { + return ::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.desktop.migration.Basic")); + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > BasicMigration_getSupportedServiceNames() + { + Sequence< ::rtl::OUString > aNames(1); + aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Basic" ) ); + return aNames; + } + + // ============================================================================= + // BasicMigration + // ============================================================================= + + BasicMigration::BasicMigration() + { + } + + // ----------------------------------------------------------------------------- + + BasicMigration::~BasicMigration() + { + } + + // ----------------------------------------------------------------------------- + + TStringVectorPtr BasicMigration::getFiles( const ::rtl::OUString& rBaseURL ) const + { + TStringVectorPtr aResult( new TStringVector ); + ::osl::Directory aDir( rBaseURL); + + if ( aDir.open() == ::osl::FileBase::E_None ) + { + // iterate over directory content + TStringVector aSubDirs; + ::osl::DirectoryItem aItem; + while ( aDir.getNextItem( aItem ) == ::osl::FileBase::E_None ) + { + ::osl::FileStatus aFileStatus( osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL ); + if ( aItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None ) + { + if ( aFileStatus.getFileType() == ::osl::FileStatus::Directory ) + aSubDirs.push_back( aFileStatus.getFileURL() ); + else + aResult->push_back( aFileStatus.getFileURL() ); + } + } + + // iterate recursive over subfolders + TStringVector::const_iterator aI = aSubDirs.begin(); + while ( aI != aSubDirs.end() ) + { + TStringVectorPtr aSubResult = getFiles( *aI ); + aResult->insert( aResult->end(), aSubResult->begin(), aSubResult->end() ); + ++aI; + } + } + + return aResult; + } + + // ----------------------------------------------------------------------------- + + ::osl::FileBase::RC BasicMigration::checkAndCreateDirectory( INetURLObject& rDirURL ) + { + ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + if ( aResult == ::osl::FileBase::E_NOENT ) + { + INetURLObject aBaseURL( rDirURL ); + aBaseURL.removeSegment(); + checkAndCreateDirectory( aBaseURL ); + return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + } + else + { + return aResult; + } + } + + // ----------------------------------------------------------------------------- + + void BasicMigration::copyFiles() + { + ::rtl::OUString sTargetDir; + ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( sTargetDir ); + if ( aStatus == ::utl::Bootstrap::PATH_EXISTS ) + { + sTargetDir += sTargetUserBasic; + TStringVectorPtr aFileList = getFiles( m_sSourceDir ); + TStringVector::const_iterator aI = aFileList->begin(); + while ( aI != aFileList->end() ) + { + ::rtl::OUString sLocalName = aI->copy( m_sSourceDir.getLength() ); + ::rtl::OUString sTargetName = sTargetDir + sLocalName; + INetURLObject aURL( sTargetName ); + aURL.removeSegment(); + checkAndCreateDirectory( aURL ); + ::osl::FileBase::RC aResult = ::osl::File::copy( *aI, sTargetName ); + if ( aResult != ::osl::FileBase::E_None ) + { + ::rtl::OString aMsg( "BasicMigration::copyFiles: cannot copy " ); + aMsg += ::rtl::OUStringToOString( *aI, RTL_TEXTENCODING_UTF8 ) + " to " + + ::rtl::OUStringToOString( sTargetName, RTL_TEXTENCODING_UTF8 ); + OSL_FAIL( aMsg.getStr() ); + } + ++aI; + } + } + else + { + OSL_FAIL( "BasicMigration::copyFiles: no user installation!" ); + } + } + + // ----------------------------------------------------------------------------- + // XServiceInfo + // ----------------------------------------------------------------------------- + + ::rtl::OUString BasicMigration::getImplementationName() throw (RuntimeException) + { + return BasicMigration_getImplementationName(); + } + + // ----------------------------------------------------------------------------- + + sal_Bool BasicMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); + const ::rtl::OUString* pNames = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pNames + aNames.getLength(); + for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) + ; + + return pNames != pEnd; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > BasicMigration::getSupportedServiceNames() throw (RuntimeException) + { + return BasicMigration_getSupportedServiceNames(); + } + + // ----------------------------------------------------------------------------- + // XInitialization + // ----------------------------------------------------------------------------- + + void BasicMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + const Any* pIter = aArguments.getConstArray(); + const Any* pEnd = pIter + aArguments.getLength(); + for ( ; pIter != pEnd ; ++pIter ) + { + beans::NamedValue aValue; + *pIter >>= aValue; + if ( aValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "UserData" ) ) ) + { + if ( !(aValue.Value >>= m_sSourceDir) ) + { + OSL_FAIL( "BasicMigration::initialize: argument UserData has wrong type!" ); + } + m_sSourceDir += sSourceUserBasic; + break; + } + } + } + + // ----------------------------------------------------------------------------- + // XJob + // ----------------------------------------------------------------------------- + + Any BasicMigration::execute( const Sequence< beans::NamedValue >& ) + throw (lang::IllegalArgumentException, Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + copyFiles(); + + return Any(); + } + + // ============================================================================= + // component operations + // ============================================================================= + + Reference< XInterface > SAL_CALL BasicMigration_create( + Reference< XComponentContext > const & ) + SAL_THROW( () ) + { + return static_cast< lang::XTypeProvider * >( new BasicMigration() ); + } + + // ----------------------------------------------------------------------------- + +//......................................................................... +} // namespace migration +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/basicmigration.hxx b/desktop/source/migration/services/basicmigration.hxx new file mode 100644 index 000000000000..49260cadd522 --- /dev/null +++ b/desktop/source/migration/services/basicmigration.hxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_BASICMIGRATION_HXX_ +#define _DESKTOP_BASICMIGRATION_HXX_ + +#include "misc.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase3.hxx> +#include <osl/mutex.hxx> +#include <osl/file.hxx> + + +class INetURLObject; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + ::rtl::OUString SAL_CALL BasicMigration_getImplementationName(); + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL BasicMigration_getSupportedServiceNames(); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL BasicMigration_create( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xContext ) + SAL_THROW( (::com::sun::star::uno::Exception) ); + + + // ============================================================================= + // class BasicMigration + // ============================================================================= + + typedef ::cppu::WeakImplHelper3< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::task::XJob > BasicMigration_BASE; + + class BasicMigration : public BasicMigration_BASE + { + private: + ::osl::Mutex m_aMutex; + ::rtl::OUString m_sSourceDir; + + TStringVectorPtr getFiles( const ::rtl::OUString& rBaseURL ) const; + ::osl::FileBase::RC checkAndCreateDirectory( INetURLObject& rDirURL ); + void copyFiles(); + + public: + BasicMigration(); + virtual ~BasicMigration(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XJob + virtual ::com::sun::star::uno::Any SAL_CALL execute( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& Arguments ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + }; + +//......................................................................... +} // namespace migration +//......................................................................... + +#endif // _DESKTOP_BASICMIGRATION_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/cexports.cxx b/desktop/source/migration/services/cexports.cxx new file mode 100644 index 000000000000..f527941376bd --- /dev/null +++ b/desktop/source/migration/services/cexports.cxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "cppuhelper/implementationentry.hxx" +#include "basicmigration.hxx" +#include "wordbookmigration.hxx" + + +extern "C" +{ + +::cppu::ImplementationEntry entries [] = +{ + { + migration::BasicMigration_create, migration::BasicMigration_getImplementationName, + migration::BasicMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory, + 0, 0 + }, + { + migration::WordbookMigration_create, migration::WordbookMigration_getImplementationName, + migration::WordbookMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory, + 0, 0 + }, + // Extension migration was disabled by Oracle / OpenOffice.org +#if 0 + { + migration::ExtensionMigration_create, migration::ExtensionMigration_getImplementationName, + migration::ExtensionMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory, + 0, 0 + }, +#endif + { 0, 0, 0, 0, 0, 0 } +}; + + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, entries ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/cexportsoo3.cxx b/desktop/source/migration/services/cexportsoo3.cxx new file mode 100644 index 000000000000..5f715393cc1c --- /dev/null +++ b/desktop/source/migration/services/cexportsoo3.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "cppuhelper/implementationentry.hxx" +#include "oo3extensionmigration.hxx" + +extern "C" +{ + +::cppu::ImplementationEntry entries [] = +{ + { + migration::OO3ExtensionMigration_create, migration::OO3ExtensionMigration_getImplementationName, + migration::OO3ExtensionMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory, + 0, 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, entries ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/cppumaker.mk b/desktop/source/migration/services/cppumaker.mk new file mode 100755 index 000000000000..5ab16ed1e3fe --- /dev/null +++ b/desktop/source/migration/services/cppumaker.mk @@ -0,0 +1,36 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +.IF "$(debug)" != "" + +# MSVC++: no inlining +.IF "$(COM)" == "MSC" +CFLAGS += -Ob0 +.ENDIF + +.ENDIF + diff --git a/desktop/source/migration/services/jvmfwk.cxx b/desktop/source/migration/services/jvmfwk.cxx new file mode 100644 index 000000000000..53c3596ae4f4 --- /dev/null +++ b/desktop/source/migration/services/jvmfwk.cxx @@ -0,0 +1,531 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "cppuhelper/implbase4.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "rtl/bootstrap.hxx" +#include "sal/types.h" +#include "sal/config.h" +#include "boost/scoped_array.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/task/XJob.hpp" +#include "com/sun/star/configuration/backend/XLayer.hpp" +#include "com/sun/star/configuration/backend/XLayerHandler.hpp" +#include "com/sun/star/configuration/backend/MalformedDataException.hpp" +#include "com/sun/star/configuration/backend/TemplateIdentifier.hpp" +#include "jvmfwk/framework.h" +#include "jvmfwk.hxx" +#include <stack> +#include <stdio.h> + +#include "osl/thread.hxx" +using ::rtl::OUString; + +#define OUSTR(x) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( x )) + +#define SERVICE_NAME "com.sun.star.migration.Java" +#define IMPL_NAME "com.sun.star.comp.desktop.migration.Java" + +#define ENABLE_JAVA 1 +#define USER_CLASS_PATH 2 + +namespace css = com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::configuration::backend; + +namespace migration +{ + +class CJavaInfo +{ + CJavaInfo(const CJavaInfo&); + CJavaInfo& operator = (const CJavaInfo&); +public: + JavaInfo* pData; + CJavaInfo(); + ~CJavaInfo(); + operator JavaInfo* () const; +}; + +CJavaInfo::CJavaInfo(): pData(NULL) +{ +} + +CJavaInfo::~CJavaInfo() +{ + jfw_freeJavaInfo(pData); +} + +CJavaInfo::operator JavaInfo*() const +{ + return pData; +} + + +class JavaMigration : public ::cppu::WeakImplHelper4< + css::lang::XServiceInfo, + css::lang::XInitialization, + css::task::XJob, + css::configuration::backend::XLayerHandler> +{ +public: + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) + throw (css::uno::RuntimeException); + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw (css::uno::RuntimeException); + + //XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) + throw(css::uno::Exception, css::uno::RuntimeException); + + //XJob + virtual css::uno::Any SAL_CALL execute( + const css::uno::Sequence<css::beans::NamedValue >& Arguments ) + throw (css::lang::IllegalArgumentException, css::uno::Exception, + css::uno::RuntimeException); + + // XLayerHandler + virtual void SAL_CALL startLayer() + throw(::com::sun::star::lang::WrappedTargetException); + + virtual void SAL_CALL endLayer() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL overrideNode( + const rtl::OUString& aName, + sal_Int16 aAttributes, + sal_Bool bClear) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addOrReplaceNode( + const rtl::OUString& aName, + sal_Int16 aAttributes) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addOrReplaceNodeFromTemplate( + const rtl::OUString& aName, + const ::com::sun::star::configuration::backend::TemplateIdentifier& aTemplate, + sal_Int16 aAttributes ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL endNode() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL dropNode( + const rtl::OUString& aName ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL overrideProperty( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const css::uno::Type& aType, + sal_Bool bClear ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL setPropertyValue( + const css::uno::Any& aValue ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL setPropertyValueForLocale( + const css::uno::Any& aValue, + const rtl::OUString& aLocale ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL endProperty() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addProperty( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const css::uno::Type& aType ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addPropertyWithValue( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const css::uno::Any& aValue ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + + + //---------------- + ~JavaMigration(); + +private: + OUString m_sUserDir; + css::uno::Reference< ::css::configuration::backend::XLayer> m_xLayer; + + void migrateJavarc(); + typedef ::std::pair< ::rtl::OUString, sal_Int16> TElementType; + typedef ::std::stack< TElementType > TElementStack; + TElementStack m_aStack; + +}; + +JavaMigration::~JavaMigration() +{ + OSL_ASSERT(m_aStack.empty()); +} + +OUString jvmfwk_getImplementationName() +{ + return OUSTR(IMPL_NAME); +} + +css::uno::Sequence< OUString > jvmfwk_getSupportedServiceNames() +{ + OUString str_name = OUSTR(SERVICE_NAME); + return css::uno::Sequence< OUString >( &str_name, 1 ); +} + +// XServiceInfo +OUString SAL_CALL JavaMigration::getImplementationName() + throw (css::uno::RuntimeException) +{ + return jvmfwk_getImplementationName(); +} + +sal_Bool SAL_CALL JavaMigration::supportsService( const OUString & rServiceName ) + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< OUString > const & rSNL = getSupportedServiceNames(); + OUString const * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + { + if (rServiceName.equals( pArray[ nPos ] )) + return true; + } + return false; + +} + +css::uno::Sequence< OUString > SAL_CALL JavaMigration::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + return jvmfwk_getSupportedServiceNames(); +} + +//XInitialization ---------------------------------------------------------------------- +void SAL_CALL JavaMigration::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) + throw(css::uno::Exception, css::uno::RuntimeException) +{ + const css::uno::Any* pIter = aArguments.getConstArray(); + const css::uno::Any* pEnd = pIter + aArguments.getLength(); + css::uno::Sequence<css::beans::NamedValue> aOldConfigValues; + css::beans::NamedValue aValue; + for(;pIter != pEnd;++pIter) + { + *pIter >>= aValue; + if (aValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("OldConfiguration"))) + { + sal_Bool bSuccess = aValue.Value >>= aOldConfigValues; + OSL_ENSURE(bSuccess == sal_True, "[Service implementation " IMPL_NAME + "] XInitialization::initialize: Argument OldConfiguration has wrong type."); + if (bSuccess) + { + const css::beans::NamedValue* pIter2 = aOldConfigValues.getConstArray(); + const css::beans::NamedValue* pEnd2 = pIter2 + aOldConfigValues.getLength(); + for(;pIter2 != pEnd2;++pIter2) + { + if ( pIter2->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("org.openoffice.Office.Java")) ) + { + pIter2->Value >>= m_xLayer; + break; + } + } + } + } + else if (aValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UserData"))) + { + if ( !(aValue.Value >>= m_sUserDir) ) + { + OSL_FAIL( + "[Service implementation " IMPL_NAME + "] XInitialization::initialize: Argument UserData has wrong type."); + } + } + } + +} + +//XJob +css::uno::Any SAL_CALL JavaMigration::execute( + const css::uno::Sequence<css::beans::NamedValue >& ) + throw (css::lang::IllegalArgumentException, css::uno::Exception, + css::uno::RuntimeException) +{ + migrateJavarc(); + if (m_xLayer.is()) + m_xLayer->readData(this); + + return css::uno::Any(); +} + +void JavaMigration::migrateJavarc() +{ + if (m_sUserDir.getLength() == 0) + return; + + OUString sValue; + rtl::Bootstrap javaini(m_sUserDir + OUSTR("/user/config/"SAL_CONFIGFILE("java"))); + sal_Bool bSuccess = javaini.getFrom(OUSTR("Home"), sValue); + OSL_ENSURE(bSuccess, "[Service implementation " IMPL_NAME + "] XJob::execute: Could not get Home entry from java.ini/javarc."); + if (bSuccess == sal_True && sValue.getLength() > 0) + { + //get the directory + CJavaInfo aInfo; + javaFrameworkError err = jfw_getJavaInfoByPath(sValue.pData, &aInfo.pData); + + if (err == JFW_E_NONE) + { + if (jfw_setSelectedJRE(aInfo) != JFW_E_NONE) + { + OSL_FAIL("[Service implementation " IMPL_NAME + "] XJob::execute: jfw_setSelectedJRE failed."); + fprintf(stderr, "\nCannot migrate Java. An error occurred.\n"); + } + } + else if (err == JFW_E_FAILED_VERSION) + { + fprintf(stderr, "\nCannot migrate Java settings because the version of the Java " + "is not supported anymore.\n"); + } + } +} + + +// XLayerHandler +void SAL_CALL JavaMigration::startLayer() + throw(css::lang::WrappedTargetException) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::endLayer() + throw( + MalformedDataException, + WrappedTargetException ) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::overrideNode( + const ::rtl::OUString&, + sal_Int16, + sal_Bool) + throw( + MalformedDataException, + WrappedTargetException ) + +{ + +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::addOrReplaceNode( + const ::rtl::OUString&, + sal_Int16) + throw( + MalformedDataException, + WrappedTargetException ) +{ + +} +void SAL_CALL JavaMigration::endNode() + throw( + MalformedDataException, + WrappedTargetException ) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::dropNode( + const ::rtl::OUString& ) + throw( + MalformedDataException, + WrappedTargetException ) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::overrideProperty( + const ::rtl::OUString& aName, + sal_Int16, + const Type&, + sal_Bool ) + throw( + MalformedDataException, + WrappedTargetException ) +{ + if (aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Enable"))) + m_aStack.push(TElementStack::value_type(aName,ENABLE_JAVA)); + else if (aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UserClassPath"))) + m_aStack.push(TElementStack::value_type(aName, USER_CLASS_PATH)); +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::setPropertyValue( + const Any& aValue ) + throw( + MalformedDataException, + WrappedTargetException ) +{ + if ( !m_aStack.empty()) + { + switch (m_aStack.top().second) + { + case ENABLE_JAVA: + { + sal_Bool val = sal_Bool(); + if ((aValue >>= val) == sal_False) + throw MalformedDataException( + OUSTR("[Service implementation " IMPL_NAME + "] XLayerHandler::setPropertyValue received wrong type for Enable property"), 0, Any()); + if (jfw_setEnabled(val) != JFW_E_NONE) + throw WrappedTargetException( + OUSTR("[Service implementation " IMPL_NAME + "] XLayerHandler::setPropertyValue: jfw_setEnabled failed."), 0, Any()); + + break; + } + case USER_CLASS_PATH: + { + OUString cp; + if ((aValue >>= cp) == sal_False) + throw MalformedDataException( + OUSTR("[Service implementation " IMPL_NAME + "] XLayerHandler::setPropertyValue received wrong type for UserClassPath property"), 0, Any()); + + if (jfw_setUserClassPath(cp.pData) != JFW_E_NONE) + throw WrappedTargetException( + OUSTR("[Service implementation " IMPL_NAME + "] XLayerHandler::setPropertyValue: jfw_setUserClassPath failed."), 0, Any()); + break; + } + default: + OSL_ASSERT(0); + } + } +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::setPropertyValueForLocale( + const Any&, + const ::rtl::OUString& ) + throw( + MalformedDataException, + WrappedTargetException ) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::endProperty() + throw( + MalformedDataException, + WrappedTargetException ) +{ + if (!m_aStack.empty()) + m_aStack.pop(); +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::addProperty( + const rtl::OUString&, + sal_Int16, + const Type& ) + throw( + MalformedDataException, + WrappedTargetException ) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::addPropertyWithValue( + const rtl::OUString&, + sal_Int16, + const Any& ) + throw( + MalformedDataException, + WrappedTargetException ) +{ +} + +void SAL_CALL JavaMigration::addOrReplaceNodeFromTemplate( + const rtl::OUString&, + const TemplateIdentifier&, + sal_Int16 ) + throw( + MalformedDataException, + WrappedTargetException ) +{ +} + +// ----------------------------------------------------------------------------- +//ToDo enable java, user class path + +} //end namespace jfw + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/jvmfwk.hxx b/desktop/source/migration/services/jvmfwk.hxx new file mode 100644 index 000000000000..c1938e03ae87 --- /dev/null +++ b/desktop/source/migration/services/jvmfwk.hxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "cppuhelper/implbase3.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "boost/scoped_array.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/task/XJob.hpp" + + +namespace css = com::sun::star; + +namespace migration +{ + +rtl::OUString jvmfwk_getImplementationName(); + +css::uno::Sequence< rtl::OUString > jvmfwk_getSupportedServiceNames(); + +} //end blind namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/makefile.mk b/desktop/source/migration/services/makefile.mk new file mode 100755 index 000000000000..f74dec646b1d --- /dev/null +++ b/desktop/source/migration/services/makefile.mk @@ -0,0 +1,131 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = migrationoo2.uno +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = migrationoo2 +LIBTARGET=NO + +# --- Settings ----------------------------------------------------- + +.INCLUDE : ..$/..$/deployment/inc/dp_misc.mk +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : cppumaker.mk + +CFLAGS+= $(SYSTEM_DB_CFLAGS) + +SLOFILES= \ + $(SLO)$/jvmfwk.obj \ + $(SLO)$/cexports.obj \ + $(SLO)$/basicmigration.obj \ + $(SLO)$/wordbookmigration.obj \ + $(SLO)$/autocorrmigration.obj \ + $(SLO)$/oo3extensionmigration.obj \ + $(SLO)$/cexportsoo3.obj + +SHL1OBJS= \ + $(SLO)$/jvmfwk.obj \ + $(SLO)$/cexports.obj \ + $(SLO)$/basicmigration.obj \ + $(SLO)$/wordbookmigration.obj \ + $(SLO)$/autocorrmigration.obj + +SHL1TARGET=$(TARGET) +SHL1VERSIONMAP = $(SOLARENV)/src/component.map + +SHL1STDLIBS= \ + $(DEPLOYMENTMISCLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) \ + $(UCBHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(I18NISOLANGLIB) \ + $(JVMFWKLIB) \ + $(XMLSCRIPTLIB) \ + $(BERKELEYLIB) + +SHL1DEPN= +SHL1IMPLIB=imigrationoo2 +SHL1DEF=$(MISC)$/$(SHL1TARGET).def + +DEF1NAME=$(SHL1TARGET) + +COMP2TYPELIST = migrationoo3 +SHL2TARGET=migrationoo3.uno +SHL2VERSIONMAP = $(SOLARENV)/src/component.map + +SHL2OBJS= \ + $(SLO)$/cexportsoo3.obj \ + $(SLO)$/oo3extensionmigration.obj + +SHL2STDLIBS= \ + $(DEPLOYMENTMISCLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) \ + $(UCBHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(I18NISOLANGLIB) \ + $(JVMFWKLIB) \ + $(XMLSCRIPTLIB) \ + $(BERKELEYLIB) + +SHL2DEPN= +SHL2IMPLIB=imigrationoo3 +SHL2DEF=$(MISC)$/$(SHL2TARGET).def + +DEF2NAME=$(SHL2TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/migrationoo3.component + +$(MISC)/migrationoo3.component .ERRREMOVE : \ + $(SOLARENV)/bin/createcomponent.xslt migrationoo3.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL2TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt migrationoo3.component + +ALLTAR : $(MISC)/migrationoo2.component + +$(MISC)/migrationoo2.component .ERRREMOVE : \ + $(SOLARENV)/bin/createcomponent.xslt migrationoo2.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt migrationoo2.component diff --git a/desktop/source/migration/services/migrationoo2.component b/desktop/source/migration/services/migrationoo2.component new file mode 100755 index 000000000000..2b21ab123b9e --- /dev/null +++ b/desktop/source/migration/services/migrationoo2.component @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.desktop.migration.Basic"> + <service name="com.sun.star.migration.Basic"/> + </implementation> + <implementation name="com.sun.star.comp.desktop.migration.Wordbooks"> + <service name="com.sun.star.migration.Wordbooks"/> + </implementation> +</component> diff --git a/desktop/source/migration/services/migrationoo2.xml b/desktop/source/migration/services/migrationoo2.xml new file mode 100755 index 000000000000..5bda732f0fba --- /dev/null +++ b/desktop/source/migration/services/migrationoo2.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> migrationoo2.uno </module-name> + <component-description> + <author> Joachim Lingner </author> + <name> com.sun.star.comp.jvmfwk.MigrationOO2</name> + <description> +Specifies a factory object to create proxy objects. +These proxy object represent a given target object and can be +be aggregated. The proxy objects act UNO conform and do NOT provide +original target interfaces on queryInterface() calls. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> C++ </language> + <status value="final"/> + <supported-service> com.sun.star.reflection.ProxyFactory </supported-service> + <service-dependency> ... </service-dependency> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.WrappedTargetException </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.task.XJob </type> + <type> com.sun.star.beans.NamedValue </type> + <type> com.sun.star.configuration.backend.XLayer </type> + <type> com.sun.star.configuration.backend.XLayerHandler </type> + <type> com.sun.star.configuration.backend.MalformedDataException </type> + <type> com.sun.star.configuration.backend.TemplateIdentifier </type> + </component-description> + <component-description> + <author>Thomas Benisch</author> + <name>com.sun.star.comp.desktop.migration.Basic</name> + <description>migration service for OpenOffice.org Basic and dialogs</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.migration.Basic</supported-service> + <service-dependency>...</service-dependency> + <type>com.sun.star.beans.NamedValue</type> + <type>com.sun.star.lang.IllegalArgumentException</type> + <type>com.sun.star.lang.XInitialization</type> + <type>com.sun.star.task.XJob</type> + <type>com.sun.star.lang.XServiceInfo</type> + <type>com.sun.star.lang.XTypeProvider</type> + <type>com.sun.star.uno.XComponentContext</type> + </component-description> + <component-description> + <author>Thomas Benisch</author> + <name>com.sun.star.comp.desktop.migration.Autocorrection</name> + <description>migration service for OpenOffice.org autocorrection</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.migration.Autocorrection</supported-service> + <service-dependency>...</service-dependency> + <type>com.sun.star.beans.NamedValue</type> + <type>com.sun.star.lang.IllegalArgumentException</type> + <type>com.sun.star.lang.XInitialization</type> + <type>com.sun.star.task.XJob</type> + <type>com.sun.star.lang.XServiceInfo</type> + <type>com.sun.star.lang.XTypeProvider</type> + <type>com.sun.star.uno.XComponentContext</type> + </component-description> + <project-build-dependency>unotools</project-build-dependency> + <project-build-dependency>tools</project-build-dependency> + <project-build-dependency>cppuhelper</project-build-dependency> + <project-build-dependency>cppu</project-build-dependency> + <project-build-dependency>sal</project-build-dependency> + <runtime-module-dependency>utl</runtime-module-dependency> + <runtime-module-dependency>tl</runtime-module-dependency> + <runtime-module-dependency>cppuhelper3$(COM)</runtime-module-dependency> + <runtime-module-dependency>cppu3</runtime-module-dependency> + <runtime-module-dependency>sal3</runtime-module-dependency> +</module-description> diff --git a/desktop/source/migration/services/migrationoo3.component b/desktop/source/migration/services/migrationoo3.component new file mode 100755 index 000000000000..380c389ab7b9 --- /dev/null +++ b/desktop/source/migration/services/migrationoo3.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.desktop.migration.OOo3Extensions"> + <service name="com.sun.star.migration.Extensions"/> + </implementation> +</component> diff --git a/desktop/source/migration/services/misc.hxx b/desktop/source/migration/services/misc.hxx new file mode 100644 index 000000000000..54396863bb8c --- /dev/null +++ b/desktop/source/migration/services/misc.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_MISC_HXX_ +#define _DESKTOP_MISC_HXX_ + +#include <rtl/ustring.hxx> + +#include <vector> +#include <memory> + +//......................................................................... +namespace migration +{ +//......................................................................... + + typedef ::std::vector< ::rtl::OUString > TStringVector; + typedef ::std::auto_ptr< TStringVector > TStringVectorPtr; + +//......................................................................... +} // namespace migration +//......................................................................... + +#endif // _DESKTOP_MISC_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/oo3extensionmigration.cxx b/desktop/source/migration/services/oo3extensionmigration.cxx new file mode 100644 index 000000000000..dc508e712cc9 --- /dev/null +++ b/desktop/source/migration/services/oo3extensionmigration.cxx @@ -0,0 +1,564 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "oo3extensionmigration.hxx" +#include <rtl/instance.hxx> +#include <osl/file.hxx> +#include <osl/thread.h> +#include <tools/urlobj.hxx> +#include <unotools/bootstrap.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/textsearch.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/processfactory.hxx> +#include <ucbhelper/content.hxx> + +#include <com/sun/star/task/XInteractionApprove.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/xml/xpath/XXPathAPI.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/deployment/ExtensionManager.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace migration +{ + +static ::rtl::OUString sExtensionSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/uno_packages/" ) ); +static ::rtl::OUString sSubDirName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cache" ) ); +static ::rtl::OUString sConfigDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data" ) ); +static ::rtl::OUString sOrgDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org" ) ); +static ::rtl::OUString sExcludeDir1 = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org" ) ); +static ::rtl::OUString sExcludeDir2 = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org/openoffice" ) ); +static ::rtl::OUString sDescriptionXmlFile = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/description.xml" ) ); +static ::rtl::OUString sExtensionRootSubDirName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/uno_packages" ) ); + +static ::rtl::OUString sConfigurationDataType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.configuration-data")); +static ::rtl::OUString sConfigurationSchemaType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.configuration-schema")); + +// ============================================================================= +// component operations +// ============================================================================= + +::rtl::OUString OO3ExtensionMigration_getImplementationName() +{ + static ::rtl::OUString* pImplName = 0; + if ( !pImplName ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pImplName ) + { + static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.desktop.migration.OOo3Extensions" ) ); + pImplName = &aImplName; + } + } + return *pImplName; +} + +// ----------------------------------------------------------------------------- + +Sequence< ::rtl::OUString > OO3ExtensionMigration_getSupportedServiceNames() +{ + static Sequence< ::rtl::OUString >* pNames = 0; + if ( !pNames ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pNames ) + { + static Sequence< ::rtl::OUString > aNames(1); + aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Extensions" ) ); + pNames = &aNames; + } + } + return *pNames; +} + +// ============================================================================= +// ExtensionMigration +// ============================================================================= + +OO3ExtensionMigration::OO3ExtensionMigration(Reference< XComponentContext > const & ctx) : +m_ctx(ctx) +{ +} + +// ----------------------------------------------------------------------------- + +OO3ExtensionMigration::~OO3ExtensionMigration() +{ +} + +::osl::FileBase::RC OO3ExtensionMigration::checkAndCreateDirectory( INetURLObject& rDirURL ) +{ + ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + if ( aResult == ::osl::FileBase::E_NOENT ) + { + INetURLObject aBaseURL( rDirURL ); + aBaseURL.removeSegment(); + checkAndCreateDirectory( aBaseURL ); + return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + } + else + { + return aResult; + } +} + +void OO3ExtensionMigration::scanUserExtensions( const ::rtl::OUString& sSourceDir, TStringVector& aMigrateExtensions ) +{ + osl::Directory aScanRootDir( sSourceDir ); + osl::FileStatus fs(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL); + osl::FileBase::RC nRetCode = aScanRootDir.open(); + if ( nRetCode == osl::Directory::E_None ) + { + sal_uInt32 nHint( 0 ); + osl::DirectoryItem aItem; + while ( aScanRootDir.getNextItem( aItem, nHint ) == osl::Directory::E_None ) + { + if (( aItem.getFileStatus(fs) == osl::FileBase::E_None ) && + ( fs.getFileType() == osl::FileStatus::Directory )) + { + //Check next folder as the "real" extension folder is below a temp folder! + ::rtl::OUString sExtensionFolderURL = fs.getFileURL(); + + osl::DirectoryItem aExtDirItem; + osl::Directory aExtensionRootDir( sExtensionFolderURL ); + + nRetCode = aExtensionRootDir.open(); + if (( nRetCode == osl::Directory::E_None ) && + ( aExtensionRootDir.getNextItem( aExtDirItem, nHint ) == osl::Directory::E_None )) + { + bool bFileStatus = aExtDirItem.getFileStatus(fs) == osl::FileBase::E_None; + bool bIsDir = fs.getFileType() == osl::FileStatus::Directory; + + if ( bFileStatus && bIsDir ) + { + sExtensionFolderURL = fs.getFileURL(); + ScanResult eResult = scanExtensionFolder( sExtensionFolderURL ); + if ( eResult == SCANRESULT_MIGRATE_EXTENSION ) + aMigrateExtensions.push_back( sExtensionFolderURL ); + } + } + } + } + } +} + +OO3ExtensionMigration::ScanResult OO3ExtensionMigration::scanExtensionFolder( const ::rtl::OUString& sExtFolder ) +{ + ScanResult aResult = SCANRESULT_NOTFOUND; + osl::Directory aDir(sExtFolder); + + // get sub dirs + if (aDir.open() == osl::FileBase::E_None) + { + // work through directory contents... + osl::DirectoryItem item; + osl::FileStatus fs(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL); + TStringVector aDirectories; + while ((aDir.getNextItem(item) == osl::FileBase::E_None ) && + ( aResult == SCANRESULT_NOTFOUND )) + { + if (item.getFileStatus(fs) == osl::FileBase::E_None) + { + ::rtl::OUString aDirEntryURL; + if (fs.getFileType() == osl::FileStatus::Directory) + aDirectories.push_back( fs.getFileURL() ); + else + { + aDirEntryURL = fs.getFileURL(); + if ( aDirEntryURL.indexOf( sDescriptionXmlFile ) > 0 ) + aResult = scanDescriptionXml( aDirEntryURL ) ? SCANRESULT_MIGRATE_EXTENSION : SCANRESULT_DONTMIGRATE_EXTENSION; + } + } + } + + TStringVector::const_iterator pIter = aDirectories.begin(); + while ( pIter != aDirectories.end() && aResult == SCANRESULT_NOTFOUND ) + { + aResult = scanExtensionFolder( *pIter ); + ++pIter; + } + } + return aResult; +} + +bool OO3ExtensionMigration::scanDescriptionXml( const ::rtl::OUString& sDescriptionXmlURL ) +{ + if ( !m_xDocBuilder.is() ) + { + m_xDocBuilder = uno::Reference< xml::dom::XDocumentBuilder >( + m_ctx->getServiceManager()->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.dom.DocumentBuilder")), + m_ctx ), uno::UNO_QUERY ); + } + + if ( !m_xSimpleFileAccess.is() ) + { + m_xSimpleFileAccess = uno::Reference< ucb::XSimpleFileAccess >( + m_ctx->getServiceManager()->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.SimpleFileAccess")), + m_ctx ), uno::UNO_QUERY ); + } + + ::rtl::OUString aExtIdentifier; + if ( m_xDocBuilder.is() && m_xSimpleFileAccess.is() ) + { + try + { + uno::Reference< io::XInputStream > xIn = + m_xSimpleFileAccess->openFileRead( sDescriptionXmlURL ); + + if ( xIn.is() ) + { + uno::Reference< xml::dom::XDocument > xDoc = m_xDocBuilder->parse( xIn ); + if ( xDoc.is() ) + { + uno::Reference< xml::dom::XElement > xRoot = xDoc->getDocumentElement(); + if ( xRoot.is() && + xRoot->getTagName().equals(::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("description"))) ) + { + uno::Reference< xml::xpath::XXPathAPI > xPath( + m_ctx->getServiceManager()->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.xpath.XPathAPI")), + m_ctx), + uno::UNO_QUERY); + + xPath->registerNS( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc")), + xRoot->getNamespaceURI()); + xPath->registerNS( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xlink")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http://www.w3.org/1999/xlink"))); + + try + { + uno::Reference< xml::dom::XNode > xRootNode( xRoot, uno::UNO_QUERY ); + uno::Reference< xml::dom::XNode > xNode( + xPath->selectSingleNode( + xRootNode, + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:identifier/@value")) )); + if ( xNode.is() ) + aExtIdentifier = xNode->getNodeValue(); + } + catch ( xml::xpath::XPathException& ) + { + } + catch ( xml::dom::DOMException& ) + { + } + } + } + } + + if ( aExtIdentifier.getLength() > 0 ) + { + // scan extension identifier and try to match with our black list entries + for ( sal_uInt32 i = 0; i < m_aBlackList.size(); i++ ) + { + utl::SearchParam param(m_aBlackList[i], utl::SearchParam::SRCH_REGEXP); + utl::TextSearch ts(param, LANGUAGE_DONTKNOW); + + xub_StrLen start = 0; + xub_StrLen end = static_cast<sal_uInt16>(aExtIdentifier.getLength()); + if (ts.SearchFrwrd(aExtIdentifier, &start, &end)) + return false; + } + } + } + catch ( ucb::CommandAbortedException& ) + { + } + catch ( uno::RuntimeException& ) + { + } + + if ( aExtIdentifier.getLength() == 0 ) + { + // Fallback: + // Try to use the folder name to match our black list + // as some extensions don't provide an identifier in the + // description.xml! + for ( sal_uInt32 i = 0; i < m_aBlackList.size(); i++ ) + { + utl::SearchParam param(m_aBlackList[i], utl::SearchParam::SRCH_REGEXP); + utl::TextSearch ts(param, LANGUAGE_DONTKNOW); + + xub_StrLen start = 0; + xub_StrLen end = static_cast<sal_uInt16>(sDescriptionXmlURL.getLength()); + if (ts.SearchFrwrd(sDescriptionXmlURL, &start, &end)) + return false; + } + } + } + + return true; +} + +bool OO3ExtensionMigration::migrateExtension( const ::rtl::OUString& sSourceDir ) +{ + if ( !m_xExtensionManager.is() ) + { + try + { + m_xExtensionManager = deployment::ExtensionManager::get( m_ctx ); + } + catch ( ucb::CommandFailedException & ){} + catch ( uno::RuntimeException & ) {} + } + + if ( m_xExtensionManager.is() ) + { + try + { + TmpRepositoryCommandEnv* pCmdEnv = new TmpRepositoryCommandEnv(); + + uno::Reference< ucb::XCommandEnvironment > xCmdEnv( + static_cast< cppu::OWeakObject* >( pCmdEnv ), uno::UNO_QUERY ); + uno::Reference< task::XAbortChannel > xAbortChannel; + uno::Reference< deployment::XPackage > xPackage = + m_xExtensionManager->addExtension( + sSourceDir, uno::Sequence<beans::NamedValue>(), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user")), xAbortChannel, xCmdEnv ); + + if ( xPackage.is() ) + return true; + } + catch ( ucb::CommandFailedException& ) + { + } + catch ( ucb::CommandAbortedException& ) + { + } + catch ( lang::IllegalArgumentException& ) + { + } + } + + return false; +} + + +// ----------------------------------------------------------------------------- +// XServiceInfo +// ----------------------------------------------------------------------------- + +::rtl::OUString OO3ExtensionMigration::getImplementationName() throw (RuntimeException) +{ + return OO3ExtensionMigration_getImplementationName(); +} + +// ----------------------------------------------------------------------------- + +sal_Bool OO3ExtensionMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); + const ::rtl::OUString* pNames = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pNames + aNames.getLength(); + for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) + ; + + return pNames != pEnd; +} + +// ----------------------------------------------------------------------------- + +Sequence< ::rtl::OUString > OO3ExtensionMigration::getSupportedServiceNames() throw (RuntimeException) +{ + return OO3ExtensionMigration_getSupportedServiceNames(); +} + +// ----------------------------------------------------------------------------- +// XInitialization +// ----------------------------------------------------------------------------- + +void OO3ExtensionMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + const Any* pIter = aArguments.getConstArray(); + const Any* pEnd = pIter + aArguments.getLength(); + for ( ; pIter != pEnd ; ++pIter ) + { + beans::NamedValue aValue; + *pIter >>= aValue; + if ( aValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "UserData" ) ) ) + { + if ( !(aValue.Value >>= m_sSourceDir) ) + { + OSL_FAIL( "ExtensionMigration::initialize: argument UserData has wrong type!" ); + } + } + else if ( aValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ExtensionBlackList" ) ) ) + { + Sequence< ::rtl::OUString > aBlackList; + if ( (aValue.Value >>= aBlackList ) && ( aBlackList.getLength() > 0 )) + { + m_aBlackList.resize( aBlackList.getLength() ); + ::comphelper::sequenceToArray< ::rtl::OUString >( &m_aBlackList[0], aBlackList ); + } + } + } +} + +Any OO3ExtensionMigration::execute( const Sequence< beans::NamedValue >& ) + throw (lang::IllegalArgumentException, Exception, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( m_sTargetDir ); + if ( aStatus == ::utl::Bootstrap::PATH_EXISTS ) + { + // copy all extensions + ::rtl::OUString sSourceDir( m_sSourceDir ); + sSourceDir += sExtensionSubDir; + sSourceDir += sSubDirName; + sSourceDir += sExtensionRootSubDirName; + TStringVector aExtensionToMigrate; + scanUserExtensions( sSourceDir, aExtensionToMigrate ); + if ( aExtensionToMigrate.size() > 0 ) + { + TStringVector::iterator pIter = aExtensionToMigrate.begin(); + while ( pIter != aExtensionToMigrate.end() ) + { + migrateExtension( *pIter ); + ++pIter; + } + } + } + + return Any(); +} + +// ----------------------------------------------------------------------------- +// TmpRepositoryCommandEnv +// ----------------------------------------------------------------------------- + +TmpRepositoryCommandEnv::TmpRepositoryCommandEnv() +{ +} + +TmpRepositoryCommandEnv::~TmpRepositoryCommandEnv() +{ +} +// XCommandEnvironment +//______________________________________________________________________________ +uno::Reference< task::XInteractionHandler > TmpRepositoryCommandEnv::getInteractionHandler() +throw ( uno::RuntimeException ) +{ + return this; +} + +//______________________________________________________________________________ +uno::Reference< ucb::XProgressHandler > TmpRepositoryCommandEnv::getProgressHandler() +throw ( uno::RuntimeException ) +{ + return this; +} + +// XInteractionHandler +void TmpRepositoryCommandEnv::handle( + uno::Reference< task::XInteractionRequest> const & xRequest ) + throw ( uno::RuntimeException ) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + bool approve = true; + bool abort = false; + + // select: + uno::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) { + uno::Reference< task::XInteractionApprove > xInteractionApprove( + pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + // don't query again for ongoing continuations: + approve = false; + } + } + else if (abort) { + uno::Reference< task::XInteractionAbort > xInteractionAbort( + pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionAbort.is()) { + xInteractionAbort->select(); + // don't query again for ongoing continuations: + abort = false; + } + } + } +} + +// XProgressHandler +void TmpRepositoryCommandEnv::push( uno::Any const & /*Status*/ ) +throw (uno::RuntimeException) +{ +} + + +void TmpRepositoryCommandEnv::update( uno::Any const & /*Status */) +throw (uno::RuntimeException) +{ +} + +void TmpRepositoryCommandEnv::pop() throw (uno::RuntimeException) +{ +} + +// ============================================================================= +// component operations +// ============================================================================= + +Reference< XInterface > SAL_CALL OO3ExtensionMigration_create( + Reference< XComponentContext > const & ctx ) + SAL_THROW( () ) +{ + return static_cast< lang::XTypeProvider * >( new OO3ExtensionMigration( + ctx) ); +} + +// ----------------------------------------------------------------------------- + +} // namespace migration + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/oo3extensionmigration.hxx b/desktop/source/migration/services/oo3extensionmigration.hxx new file mode 100644 index 000000000000..adadb3b293e6 --- /dev/null +++ b/desktop/source/migration/services/oo3extensionmigration.hxx @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_OO3EXTENSIONMIGRATION_HXX_ +#define _DESKTOP_OO3EXTENSIONMIGRATION_HXX_ + +#include "misc.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/deployment/XExtensionManager.hpp> + +#include <osl/mutex.hxx> +#include <osl/file.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/compbase3.hxx> +#include <ucbhelper/content.hxx> +#include <xmlscript/xmllib_imexp.hxx> + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace deployment { + class XPackage; + } +}}} + +class INetURLObject; + + +namespace migration +{ + + ::rtl::OUString SAL_CALL OO3ExtensionMigration_getImplementationName(); + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL OO3ExtensionMigration_getSupportedServiceNames(); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL OO3ExtensionMigration_create( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xContext ) + SAL_THROW( (::com::sun::star::uno::Exception) ); + + + // ============================================================================= + // class ExtensionMigration + // ============================================================================= + + typedef ::cppu::WeakImplHelper3< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::task::XJob > ExtensionMigration_BASE; + + class OO3ExtensionMigration : public ExtensionMigration_BASE + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_ctx; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XDocumentBuilder > m_xDocBuilder; + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > m_xSimpleFileAccess; + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > m_xExtensionManager; + ::osl::Mutex m_aMutex; + ::rtl::OUString m_sSourceDir; + ::rtl::OUString m_sTargetDir; + TStringVector m_aBlackList; + + enum ScanResult + { + SCANRESULT_NOTFOUND, + SCANRESULT_MIGRATE_EXTENSION, + SCANRESULT_DONTMIGRATE_EXTENSION + }; + + ::osl::FileBase::RC checkAndCreateDirectory( INetURLObject& rDirURL ); + ScanResult scanExtensionFolder( const ::rtl::OUString& sExtFolder ); + void scanUserExtensions( const ::rtl::OUString& sSourceDir, TStringVector& aMigrateExtensions ); + bool scanDescriptionXml( const ::rtl::OUString& sDescriptionXmlFilePath ); + bool migrateExtension( const ::rtl::OUString& sSourceDir ); + + public: + OO3ExtensionMigration(::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const & ctx); + virtual ~OO3ExtensionMigration(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XJob + virtual ::com::sun::star::uno::Any SAL_CALL execute( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& Arguments ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + }; + + class TmpRepositoryCommandEnv + : public ::cppu::WeakImplHelper3< ::com::sun::star::ucb::XCommandEnvironment, + ::com::sun::star::task::XInteractionHandler, + ::com::sun::star::ucb::XProgressHandler > + { + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler> m_forwardHandler; + public: + virtual ~TmpRepositoryCommandEnv(); + TmpRepositoryCommandEnv(); + + // XCommandEnvironment + virtual ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw ( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw ( ::com::sun::star::uno::RuntimeException ); + + // XInteractionHandler + virtual void SAL_CALL handle( + ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest > const & xRequest ) + throw (::com::sun::star::uno::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( ::com::sun::star::uno::Any const & Status ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL update( ::com::sun::star::uno::Any const & Status ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL pop() throw (::com::sun::star::uno::RuntimeException); + }; + +//......................................................................... +} // namespace migration +//......................................................................... + +#endif // _DESKTOP_OO3EXTENSIONMIGRATION_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/wordbookmigration.cxx b/desktop/source/migration/services/wordbookmigration.cxx new file mode 100644 index 000000000000..dc3c73efff5b --- /dev/null +++ b/desktop/source/migration/services/wordbookmigration.cxx @@ -0,0 +1,325 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "wordbookmigration.hxx" +#include <tools/urlobj.hxx> +#include <unotools/bootstrap.hxx> +#include <unotools/ucbstreamhelper.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + + static ::rtl::OUString sSourceSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/wordbook" ) ); + static ::rtl::OUString sTargetSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/wordbook" ) ); + static ::rtl::OUString sBaseName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/wordbook" ) ); + static ::rtl::OUString sSuffix = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".dic" ) ); + + + // ============================================================================= + // component operations + // ============================================================================= + + ::rtl::OUString WordbookMigration_getImplementationName() + { + static ::rtl::OUString* pImplName = 0; + if ( !pImplName ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pImplName ) + { + static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.desktop.migration.Wordbooks" ) ); + pImplName = &aImplName; + } + } + return *pImplName; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > WordbookMigration_getSupportedServiceNames() + { + static Sequence< ::rtl::OUString >* pNames = 0; + if ( !pNames ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pNames ) + { + static Sequence< ::rtl::OUString > aNames(1); + aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Wordbooks" ) ); + pNames = &aNames; + } + } + return *pNames; + } + + // ============================================================================= + // WordbookMigration + // ============================================================================= + + WordbookMigration::WordbookMigration() + { + } + + // ----------------------------------------------------------------------------- + + WordbookMigration::~WordbookMigration() + { + } + + // ----------------------------------------------------------------------------- + + TStringVectorPtr WordbookMigration::getFiles( const ::rtl::OUString& rBaseURL ) const + { + TStringVectorPtr aResult( new TStringVector ); + ::osl::Directory aDir( rBaseURL); + + if ( aDir.open() == ::osl::FileBase::E_None ) + { + // iterate over directory content + TStringVector aSubDirs; + ::osl::DirectoryItem aItem; + while ( aDir.getNextItem( aItem ) == ::osl::FileBase::E_None ) + { + ::osl::FileStatus aFileStatus( osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL ); + if ( aItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None ) + { + if ( aFileStatus.getFileType() == ::osl::FileStatus::Directory ) + aSubDirs.push_back( aFileStatus.getFileURL() ); + else + aResult->push_back( aFileStatus.getFileURL() ); + } + } + + // iterate recursive over subfolders + TStringVector::const_iterator aI = aSubDirs.begin(); + while ( aI != aSubDirs.end() ) + { + TStringVectorPtr aSubResult = getFiles( *aI ); + aResult->insert( aResult->end(), aSubResult->begin(), aSubResult->end() ); + ++aI; + } + } + + return aResult; + } + + // ----------------------------------------------------------------------------- + + ::osl::FileBase::RC WordbookMigration::checkAndCreateDirectory( INetURLObject& rDirURL ) + { + ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + if ( aResult == ::osl::FileBase::E_NOENT ) + { + INetURLObject aBaseURL( rDirURL ); + aBaseURL.removeSegment(); + checkAndCreateDirectory( aBaseURL ); + return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + } + else + { + return aResult; + } + } + +#define MAX_HEADER_LENGTH 16 +bool IsUserWordbook( const ::rtl::OUString& rFile ) +{ + static const sal_Char* pVerStr2 = "WBSWG2"; + static const sal_Char* pVerStr5 = "WBSWG5"; + static const sal_Char* pVerStr6 = "WBSWG6"; + static const sal_Char* pVerOOo7 = "OOoUserDict1"; + + bool bRet = false; + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( String(rFile), STREAM_STD_READ ); + if ( pStream && !pStream->GetError() ) + { + sal_Size nSniffPos = pStream->Tell(); + static sal_Size nVerOOo7Len = sal::static_int_cast< sal_Size >(strlen( pVerOOo7 )); + sal_Char pMagicHeader[MAX_HEADER_LENGTH]; + pMagicHeader[ nVerOOo7Len ] = '\0'; + if ((pStream->Read((void *) pMagicHeader, nVerOOo7Len) == nVerOOo7Len)) + { + if ( !strcmp(pMagicHeader, pVerOOo7) ) + bRet = true; + else + { + sal_uInt16 nLen; + pStream->Seek (nSniffPos); + *pStream >> nLen; + if ( nLen < MAX_HEADER_LENGTH ) + { + pStream->Read(pMagicHeader, nLen); + pMagicHeader[nLen] = '\0'; + if ( !strcmp(pMagicHeader, pVerStr2) + || !strcmp(pMagicHeader, pVerStr5) + || !strcmp(pMagicHeader, pVerStr6) ) + bRet = true; + } + } + } + } + + delete pStream; + return bRet; +} + + + // ----------------------------------------------------------------------------- + + void WordbookMigration::copyFiles() + { + ::rtl::OUString sTargetDir; + ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( sTargetDir ); + if ( aStatus == ::utl::Bootstrap::PATH_EXISTS ) + { + sTargetDir += sTargetSubDir; + TStringVectorPtr aFileList = getFiles( m_sSourceDir ); + TStringVector::const_iterator aI = aFileList->begin(); + while ( aI != aFileList->end() ) + { + if (IsUserWordbook(*aI) ) + { + ::rtl::OUString sSourceLocalName = aI->copy( m_sSourceDir.getLength() ); + ::rtl::OUString sTargetName = sTargetDir + sSourceLocalName; + INetURLObject aURL( sTargetName ); + aURL.removeSegment(); + checkAndCreateDirectory( aURL ); + ::osl::FileBase::RC aResult = ::osl::File::copy( *aI, sTargetName ); + if ( aResult != ::osl::FileBase::E_None ) + { + ::rtl::OString aMsg( "WordbookMigration::copyFiles: cannot copy " ); + aMsg += ::rtl::OUStringToOString( *aI, RTL_TEXTENCODING_UTF8 ) + " to " + + ::rtl::OUStringToOString( sTargetName, RTL_TEXTENCODING_UTF8 ); + OSL_FAIL( aMsg.getStr() ); + } + } + ++aI; + } + } + else + { + OSL_FAIL( "WordbookMigration::copyFiles: no user installation!" ); + } + } + + // ----------------------------------------------------------------------------- + // XServiceInfo + // ----------------------------------------------------------------------------- + + ::rtl::OUString WordbookMigration::getImplementationName() throw (RuntimeException) + { + return WordbookMigration_getImplementationName(); + } + + // ----------------------------------------------------------------------------- + + sal_Bool WordbookMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); + const ::rtl::OUString* pNames = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pNames + aNames.getLength(); + for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) + ; + + return pNames != pEnd; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > WordbookMigration::getSupportedServiceNames() throw (RuntimeException) + { + return WordbookMigration_getSupportedServiceNames(); + } + + // ----------------------------------------------------------------------------- + // XInitialization + // ----------------------------------------------------------------------------- + + void WordbookMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + const Any* pIter = aArguments.getConstArray(); + const Any* pEnd = pIter + aArguments.getLength(); + for ( ; pIter != pEnd ; ++pIter ) + { + beans::NamedValue aValue; + *pIter >>= aValue; + if ( aValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "UserData" ) ) ) + { + if ( !(aValue.Value >>= m_sSourceDir) ) + { + OSL_FAIL( "WordbookMigration::initialize: argument UserData has wrong type!" ); + } + m_sSourceDir += sSourceSubDir; + break; + } + } + } + + // ----------------------------------------------------------------------------- + // XJob + // ----------------------------------------------------------------------------- + + Any WordbookMigration::execute( const Sequence< beans::NamedValue >& ) + throw (lang::IllegalArgumentException, Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + copyFiles(); + + return Any(); + } + + // ============================================================================= + // component operations + // ============================================================================= + + Reference< XInterface > SAL_CALL WordbookMigration_create( + Reference< XComponentContext > const & ) + SAL_THROW( () ) + { + return static_cast< lang::XTypeProvider * >( new WordbookMigration() ); + } + + // ----------------------------------------------------------------------------- + +//......................................................................... +} // namespace migration +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/wordbookmigration.hxx b/desktop/source/migration/services/wordbookmigration.hxx new file mode 100644 index 000000000000..72077e16b657 --- /dev/null +++ b/desktop/source/migration/services/wordbookmigration.hxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _DESKTOP_WORDBOOKMIGRATION_HXX_ +#define _DESKTOP_WORDBOOKMIGRATION_HXX_ + +#include "misc.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase3.hxx> +#include <osl/mutex.hxx> +#include <osl/file.hxx> + + +class INetURLObject; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + ::rtl::OUString SAL_CALL WordbookMigration_getImplementationName(); + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL WordbookMigration_getSupportedServiceNames(); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL WordbookMigration_create( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xContext ) + SAL_THROW( (::com::sun::star::uno::Exception) ); + + + // ============================================================================= + // class WordbookMigration + // ============================================================================= + + typedef ::cppu::WeakImplHelper3< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::task::XJob > WordbookMigration_BASE; + + class WordbookMigration : public WordbookMigration_BASE + { + private: + ::osl::Mutex m_aMutex; + ::rtl::OUString m_sSourceDir; + + TStringVectorPtr getFiles( const ::rtl::OUString& rBaseURL ) const; + ::osl::FileBase::RC checkAndCreateDirectory( INetURLObject& rDirURL ); + void copyFiles(); + + public: + WordbookMigration(); + virtual ~WordbookMigration(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XJob + virtual ::com::sun::star::uno::Any SAL_CALL execute( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& Arguments ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + }; + +//......................................................................... +} // namespace migration +//......................................................................... + +#endif // _DESKTOP_AUTOCORRMIGRATION_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/offacc/acceptor.cxx b/desktop/source/offacc/acceptor.cxx new file mode 100644 index 000000000000..dc40670e9535 --- /dev/null +++ b/desktop/source/offacc/acceptor.cxx @@ -0,0 +1,331 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "acceptor.hxx" +#include <unotools/bootstrap.hxx> +#include <tools/urlobj.hxx> +#include <tools/stream.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/uno/XNamingService.hpp> + +#include <cppuhelper/factory.hxx> + +namespace desktop +{ + +extern "C" void workerfunc (void * acc) +{ + ((Acceptor*)acc)->run(); +} + +static Reference<XInterface> getComponentContext( const Reference<XMultiServiceFactory>& rFactory) +{ + Reference<XInterface> rContext; + Reference< XPropertySet > rPropSet( rFactory, UNO_QUERY ); + Any a = rPropSet->getPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ); + a >>= rContext; + return rContext; +} + +Mutex Acceptor::m_aMutex; + +Acceptor::Acceptor( const Reference< XMultiServiceFactory >& rFactory ) + : m_thread(NULL) + , m_aAcceptString() + , m_aConnectString() + , m_aProtocol() + , m_bInit(sal_False) + , m_bDying(false) +{ + m_rSMgr = rFactory; + m_rAcceptor = Reference< XAcceptor > (m_rSMgr->createInstance( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.connection.Acceptor" ))), + UNO_QUERY ); + m_rBridgeFactory = Reference < XBridgeFactory > (m_rSMgr->createInstance( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.bridge.BridgeFactory" ))), + UNO_QUERY ); + // get component context + m_rContext = getComponentContext(m_rSMgr); +} + + +Acceptor::~Acceptor() +{ + m_rAcceptor->stopAccepting(); + oslThread t; + { + osl::MutexGuard g(m_aMutex); + t = m_thread; + } + //prevent locking if the thread is still waiting + m_bDying = true; + m_cEnable.set(); + osl_joinWithThread(t); + { + // Make the final state of m_bridges visible to this thread (since + // m_thread is joined, the code that follows is the only one left + // accessing m_bridges): + osl::MutexGuard g(m_aMutex); + } + for (;;) { + com::sun::star::uno::Reference< com::sun::star::bridge::XBridge > b( + m_bridges.remove()); + if (!b.is()) { + break; + } + com::sun::star::uno::Reference< com::sun::star::lang::XComponent >( + b, com::sun::star::uno::UNO_QUERY_THROW)->dispose(); + } +} + +void SAL_CALL Acceptor::run() +{ + while ( m_rAcceptor.is() && m_rBridgeFactory.is() ) + { + RTL_LOGFILE_CONTEXT( aLog, "desktop (lo119109) Acceptor::run" ); + try + { + // wait until we get enabled + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\ + "Acceptor::run waiting for office to come up"); + m_cEnable.wait(); + if (m_bDying) //see destructor + break; + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\ + "Acceptor::run now enabled and continuing"); + + // accept connection + Reference< XConnection > rConnection = m_rAcceptor->accept( m_aConnectString ); + // if we return without a valid connection we mus assume that the acceptor + // is destructed so we break out of the run method terminating the thread + if (! rConnection.is()) break; + OUString aDescription = rConnection->getDescription(); + RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::run connection %s", + OUStringToOString(aDescription, RTL_TEXTENCODING_ASCII_US).getStr()); + + // create instanceprovider for this connection + Reference< XInstanceProvider > rInstanceProvider( + (XInstanceProvider*)new AccInstanceProvider(m_rSMgr, rConnection)); + // create the bridge. The remote end will have a reference to this bridge + // thus preventing the bridge from being disposed. When the remote end releases + // the bridge, it will be destructed. + Reference< XBridge > rBridge = m_rBridgeFactory->createBridge( + rtl::OUString() ,m_aProtocol ,rConnection ,rInstanceProvider ); + osl::MutexGuard g(m_aMutex); + m_bridges.add(rBridge); + } catch (Exception&) { + // connection failed... + // something went wrong during connection setup. + // just wait for a new connection to accept + } + } +} + +// XInitialize +void SAL_CALL Acceptor::initialize( const Sequence<Any>& aArguments ) + throw( Exception ) +{ + // prevent multiple initialization + ClearableMutexGuard aGuard( m_aMutex ); + RTL_LOGFILE_CONTEXT( aLog, "destop (lo119109) Acceptor::initialize()" ); + + sal_Bool bOk = sal_False; + + // arg count + int nArgs = aArguments.getLength(); + + // not yet initialized and acceptstring + if (!m_bInit && nArgs > 0 && (aArguments[0] >>= m_aAcceptString)) + { + RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::initialize string=%s", + OUStringToOString(m_aAcceptString, RTL_TEXTENCODING_ASCII_US).getStr()); + + // get connect string and protocol from accept string + // "<connectString>;<protocol>" + sal_Int32 nIndex1 = m_aAcceptString.indexOf( (sal_Unicode) ';' ); + if (nIndex1 < 0) throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("Invalid accept-string format")), m_rContext, 1); + m_aConnectString = m_aAcceptString.copy( 0 , nIndex1 ).trim(); + nIndex1++; + sal_Int32 nIndex2 = m_aAcceptString.indexOf( (sal_Unicode) ';' , nIndex1 ); + if (nIndex2 < 0) nIndex2 = m_aAcceptString.getLength(); + m_aProtocol = m_aAcceptString.copy( nIndex1, nIndex2 - nIndex1 ); + + // start accepting in new thread... + m_thread = osl_createThread(workerfunc, this); + m_bInit = sal_True; + bOk = sal_True; + } + + // do we want to enable accepting? + sal_Bool bEnable = sal_False; + if (((nArgs == 1 && (aArguments[0] >>= bEnable)) || + (nArgs == 2 && (aArguments[1] >>= bEnable))) && + bEnable ) + { + m_cEnable.set(); + bOk = sal_True; + } + + if (!bOk) + { + throw IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("invalid initialization")), m_rContext, 1); + } +} + +// XServiceInfo +const sal_Char *Acceptor::serviceName = "com.sun.star.office.Acceptor"; +const sal_Char *Acceptor::implementationName = "com.sun.star.office.comp.Acceptor"; +const sal_Char *Acceptor::supportedServiceNames[] = {"com.sun.star.office.Acceptor", NULL}; +OUString Acceptor::impl_getImplementationName() +{ + return OUString::createFromAscii( implementationName ); +} +OUString SAL_CALL Acceptor::getImplementationName() + throw (RuntimeException) +{ + return Acceptor::impl_getImplementationName(); +} +Sequence<OUString> Acceptor::impl_getSupportedServiceNames() +{ + Sequence<OUString> aSequence; + for (int i=0; supportedServiceNames[i]!=NULL; i++) { + aSequence.realloc(i+1); + aSequence[i]=(OUString::createFromAscii(supportedServiceNames[i])); + } + return aSequence; +} +Sequence<OUString> SAL_CALL Acceptor::getSupportedServiceNames() + throw (RuntimeException) +{ + return Acceptor::impl_getSupportedServiceNames(); +} +sal_Bool SAL_CALL Acceptor::supportsService( const OUString&) + throw (RuntimeException) +{ + return sal_False; +} + +// Factory +Reference< XInterface > Acceptor::impl_getInstance( const Reference< XMultiServiceFactory >& aFactory ) +{ + try { + return (XComponent*) new Acceptor( aFactory ); + } catch ( Exception& ) { + return (XComponent*) NULL; + } +} + +// InstanceProvider +AccInstanceProvider::AccInstanceProvider(const Reference<XMultiServiceFactory>& aFactory, const Reference<XConnection>& rConnection) +{ + m_rSMgr = aFactory; + m_rConnection = rConnection; +} + +AccInstanceProvider::~AccInstanceProvider() +{ +} + +Reference<XInterface> SAL_CALL AccInstanceProvider::getInstance (const OUString& aName ) + throw ( NoSuchElementException ) +{ + + Reference<XInterface> rInstance; + + if ( aName.compareToAscii( "StarOffice.ServiceManager" ) == 0) + { + rInstance = Reference< XInterface >( m_rSMgr ); + } + else if(aName.compareToAscii( "StarOffice.ComponentContext" ) == 0 ) + { + rInstance = getComponentContext( m_rSMgr ); + } + else if ( aName.compareToAscii("StarOffice.NamingService" ) == 0 ) + { + Reference< XNamingService > rNamingService( + m_rSMgr->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uno.NamingService" ))), + UNO_QUERY ); + if ( rNamingService.is() ) + { + rNamingService->registerObject( + OUString(RTL_CONSTASCII_USTRINGPARAM( "StarOffice.ServiceManager" )), m_rSMgr ); + rNamingService->registerObject( + OUString(RTL_CONSTASCII_USTRINGPARAM( "StarOffice.ComponentContext" )), getComponentContext( m_rSMgr )); + rInstance = rNamingService; + } + } + return rInstance; +} + +} + +// component management stuff... +// ---------------------------------------------------------------------------- +extern "C" +{ +using namespace desktop; + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void *) +{ + void* pReturn = NULL ; + if ( pImplementationName && pServiceManager ) + { + // Define variables which are used in following macros. + Reference< XSingleServiceFactory > xFactory; + Reference< XMultiServiceFactory > xServiceManager( + reinterpret_cast< XMultiServiceFactory* >(pServiceManager)); + + if (Acceptor::impl_getImplementationName().compareToAscii( pImplementationName ) == COMPARE_EQUAL ) + { + xFactory = Reference< XSingleServiceFactory >( cppu::createSingleFactory( + xServiceManager, Acceptor::impl_getImplementationName(), + Acceptor::impl_getInstance, Acceptor::impl_getSupportedServiceNames()) ); + } + + // Factory is valid - service was found. + if ( xFactory.is() ) + { + xFactory->acquire(); + pReturn = xFactory.get(); + } + } + + // Return with result of this operation. + return pReturn ; +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/offacc/acceptor.hxx b/desktop/source/offacc/acceptor.hxx new file mode 100644 index 000000000000..e4e22da631bd --- /dev/null +++ b/desktop/source/offacc/acceptor.hxx @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/connection/XAcceptor.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/bridge/XInstanceProvider.hpp> +#include <com/sun/star/bridge/XBridgeFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <rtl/logfile.hxx> + +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <comphelper/weakbag.hxx> +#include <osl/mutex.hxx> +#include <osl/conditn.hxx> +#include <osl/thread.hxx> + + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::bridge; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::connection; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::registry; + +namespace desktop { + +class Acceptor + : public ::cppu::WeakImplHelper2<XServiceInfo, XInitialization> +{ +private: + static const sal_Char *serviceName; + static const sal_Char *implementationName; + static const sal_Char *supportedServiceNames[]; + + static Mutex m_aMutex; + + oslThread m_thread; + comphelper::WeakBag< com::sun::star::bridge::XBridge > m_bridges; + + Condition m_cEnable; + + Reference< XMultiServiceFactory > m_rSMgr; + Reference< XInterface > m_rContext; + Reference< XAcceptor > m_rAcceptor; + Reference< XBridgeFactory > m_rBridgeFactory; + + OUString m_aAcceptString; + OUString m_aConnectString; + OUString m_aProtocol; + + sal_Bool m_bInit; + bool m_bDying; + +public: + Acceptor( const Reference< XMultiServiceFactory >& aFactory ); + virtual ~Acceptor(); + + void SAL_CALL run(); + + // XService info + static OUString impl_getImplementationName(); + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + static Sequence<OUString> impl_getSupportedServiceNames(); + virtual Sequence<OUString> SAL_CALL getSupportedServiceNames() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString& aName ) + throw (RuntimeException); + + // XInitialize + virtual void SAL_CALL initialize( const Sequence<Any>& aArguments ) + throw ( Exception ); + + static Reference<XInterface> impl_getInstance( const Reference< XMultiServiceFactory >& aFactory ); +}; + +class AccInstanceProvider : public ::cppu::WeakImplHelper1<XInstanceProvider> +{ +private: + Reference<XMultiServiceFactory> m_rSMgr; + Reference<XConnection> m_rConnection; + +public: + AccInstanceProvider(const Reference< XMultiServiceFactory >& aFactory, + const Reference< XConnection >& rConnection); + virtual ~AccInstanceProvider(); + + // XInstanceProvider + virtual Reference<XInterface> SAL_CALL getInstance (const OUString& aName ) + throw ( NoSuchElementException ); +}; + + +} //namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/offacc/makefile.mk b/desktop/source/offacc/makefile.mk new file mode 100755 index 000000000000..809c28414bef --- /dev/null +++ b/desktop/source/offacc/makefile.mk @@ -0,0 +1,70 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=offacc +LIBTARGET=NO + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +SLOFILES = $(SLO)$/acceptor.obj + +SHL1DEPN= makefile.mk +SHL1OBJS= $(SLOFILES) + +SHL1TARGET= $(TARGET)$(DLLPOSTFIX) +SHL1IMPLIB= i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +SHL1STDLIBS= \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + + +ALLTAR : $(MISC)/offacc.component + +$(MISC)/offacc.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + offacc.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt offacc.component diff --git a/desktop/source/offacc/offacc.component b/desktop/source/offacc/offacc.component new file mode 100755 index 000000000000..6f0d4a97a2d2 --- /dev/null +++ b/desktop/source/offacc/offacc.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.office.comp.Acceptor"> + <service name="com.sun.star.office.Acceptor"/> + </implementation> +</component> diff --git a/desktop/source/pagein/makefile.mk b/desktop/source/pagein/makefile.mk new file mode 100755 index 000000000000..1125e45b1a41 --- /dev/null +++ b/desktop/source/pagein/makefile.mk @@ -0,0 +1,169 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=pagein + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +.INCLUDE .IGNORE : icuversion.mk + +# --- Targets ------------------------------------------------------ + +ALL: \ + $(MISC)$/$(TARGET)-calc \ + $(MISC)$/$(TARGET)-draw \ + $(MISC)$/$(TARGET)-impress \ + $(MISC)$/$(TARGET)-writer \ + $(MISC)$/$(TARGET)-common \ + ALLTAR + +.INCLUDE : target.mk + +ICUDLLPOST=$(DLLPOST).$(ICU_MAJOR)$(ICU_MINOR) +UDKDLLPOST=$(DLLPOST).$(UDK_MAJOR) +UNODLLPOST=.uno$(DLLPOST) +DFTDLLPOST=$(DLLPOSTFIX)$(DLLPOST) # Default + +URELIBPATH=..$/ure-link$/lib +UREMISCPATH=..$/ure-link$/share$/misc + +$(MISC)$/$(TARGET)-calc : makefile.mk + @echo Making: $@ + @-echo $(DLLPRE)sc$(DFTDLLPOST) > $@ + @-echo $(DLLPRE)scui$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svxcore$(DFTDLLPOST) >> $@ + +$(MISC)$/$(TARGET)-draw : makefile.mk + @echo Making: $@ + @-echo $(DLLPRE)sd$(DFTDLLPOST) > $@ + @-echo $(DLLPRE)sdui$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svxcore$(DFTDLLPOST) >> $@ + +$(MISC)$/$(TARGET)-impress : makefile.mk + @echo Making: $@ + @-echo $(DLLPRE)sd$(DFTDLLPOST) > $@ + @-echo $(DLLPRE)sdui$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svxcore$(DFTDLLPOST) >> $@ + +$(MISC)$/$(TARGET)-writer : makefile.mk + @echo Making: $@ + @-echo $(DLLPRE)sw$(DFTDLLPOST) > $@ + @-echo $(DLLPRE)swui$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svxcore$(DFTDLLPOST) >> $@ + +# sorted in approx. reverse load order (ld.so.1) +$(MISC)$/$(TARGET)-common : makefile.mk + @echo Making: $@ + @-echo i18npool$(UNODLLPOST) > $@ +.IF "$(SYSTEM_ICU)" != "YES" + @-echo $(DLLPRE)icui18n$(ICUDLLPOST) >> $@ + @-echo $(DLLPRE)icule$(ICUDLLPOST) >> $@ + @-echo $(DLLPRE)icuuc$(ICUDLLPOST) >> $@ +# @-echo $(DLLPRE)icudata$(ICUDLLPOST) >> $@ - a huge dll, almost none of it used +.ENDIF # SYSTEM_ICU +# + @-echo $(DLLPRE)lng$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)xo$(DFTDLLPOST) >> $@ +# + + @-echo $(DLLPRE)fwe$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)fwk$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)fwi$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)fwl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)package2$(DLLPOST) >> $@ + @-echo $(DLLPRE)ucpfile1$(DLLPOST) >> $@ + @-echo $(DLLPRE)ucb1$(DLLPOST) >> $@ + @-echo configmgr$(UNODLLPOST) >> $@ +# + @-echo $(DLLPRE)vclplug_gen$(DFTDLLPOST) >> $@ +.IF "$(ENABLE_GTK)" != "" + @-echo $(DLLPRE)vclplug_gtk$(DFTDLLPOST) >> $@ +.ENDIF # ENABLE_GTK +.IF "$(ENABLE_KDE)" != "" + @-echo $(DLLPRE)vclplug_kde$(DFTDLLPOST) >> $@ +.ENDIF # ENABLE_KDE +# + @-echo $(DLLPRE)basegfx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)sot$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)xcr$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)sb$(DFTDLLPOST) >> $@ +# +# uno runtime environment +# + @-echo $(URELIBPATH)$/stocservices$(UNODLLPOST) >> $@ + @-echo $(URELIBPATH)$/bootstrap$(UNODLLPOST) >> $@ + @-echo $(URELIBPATH)$/$(DLLPRE)reg$(UDKDLLPOST) >> $@ + @-echo $(URELIBPATH)$/$(DLLPRE)store$(UDKDLLPOST) >> $@ + @-echo $(URELIBPATH)$/reflection$(UNODLLPOST) >> $@ + @-echo $(URELIBPATH)$/$(DLLPRE)uno_cppuhelper$(COMID)$(UDKDLLPOST) >> $@ + @-echo $(URELIBPATH)$/$(DLLPRE)uno_cppu$(UDKDLLPOST) >> $@ + @-echo $(URELIBPATH)$/$(DLLPRE)uno_sal$(UDKDLLPOST) >> $@ +# + @-echo $(DLLPRE)ucbhelper$(UCBHELPER_MAJOR)$(COMID)$(DLLPOST) >> $@ + @-echo $(DLLPRE)comphelp$(COMPHLP_MAJOR)$(COMID)$(DLLPOST) >> $@ + @-echo $(DLLPRE)tl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)utl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)vcl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)tk$(DFTDLLPOST) >> $@ + @-echo $(UREMISCPATH)$/types.rdb >> $@ + @-echo services.rdb >> $@ + @-echo oovbaapi.rdb >> $@ + @-echo deployment$(DLLPOSTFIX)$(UNODLLPOST) >> $@ + @-echo $(DLLPRE)deploymentmisc$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)ucb1$(DLLPOST) >> $@ + @-echo $(DLLPRE)xstor$(DLLPOST) >> $@ + @-echo $(DLLPRE)package2$(DLLPOST) >> $@ + @-echo $(DLLPRE)filterconfig1$(DLLPOST) >> $@ + @-echo $(DLLPRE)uui$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)lng$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svt$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)spl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)basegfx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)avmedia$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)helplinker$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)vclplug_gen$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)icule$(ICUDLLPOST) >> $@ + @-echo sax$(UNODLLPOST) >> $@ + @-echo gconfbe1$(UNODLLPOST) >> $@ + @-echo fsstorage$(UNODLLPOST) >> $@ + @-echo desktopbe1$(UNODLLPOST) >> $@ + @-echo localebe1$(UNODLLPOST) >> $@ + @-echo ucpexpand1$(UNODLLPOST) >> $@ +# stoc bits + @-echo $(DLLPRE)sfx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)sofficeapp$(DLLPOST) >> $@ + diff --git a/desktop/source/pkgchk/unopkg/makefile.mk b/desktop/source/pkgchk/unopkg/makefile.mk new file mode 100755 index 000000000000..e96cf60f0f42 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/makefile.mk @@ -0,0 +1,98 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 +TARGETTYPE = GUI +ENABLE_EXCEPTIONS = TRUE +LIBTARGET=NO + +PRJINC += ..$/..$/deployment ..$/.. +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/source$/deployment$/inc$/dp_misc.mk + +CFLAGS+= $(SYSTEM_DB_CFLAGS) + +.IF "$(LINK_SO)"!="" +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 +.ENDIF # "$(LINK_SO)"!="" + +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..5411e40a91ca --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_app.cxx @@ -0,0 +1,710 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "rtl/bootstrap.hxx" +#include "osl/thread.h" +#include "osl/process.h" +#include "osl/conditn.hxx" +#include "osl/file.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/sequence.hxx" +#include "com/sun/star/deployment/ExtensionManager.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 { + +struct ExtensionName +{ + OUString m_str; + ExtensionName( OUString const & str ) : m_str( str ) {} + bool operator () ( Reference<deployment::XPackage> const & e ) const + { + if (m_str.equals(dp_misc::getIdentifier(e)) + || m_str.equals(e->getName())) + return true; + return false; + } +}; + +//------------------------------------------------------------------------------ +const char s_usingText [] = +"\n" +"using: " APP_NAME " add <options> extension-path...\n" +" " APP_NAME " validate <options> extension-identifier...\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" +" validate checks the prerequisites of an installed extension and" +" registers it if possible\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" +" -s, --suppress-license prevents showing the license\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" +" --bundled expert feature: operate on bundled extensions. Only\n" +" works with list, validate, reinstall;\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}, + { RTL_CONSTASCII_STRINGPARAM("suppress-license"), 's', 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( + OUString const & repository, + Reference<deployment::XExtensionManager> const & manager, + Reference<ucb::XCommandEnvironment > const & environment, + OUString const & idOrFileName ) +{ + Sequence< Reference<deployment::XPackage> > ps( + manager->getDeployedExtensions(repository, + 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 option_suppressLicense = false; + bool subcmd_add = false; + bool subcmd_gui = false; + OUString logFile; + OUString repository; + 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") ); + OptionInfo const * info_suppressLicense = getOptionInfo( + s_option_infos, OUSTR("suppress-license") ); + + + 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.3\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 ) && + !readOption( &option_suppressLicense, info_suppressLicense, &nPos ) && + !readArgument( &repository, 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 ); + } + } + } + } + + if (repository.getLength() == 0) + { + if (option_shared) + repository = OUSTR("shared"); + else if (option_bundled) + repository = OUSTR("bundled"); + else + repository = OUSTR("user"); + } + else + { + if (repository.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") ); + } + } + + if (subCommand.equals(OUSTR("reinstall"))) + { + //We must prevent that services and types are loaded by UNO, + //otherwise we cannot delete the registry data folder. + OUString extensionUnorc; + if (repository.equals(OUSTR("user"))) + extensionUnorc = OUSTR("$UNO_USER_PACKAGES_CACHE/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc"); + else if (repository.equals(OUSTR("shared"))) + extensionUnorc = OUSTR("$SHARED_EXTENSIONS_USER/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc"); + else if (repository.equals(OUSTR("bundled"))) + extensionUnorc = OUSTR("$BUNDLED_EXTENSIONS_USER/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc"); + else + OSL_ASSERT(0); + + ::rtl::Bootstrap::expandMacros(extensionUnorc); + oslFileError e = osl_removeFile(extensionUnorc.pData); + if (e != osl_File_E_None && e != osl_File_E_NOENT) + throw Exception(OUSTR("Could not delete ") + extensionUnorc, 0); + } + else if (subCommand.equals(OUSTR("sync"))) + { + //sync is private!!!! Only to be called from setup!!! + //The UserInstallation is diverted to the prereg folder. But only + //the lock file is written! This requires that + //-env:UNO_JAVA_JFW_INSTALL_DATA is passed to javaldx and unopkg otherwise the + //javasettings file is written to the prereg folder. + // + //For performance reasons unopkg sync is called during the setup and + //creates the registration data for the repository of the bundled + //extensions. It is then copied to the user installation during + //startup of OOo (userdata/extensions/bundled). The registration + //data is in the brand installation and must be removed when + //uninstalling OOo. We do this here, before UNO is + //bootstrapped. Otherwies files could be locked by this process. + + //If there is no folder left in + //$BRAND_BASE_DIR/share/extensions + //then we can delete the registration data at + //$BUNDLED_EXTENSIONS_USER + if (hasNoFolder(OUSTR("$BRAND_BASE_DIR/share/extensions"))) + { + removeFolder(OUSTR("$BUNDLED_EXTENSIONS_PREREG")); + //return otherwise we create the registration data again + return 0; + } + //redirect the UserInstallation, so we do not create a + //user installation for the admin and we also do not need + //to call unopkg with -env:UserInstallation + ::rtl::Bootstrap::set(OUSTR("UserInstallation"), + OUSTR("$BUNDLED_EXTENSIONS_PREREG/..")); + //Setting UNO_JAVA_JFW_INSTALL_DATA causes the javasettings to be written + //in the office installation. We do not want to create the user data folder + //for the admin. The value must also be set in the unopkg script (Linux, etc.) + //when calling javaldx + ::rtl::Bootstrap::set(OUSTR("UNO_JAVA_JFW_INSTALL_DATA"), + OUSTR("$OOO_BASE_DIR/share/config/javasettingsunopkginstall.xml")); + + } + + xComponentContext = getUNO( + disposeGuard, option_verbose, option_shared, subcmd_gui, + xLocalComponentContext ); + + Reference<deployment::XExtensionManager> xExtensionManager( + deployment::ExtensionManager::get( xComponentContext ) ); + + Reference< ::com::sun::star::ucb::XCommandEnvironment > xCmdEnv( + createCmdEnv( xComponentContext, logFile, + option_force, option_verbose, option_suppressLicense) ); + + //synchronize bundled/shared extensions + //Do not synchronize when command is "reinstall". This could add types and services to UNO and + //prevent the deletion of the registry data folder + //synching is done in XExtensionManager.reinstall + if (!subcmd_gui && ! subCommand.equals(OUSTR("reinstall")) + && ! subCommand.equals(OUSTR("sync")) + && ! dp_misc::office_is_running()) + dp_misc::syncRepositories(xCmdEnv); + + 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) + { + beans::NamedValue nvSuppress( + OUSTR("SUPPRESS_LICENSE"), option_suppressLicense ? + makeAny(OUSTR("1")):makeAny(OUSTR("0"))); + xExtensionManager->addExtension( + cmdPackage, Sequence<beans::NamedValue>(&nvSuppress, 1), + repository, Reference<task::XAbortChannel>(), xCmdEnv); + } + else + { + try + { + xExtensionManager->removeExtension( + cmdPackage, cmdPackage, repository, + Reference<task::XAbortChannel>(), xCmdEnv ); + } + catch (lang::IllegalArgumentException &) + { + Reference<deployment::XPackage> p( + findPackage(repository, + xExtensionManager, xCmdEnv, cmdPackage ) ); + if ( !p.is()) + throw; + else if (p.is()) + xExtensionManager->removeExtension( + ::dp_misc::getIdentifier(p), p->getName(), + repository, + Reference<task::XAbortChannel>(), xCmdEnv ); + } + } + } + } + else if (subCommand.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("reinstall") )) + { + xExtensionManager->reinstallDeployedExtensions( + repository, Reference<task::XAbortChannel>(), xCmdEnv); + } + else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("list") )) + { + ::std::vector<Reference<deployment::XPackage> > vecExtUnaccepted; + ::comphelper::sequenceToContainer(vecExtUnaccepted, + xExtensionManager->getExtensionsWithUnacceptedLicenses( + repository, xCmdEnv)); + + //This vector tells what XPackage in allExtensions has an + //unaccepted license. + std::vector<bool> vecUnaccepted; + std::vector<Reference<deployment::XPackage> > allExtensions; + if (cmdPackages.empty()) + { + Sequence< Reference<deployment::XPackage> > + packages = xExtensionManager->getDeployedExtensions( + repository, Reference<task::XAbortChannel>(), xCmdEnv ); + + ::std::vector<Reference<deployment::XPackage> > vec_packages; + ::comphelper::sequenceToContainer(vec_packages, packages); + + //First copy the extensions with the unaccepted license + //to vector allExtensions. + allExtensions.resize(vecExtUnaccepted.size() + vec_packages.size()); + + ::std::vector<Reference<deployment::XPackage> >::iterator i_all_ext = + ::std::copy(vecExtUnaccepted.begin(), vecExtUnaccepted.end(), + allExtensions.begin()); + //Now copy those we got from getDeployedExtensions + ::std::copy(vec_packages.begin(), vec_packages.end(), i_all_ext); + + //Now prepare the vector which tells what extension has an + //unaccepted license + vecUnaccepted.resize(vecExtUnaccepted.size() + vec_packages.size()); + ::std::fill_n(vecUnaccepted.begin(), vecExtUnaccepted.size(), true); + ::std::fill_n(vecUnaccepted.begin() + vecExtUnaccepted.size(), + vec_packages.size(), false); + + dp_misc::writeConsole( + OUSTR("All deployed ") + repository + OUSTR(" extensions:\n\n")); + } + else + { + //The user provided the names (ids or file names) of the extensions + //which shall be listed + for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) + { + Reference<deployment::XPackage> extension; + try + { + extension = xExtensionManager->getDeployedExtension( + repository, cmdPackages[ pos ], cmdPackages[ pos ], xCmdEnv ); + } + catch (lang::IllegalArgumentException &) + { + extension = findPackage(repository, + xExtensionManager, xCmdEnv, cmdPackages[ pos ] ); + } + + //Now look if the requested extension has an unaccepted license + bool bUnacceptedLic = false; + if (!extension.is()) + { + ::std::vector<Reference<deployment::XPackage> >::const_iterator + i = ::std::find_if( + vecExtUnaccepted.begin(), + vecExtUnaccepted.end(), ExtensionName(cmdPackages[pos])); + if (i != vecExtUnaccepted.end()) + { + extension = *i; + bUnacceptedLic = true; + } + } + + if (extension.is()) + { + allExtensions.push_back(extension); + vecUnaccepted.push_back(bUnacceptedLic); + } + + else + throw lang::IllegalArgumentException( + OUSTR("There is no such extension deployed: ") + + cmdPackages[pos],0,-1); + } + + } + + printf_packages(allExtensions, vecUnaccepted, xCmdEnv ); + } + else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("validate") )) + { + ::std::vector<Reference<deployment::XPackage> > vecExtUnaccepted; + ::comphelper::sequenceToContainer( + vecExtUnaccepted, xExtensionManager->getExtensionsWithUnacceptedLicenses( + repository, xCmdEnv)); + + for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) + { + Reference<deployment::XPackage> extension; + try + { + extension = xExtensionManager->getDeployedExtension( + repository, cmdPackages[ pos ], cmdPackages[ pos ], xCmdEnv ); + } + catch (lang::IllegalArgumentException &) + { + extension = findPackage( + repository, xExtensionManager, xCmdEnv, cmdPackages[ pos ] ); + } + + if (!extension.is()) + { + ::std::vector<Reference<deployment::XPackage> >::const_iterator + i = ::std::find_if( + vecExtUnaccepted.begin(), + vecExtUnaccepted.end(), ExtensionName(cmdPackages[pos])); + if (i != vecExtUnaccepted.end()) + { + extension = *i; + } + } + + if (extension.is()) + xExtensionManager->checkPrerequisitesAndEnable( + extension, Reference<task::XAbortChannel>(), 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 if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("sync"))) + { + if (! dp_misc::office_is_running()) + { + xExtensionManager->synchronizeBundledPrereg( + Reference<task::XAbortChannel>(), xCmdEnv); + } + else + { + dp_misc::writeConsoleError(OUSTR("\nError: office is running")); + } + } + 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; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx b/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx new file mode 100644 index 000000000000..1732b3fb5f88 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx @@ -0,0 +1,446 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <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<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_suppress_license; + 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, + bool option_suppress_license); + + // 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_suppressLicense) + : m_logLevel(0), + m_option_force_overwrite( option_force_overwrite ), + m_option_verbose( option_verbose ), + m_option_suppress_license( option_suppressLicense ), + 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_FAIL( ::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) + { + if ( !m_option_suppress_license ) + printLicense(licExc.ExtensionName, licExc.Text, approve, abort); + else + { + approve = true; + abort = false; + } + } + 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, + bool option_suppress_license) +{ + return new CommandEnvironmentImpl( + xContext, logFile, option_force_overwrite, option_verbose, option_suppress_license); +} +} // unopkg + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/unopkg_main.c b/desktop/source/pkgchk/unopkg/unopkg_main.c new file mode 100755 index 000000000000..07e310c3b402 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_main.c @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/unopkg_main.h b/desktop/source/pkgchk/unopkg/unopkg_main.h new file mode 100755 index 000000000000..a4d66cf17c05 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_main.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/unopkg_misc.cxx b/desktop/source/pkgchk/unopkg/unopkg_misc.cxx new file mode 100644 index 000000000000..a2c9baf4986e --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_misc.cxx @@ -0,0 +1,638 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "comphelper/sequence.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_FAIL( ::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< + 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< + 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"); + ::std::vector<Reference<deployment::XPackage> >vec_bundle; + ::comphelper::sequenceToContainer(vec_bundle, seq); + printf_packages( vec_bundle, ::std::vector<bool>(vec_bundle.size()), + xCmdEnv, level + 2 ); + printf_space( level + 1 ); + dp_misc::writeConsole("}\n"); + } +} + +} // anon namespace + +void printf_unaccepted_licenses( + Reference<deployment::XPackage> const & ext) +{ + OUString id( + dp_misc::getIdentifier(ext) ); + printf_line( OUSTR("Identifier"), id, 0 ); + printf_space(1); + dp_misc::writeConsole(OUSTR("License not accepted\n\n")); +} + +//============================================================================== +void printf_packages( + ::std::vector< Reference<deployment::XPackage> > const & allExtensions, + ::std::vector<bool> const & vecUnaccepted, + Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level ) +{ + OSL_ASSERT(allExtensions.size() == vecUnaccepted.size()); + + if (allExtensions.size() == 0) + { + printf_space( level ); + dp_misc::writeConsole("<none>\n"); + } + else + { + typedef ::std::vector< Reference<deployment::XPackage> >::const_iterator I_EXT; + int index = 0; + for (I_EXT i = allExtensions.begin(); i != allExtensions.end(); ++i, ++index) + { + if (vecUnaccepted[index]) + printf_unaccepted_licenses(*i); + else + printf_package( *i, xCmdEnv, level ); + dp_misc::writeConsole(OUSTR("\n")); + } + } +} + + + +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 ); + + disposeGuard.setDeinitUCB(); + 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; +} + +//Determines if a folder does not contains a folder. +//Return false may also mean that the status could not be determined +//because some error occurred. +bool hasNoFolder(OUString const & folderUrl) +{ + bool ret = false; + OUString url = folderUrl; + ::rtl::Bootstrap::expandMacros(url); + ::osl::Directory dir(url); + osl::File::RC rc = dir.open(); + if (rc == osl::File::E_None) + { + bool bFolderExist = false; + osl::DirectoryItem i; + osl::File::RC rcNext = osl::File::E_None; + while ( (rcNext = dir.getNextItem(i)) == osl::File::E_None) + { + osl::FileStatus stat(osl_FileStatus_Mask_Type); + if (i.getFileStatus(stat) == osl::File::E_None) + { + if (stat.getFileType() == osl::FileStatus::Directory) + { + bFolderExist = true; + break; + } + } + else + { + dp_misc::writeConsole( + OUSTR("unopkg: Error while investigating ") + url + OUSTR("\n")); + break; + } + i = osl::DirectoryItem(); + } + + if (rcNext == osl::File::E_NOENT || + rcNext == osl::File::E_None) + { + if (!bFolderExist) + ret = true; + } + else + { + dp_misc::writeConsole( + OUSTR("unopkg: Error while investigating ") + url + OUSTR("\n")); + } + + dir.close(); + } + else + { + dp_misc::writeConsole( + OUSTR("unopkg: Error while investigating ") + url + OUSTR("\n")); + } + return ret; +} + +void removeFolder(OUString const & folderUrl) +{ + OUString url = folderUrl; + ::rtl::Bootstrap::expandMacros(url); + ::osl::Directory dir(url); + ::osl::File::RC rc = dir.open(); + if (rc == osl::File::E_None) + { + ::osl::DirectoryItem i; + ::osl::File::RC rcNext = ::osl::File::E_None; + while ( (rcNext = dir.getNextItem(i)) == ::osl::File::E_None) + { + ::osl::FileStatus stat(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL); + if (i.getFileStatus(stat) == ::osl::File::E_None) + { + ::osl::FileStatus::Type t = stat.getFileType(); + if (t == ::osl::FileStatus::Directory) + { + //remove folder + removeFolder(stat.getFileURL()); + } + else if (t == ::osl::FileStatus::Regular) + { + //remove file + ::osl::File::remove(stat.getFileURL()); + } + else + { + OSL_ASSERT(0); + } + } + else + { + dp_misc::writeConsole( + OUSTR("unopkg: Error while investigating ") + url + OUSTR("\n")); + break; + } + i = ::osl::DirectoryItem(); + } + dir.close(); + ::osl::Directory::remove(url); + } + else if (rc != osl::File::E_NOENT) + { + dp_misc::writeConsole( + OUSTR("unopkg: Error while removing ") + url + OUSTR("\n")); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/unopkg_shared.h b/desktop/source/pkgchk/unopkg/unopkg_shared.h new file mode 100755 index 000000000000..feffd892a27e --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_shared.h @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" +#include "ucbhelper/contentbroker.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<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; + bool m_bDeinitUCB; +public: + DisposeGuard(): m_bDeinitUCB(false) {} + inline ~DisposeGuard() + { + if (m_bDeinitUCB) + ::ucbhelper::ContentBroker::deinitialize(); + + if (m_xComp.is()) + m_xComp->dispose(); + } + + inline void reset( + css::uno::Reference<css::lang::XComponent> const & xComp ) + { + m_xComp = xComp; + } + + inline void setDeinitUCB() + { + m_bDeinitUCB = true; + } + +}; + +//============================================================================== +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_suppressLicense); +//============================================================================== +void printf_packages( + ::std::vector< + css::uno::Reference<css::deployment::XPackage> > const & allExtensions, + ::std::vector<bool> const & vecUnaccepted, + 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); + +bool hasNoFolder(::rtl::OUString const & folderUrl); + +void removeFolder(::rtl::OUString const & folderUrl); + +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/version.map b/desktop/source/pkgchk/unopkg/version.map new file mode 100755 index 000000000000..6d34cb662d2c --- /dev/null +++ b/desktop/source/pkgchk/unopkg/version.map @@ -0,0 +1,34 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +UDK_3_0_0 { + global: + unopkg_main; + + local: + *; +}; diff --git a/desktop/source/splash/makefile.mk b/desktop/source/splash/makefile.mk new file mode 100755 index 000000000000..8db499d7c913 --- /dev/null +++ b/desktop/source/splash/makefile.mk @@ -0,0 +1,80 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=spl +LIBTARGET=NO + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +SLOFILES = $(SLO)$/splash.obj \ + $(SLO)$/services_spl.obj + +SHL1DEPN= makefile.mk +SHL1OBJS= $(SLOFILES) \ + $(SLO)$/migration.obj + + +SHL1TARGET=$(TARGET)$(DLLPOSTFIX) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +SHL1STDLIBS= \ + $(VCLLIB) \ + $(SVLLIB) \ + $(SVTOOLLIB) \ + $(COMPHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(UCBHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SFXLIB) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/spl.component + +$(MISC)/spl.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + spl.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt spl.component diff --git a/desktop/source/splash/services_spl.cxx b/desktop/source/splash/services_spl.cxx new file mode 100644 index 000000000000..a2f9bd232123 --- /dev/null +++ b/desktop/source/splash/services_spl.cxx @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/util/Date.hpp> +#include <uno/environment.h> +#include <cppuhelper/factory.hxx> +#include <unotools/configmgr.hxx> + +#include "splash.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::registry; +using namespace ::desktop; + +using ::rtl::OUString; + +static const char* pServices[] = +{ + SplashScreen::serviceName, + NULL +}; + +static const char* pImplementations[] = +{ + SplashScreen::implementationName, + NULL +}; + +typedef Reference<XInterface>(* fProvider)(const Reference<XMultiServiceFactory>&); + +static const fProvider pInstanceProviders[] = +{ + SplashScreen::getInstance, + NULL +}; + +static const char** pSupportedServices[] = +{ + SplashScreen::interfaces, + NULL +}; + +static Sequence<OUString> +getSupportedServiceNames(int p) { + const char **names = pSupportedServices[p]; + Sequence<OUString> aSeq; + for(int i = 0; names[i] != NULL; i++) { + aSeq.realloc(i+1); + aSeq[i] = OUString::createFromAscii(names[i]); + } + return aSeq; +} + +extern "C" +{ +SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( + const sal_Char* pImplementationName, + void* pServiceManager, + void*) +{ + // Set default return value for this operation - if it failed. + if ( pImplementationName && pServiceManager ) + { + Reference< XSingleServiceFactory > xFactory; + Reference< XMultiServiceFactory > xServiceManager( + reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; + + // search implementation + for (int i = 0; (pImplementations[i]!=NULL); i++) { + if ( strcmp(pImplementations[i], pImplementationName ) == 0 ) { + // found implementation + xFactory = Reference<XSingleServiceFactory>(cppu::createSingleFactory( + xServiceManager, OUString::createFromAscii(pImplementationName), + pInstanceProviders[i], getSupportedServiceNames(i))); + if ( xFactory.is() ) { + // Factory is valid - service was found. + xFactory->acquire(); + return xFactory.get(); + } + } + } // for() + } + // Return with result of this operation. + return NULL; +} +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/splash/spl.component b/desktop/source/splash/spl.component new file mode 100755 index 000000000000..2caecf5c0e4b --- /dev/null +++ b/desktop/source/splash/spl.component @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.desktop.FirstStart"> + <service name="com.sun.star.task.Job"/> + </implementation> + <implementation name="com.sun.star.office.comp.SplashScreen"> + <service name="com.sun.star.office.SplashScreen"/> + </implementation> +</component> diff --git a/desktop/source/splash/splash.cxx b/desktop/source/splash/splash.cxx new file mode 100644 index 000000000000..42e1dfd51c0d --- /dev/null +++ b/desktop/source/splash/splash.cxx @@ -0,0 +1,580 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "splash.hxx" +#include <stdio.h> +#include <unotools/bootstrap.hxx> +#include <tools/urlobj.hxx> +#include <tools/stream.hxx> +#include <sfx2/sfx.hrc> +#include <vcl/svapp.hxx> +#include <vcl/salnativewidgets.hxx> + +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <rtl/bootstrap.hxx> +#include <rtl/logfile.hxx> +#include <rtl/locale.hxx> +#include <rtl/strbuf.hxx> +#include <rtl/math.hxx> +#include <vcl/graph.hxx> +#include <svtools/filter.hxx> + +#define NOT_LOADED ((long)-1) + +using namespace ::rtl; +using namespace ::com::sun::star::registry; + +namespace desktop +{ + +SplashScreen::SplashScreen(const Reference< XMultiServiceFactory >& rSMgr) + : IntroWindow() + , _vdev(*((IntroWindow*)this)) + , _cProgressFrameColor(sal::static_int_cast< ColorData >(NOT_LOADED)) + , _cProgressBarColor(sal::static_int_cast< ColorData >(NOT_LOADED)) + , _bNativeProgress(true) + , _iMax(100) + , _iProgress(0) + , _eBitmapMode(BM_DEFAULTMODE) + , _bPaintBitmap(sal_True) + , _bPaintProgress(sal_False) + , _bShowLogo(sal_True) + , _bFullScreenSplash(sal_False) + , _bProgressEnd(sal_False) + , _tlx(NOT_LOADED) + , _tly(NOT_LOADED) + , _barwidth(NOT_LOADED) + , _barheight(NOT_LOADED) + , _barspace(2) + , _fXPos(-1.0) + , _fYPos(-1.0) + , _fWidth(-1.0) + , _fHeight(-1.0) + , _xoffset(12) + , _yoffset(18) +{ + _rFactory = rSMgr; + + loadConfig(); +} + +SplashScreen::~SplashScreen() +{ + Application::RemoveEventListener( + LINK( this, SplashScreen, AppEventListenerHdl ) ); + Hide(); + +} + +void SAL_CALL SplashScreen::start(const OUString&, sal_Int32 nRange) + throw (RuntimeException) +{ + _iMax = nRange; + if (_bVisible) { + _bProgressEnd = sal_False; + SolarMutexGuard aSolarGuard; + if ( _eBitmapMode == BM_FULLSCREEN ) + ShowFullScreenMode( sal_True ); + Show(); + Paint(Rectangle()); + Flush(); + } +} + +void SAL_CALL SplashScreen::end() + throw (RuntimeException) +{ + _iProgress = _iMax; + if (_bVisible ) + { + if ( _eBitmapMode == BM_FULLSCREEN ) + EndFullScreenMode(); + Hide(); + } + _bProgressEnd = sal_True; +} + +void SAL_CALL SplashScreen::reset() + throw (RuntimeException) +{ + _iProgress = 0; + if (_bVisible && !_bProgressEnd ) + { + if ( _eBitmapMode == BM_FULLSCREEN ) + ShowFullScreenMode( sal_True ); + Show(); + updateStatus(); + } +} + +void SAL_CALL SplashScreen::setText(const OUString& rText) + throw (RuntimeException) +{ + SolarMutexGuard aSolarGuard; + if ( _sProgressText != rText ) + { + _sProgressText = rText; + + if (_bVisible && !_bProgressEnd) + { + if ( _eBitmapMode == BM_FULLSCREEN ) + ShowFullScreenMode( sal_True ); + Show(); + updateStatus(); + } + } +} + +void SAL_CALL SplashScreen::setValue(sal_Int32 nValue) + throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT( aLog, "::SplashScreen::setValue (lo119109)" ); + RTL_LOGFILE_CONTEXT_TRACE1( aLog, "value=%d", nValue ); + + SolarMutexGuard aSolarGuard; + if (_bVisible && !_bProgressEnd) { + if ( _eBitmapMode == BM_FULLSCREEN ) + ShowFullScreenMode( sal_True ); + Show(); + if (nValue >= _iMax) _iProgress = _iMax; + else _iProgress = nValue; + updateStatus(); + } +} + +// XInitialize +void SAL_CALL +SplashScreen::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments ) + throw (RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard( _aMutex ); + if (aArguments.getLength() > 0) + { + aArguments[0] >>= _bVisible; + if (aArguments.getLength() > 1 ) + aArguments[1] >>= _sAppName; + + // start to determine bitmap and all other required value + if ( _bShowLogo ) + SetScreenBitmap (_aIntroBmp); + Size aSize = _aIntroBmp.GetSizePixel(); + SetOutputSizePixel( aSize ); + _vdev.SetOutputSizePixel( aSize ); + _height = aSize.Height(); + _width = aSize.Width(); + if (_width > 500) + { + Point xtopleft(212,216); + if ( NOT_LOADED == _tlx || NOT_LOADED == _tly ) + { + _tlx = xtopleft.X(); // top-left x + _tly = xtopleft.Y(); // top-left y + } + if ( NOT_LOADED == _barwidth ) + _barwidth = 263; + if ( NOT_LOADED == _barheight ) + _barheight = 8; + if (( _eBitmapMode == BM_FULLSCREEN ) && + _bFullScreenSplash ) + { + if( ( _fXPos >= 0.0 ) && ( _fYPos >= 0.0 )) + { + _tlx = sal_Int32( double( aSize.Width() ) * _fXPos ); + _tly = sal_Int32( double( aSize.Height() ) * _fYPos ); + } + if ( _fWidth >= 0.0 ) + _barwidth = sal_Int32( double( aSize.Width() ) * _fWidth ); + if ( _fHeight >= 0.0 ) + _barheight = sal_Int32( double( aSize.Width() ) * _fHeight ); + } + } + else + { + if ( NOT_LOADED == _barwidth ) + _barwidth = _width - (2 * _xoffset); + if ( NOT_LOADED == _barheight ) + _barheight = 6; + if ( NOT_LOADED == _tlx || NOT_LOADED == _tly ) + { + _tlx = _xoffset; // top-left x + _tly = _height - _yoffset; // top-left y + } + } + + if ( sal::static_int_cast< ColorData >(NOT_LOADED) == + _cProgressFrameColor.GetColor() ) + _cProgressFrameColor = Color( COL_LIGHTGRAY ); + + if ( sal::static_int_cast< ColorData >(NOT_LOADED) == + _cProgressBarColor.GetColor() ) + { + // progress bar: new color only for big bitmap format + if ( _width > 500 ) + _cProgressBarColor = Color( 157, 202, 18 ); + else + _cProgressBarColor = Color( COL_BLUE ); + } + + Application::AddEventListener( + LINK( this, SplashScreen, AppEventListenerHdl ) ); + + SetBackgroundBitmap( _aIntroBmp ); + } +} + +void SplashScreen::updateStatus() +{ + if (!_bVisible || _bProgressEnd) return; + if (!_bPaintProgress) _bPaintProgress = sal_True; + Paint(Rectangle()); + Flush(); +} + +// internal private methods +IMPL_LINK( SplashScreen, AppEventListenerHdl, VclWindowEvent *, inEvent ) +{ + if ( inEvent != 0 ) + { + switch ( inEvent->GetId() ) + { + case VCLEVENT_WINDOW_SHOW: + Paint( Rectangle() ); + break; + default: + break; + } + } + return 0; +} + +// Read keys from edition/edition.ini or soffice{.ini|rc}: +OUString implReadBootstrapKey( const OUString& _rKey ) +{ + OUString sValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "${.override:${BRAND_BASE_DIR}/program/edition/edition.ini:")) + + _rKey + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("}"))); + rtl::Bootstrap::expandMacros(sValue); + return sValue; +} + +void SplashScreen::loadConfig() +{ + _bShowLogo = !implReadBootstrapKey( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Logo"))). + equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("0")); + + OUString sProgressFrameColor = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressFrameColor" ) ) ); + OUString sProgressBarColor = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressBarColor" ) ) ); + OUString sSize = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressSize" ) ) ); + OUString sPosition = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressPosition" ) ) ); + OUString sFullScreenSplash = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "FullScreenSplash" ) ) ); + OUString sNativeProgress = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "NativeProgress" ) ) ); + + + // Determine full screen splash mode + _bFullScreenSplash = (( sFullScreenSplash.getLength() > 0 ) && + ( !sFullScreenSplash.equalsAsciiL( "0", 1 ))); + + // Try to retrieve the relative values for the progress bar. The current + // schema uses the screen ratio to retrieve the associated values. + if ( _bFullScreenSplash ) + determineProgressRatioValues( _fXPos, _fYPos, _fWidth, _fHeight ); + + if ( sProgressFrameColor.getLength() ) + { + sal_uInt8 nRed = 0; + sal_Int32 idx = 0; + sal_Int32 temp = sProgressFrameColor.getToken( 0, ',', idx ).toInt32(); + if ( idx != -1 ) + { + nRed = static_cast< sal_uInt8 >( temp ); + temp = sProgressFrameColor.getToken( 0, ',', idx ).toInt32(); + } + if ( idx != -1 ) + { + sal_uInt8 nGreen = static_cast< sal_uInt8 >( temp ); + sal_uInt8 nBlue = static_cast< sal_uInt8 >( sProgressFrameColor.getToken( 0, ',', idx ).toInt32() ); + _cProgressFrameColor = Color( nRed, nGreen, nBlue ); + } + } + + if ( sProgressBarColor.getLength() ) + { + sal_uInt8 nRed = 0; + sal_Int32 idx = 0; + sal_Int32 temp = sProgressBarColor.getToken( 0, ',', idx ).toInt32(); + if ( idx != -1 ) + { + nRed = static_cast< sal_uInt8 >( temp ); + temp = sProgressBarColor.getToken( 0, ',', idx ).toInt32(); + } + if ( idx != -1 ) + { + sal_uInt8 nGreen = static_cast< sal_uInt8 >( temp ); + sal_uInt8 nBlue = static_cast< sal_uInt8 >( sProgressBarColor.getToken( 0, ',', idx ).toInt32() ); + _cProgressBarColor = Color( nRed, nGreen, nBlue ); + } + } + + if( sNativeProgress.getLength() ) + { + _bNativeProgress = sNativeProgress.toBoolean(); + } + + if ( sSize.getLength() ) + { + sal_Int32 idx = 0; + sal_Int32 temp = sSize.getToken( 0, ',', idx ).toInt32(); + if ( idx != -1 ) + { + _barwidth = temp; + _barheight = sSize.getToken( 0, ',', idx ).toInt32(); + } + } + + if ( _barheight >= 10 ) + _barspace = 3; // more space between frame and bar + + if ( sPosition.getLength() ) + { + sal_Int32 idx = 0; + sal_Int32 temp = sPosition.getToken( 0, ',', idx ).toInt32(); + if ( idx != -1 ) + { + _tlx = temp; + _tly = sPosition.getToken( 0, ',', idx ).toInt32(); + } + } +} + +void SplashScreen::SetScreenBitmap(BitmapEx &rBitmap) +{ + sal_Int32 nWidth( 0 ); + sal_Int32 nHeight( 0 ); + + // determine desktop resolution + sal_uInt32 nCount = Application::GetScreenCount(); + if ( nCount > 0 ) + { + // retrieve size from first screen + Rectangle aScreenArea = Application::GetScreenPosSizePixel((unsigned int)0); + nWidth = aScreenArea.GetWidth(); + nHeight = aScreenArea.GetHeight(); + } + + // create file name from screen resolution information + OStringBuffer aStrBuf( 128 ); + OStringBuffer aResBuf( 32 ); + aStrBuf.append( "intro_" ); + if ( _sAppName.getLength() > 0 ) + { + aStrBuf.append( OUStringToOString(_sAppName, RTL_TEXTENCODING_UTF8) ); + aStrBuf.append( "_" ); + } + aResBuf.append( OString::valueOf( nWidth )); + aResBuf.append( "x" ); + aResBuf.append( OString::valueOf( nHeight )); + + aStrBuf.append( aResBuf.getStr() ); + if (Application::LoadBrandBitmap (aStrBuf.makeStringAndClear().getStr(), rBitmap)) + return; + + aStrBuf.append( "intro_" ); + aStrBuf.append( aResBuf.getStr() ); + if (Application::LoadBrandBitmap (aResBuf.makeStringAndClear().getStr(), rBitmap)) + return; + + Application::LoadBrandBitmap ("intro", rBitmap); +} + +void SplashScreen::determineProgressRatioValues( + double& rXRelPos, double& rYRelPos, + double& rRelWidth, double& rRelHeight ) +{ + sal_Int32 nWidth( 0 ); + sal_Int32 nHeight( 0 ); + sal_Int32 nScreenRatio( 0 ); + + // determine desktop resolution + sal_uInt32 nCount = Application::GetScreenCount(); + if ( nCount > 0 ) + { + // retrieve size from first screen + Rectangle aScreenArea = Application::GetScreenPosSizePixel((unsigned int)0); + nWidth = aScreenArea.GetWidth(); + nHeight = aScreenArea.GetHeight(); + nScreenRatio = sal_Int32( math::round( double( nWidth ) / double( nHeight ), 2 ) * 100 ); + } + + char szFullScreenProgressRatio[] = "FullScreenProgressRatio0"; + char szFullScreenProgressPos[] = "FullScreenProgressPos0"; + char szFullScreenProgressSize[] = "FullScreenProgressSize0"; + for ( sal_Int32 i = 0; i <= 9; i++ ) + { + char cNum = '0' + char( i ); + szFullScreenProgressRatio[23] = cNum; + szFullScreenProgressPos[21] = cNum; + szFullScreenProgressSize[22] = cNum; + + OUString sFullScreenProgressRatio = implReadBootstrapKey( + OUString::createFromAscii( szFullScreenProgressRatio ) ); + + if ( sFullScreenProgressRatio.getLength() > 0 ) + { + double fRatio = sFullScreenProgressRatio.toDouble(); + sal_Int32 nRatio = sal_Int32( math::round( fRatio, 2 ) * 100 ); + if ( nRatio == nScreenRatio ) + { + OUString sFullScreenProgressPos = implReadBootstrapKey( + OUString::createFromAscii( szFullScreenProgressPos ) ); + OUString sFullScreenProgressSize = implReadBootstrapKey( + OUString::createFromAscii( szFullScreenProgressSize ) ); + + if ( sFullScreenProgressPos.getLength() ) + { + sal_Int32 idx = 0; + double temp = sFullScreenProgressPos.getToken( 0, ',', idx ).toDouble(); + if ( idx != -1 ) + { + rXRelPos = temp; + rYRelPos = sFullScreenProgressPos.getToken( 0, ',', idx ).toDouble(); + } + } + + if ( sFullScreenProgressSize.getLength() ) + { + sal_Int32 idx = 0; + double temp = sFullScreenProgressSize.getToken( 0, ',', idx ).toDouble(); + if ( idx != -1 ) + { + rRelWidth = temp; + rRelHeight = sFullScreenProgressSize.getToken( 0, ',', idx ).toDouble(); + } + } + } + } + else + break; + } +} + +void SplashScreen::Paint( const Rectangle&) +{ + if(!_bVisible) return; + + //native drawing + sal_Bool bNativeOK = sal_False; + + // in case of native controls we need to draw directly to the window + if( _bNativeProgress && IsNativeControlSupported( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL ) ) + { + DrawBitmapEx( Point(), _aIntroBmp ); + + ImplControlValue aValue( _iProgress * _barwidth / _iMax); + Rectangle aDrawRect( Point(_tlx, _tly), Size( _barwidth, _barheight ) ); + Rectangle aNativeControlRegion, aNativeContentRegion; + + if( GetNativeControlRegion( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL, aDrawRect, + CTRL_STATE_ENABLED, aValue, rtl::OUString(), + aNativeControlRegion, aNativeContentRegion ) ) + { + long nProgressHeight = aNativeControlRegion.GetHeight(); + aDrawRect.Top() -= (nProgressHeight - _barheight)/2; + aDrawRect.Bottom() += (nProgressHeight - _barheight)/2; + } + + if( (bNativeOK = DrawNativeControl( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL, aDrawRect, + CTRL_STATE_ENABLED, aValue, _sProgressText )) != sal_False ) + { + return; + } + } + //non native drawing + // draw bitmap + if (_bPaintBitmap) + _vdev.DrawBitmapEx( Point(), _aIntroBmp ); + + if (_bPaintProgress) { + // draw progress... + long length = (_iProgress * _barwidth / _iMax) - (2 * _barspace); + if (length < 0) length = 0; + + // border + _vdev.SetFillColor(); + _vdev.SetLineColor( _cProgressFrameColor ); + _vdev.DrawRect(Rectangle(_tlx, _tly, _tlx+_barwidth, _tly+_barheight)); + _vdev.SetFillColor( _cProgressBarColor ); + _vdev.SetLineColor(); + _vdev.DrawRect(Rectangle(_tlx+_barspace, _tly+_barspace, _tlx+_barspace+length, _tly+_barheight-_barspace)); + _vdev.DrawText( Rectangle(_tlx, _tly+_barheight+5, _tlx+_barwidth, _tly+_barheight+5+20), _sProgressText, TEXT_DRAW_CENTER ); + } + DrawOutDev(Point(), GetOutputSizePixel(), Point(), _vdev.GetOutputSizePixel(), _vdev ); +} + + +// get service instance... +SplashScreen *SplashScreen::_pINSTANCE = NULL; +osl::Mutex SplashScreen::_aMutex; + +Reference< XInterface > SplashScreen::getInstance(const Reference< XMultiServiceFactory >& rSMgr) +{ + if ( _pINSTANCE == 0 ) + { + osl::MutexGuard guard(_aMutex); + if (_pINSTANCE == 0) + return (XComponent*)new SplashScreen(rSMgr); + } + + return (XComponent*)0; +} + +// static service info... +const char* SplashScreen::interfaces[] = +{ + "com.sun.star.task.XStartusIndicator", + "com.sun.star.lang.XInitialization", + NULL, +}; +const sal_Char *SplashScreen::serviceName = "com.sun.star.office.SplashScreen"; +const sal_Char *SplashScreen::implementationName = "com.sun.star.office.comp.SplashScreen"; +const sal_Char *SplashScreen::supportedServiceNames[] = {"com.sun.star.office.SplashScreen", NULL}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/splash/splash.hxx b/desktop/source/splash/splash.hxx new file mode 100644 index 000000000000..0d4858402b83 --- /dev/null +++ b/desktop/source/splash/splash.hxx @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <vcl/introwin.hxx> +#include <vcl/bitmapex.hxx> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <osl/mutex.hxx> +#include <vcl/virdev.hxx> + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::task; + +namespace desktop { + +class SplashScreen + : public ::cppu::WeakImplHelper2< XStatusIndicator, XInitialization > + , public IntroWindow +{ +private: + struct FullScreenProgressRatioValue + { + double _fXRelPos; + double _fYRelPos; + double _fRelWidth; + double _fRelHeight; + }; + enum BitmapMode { BM_FULLSCREEN, BM_DEFAULTMODE }; + + // don't allow anybody but ourselves to create instances of this class + SplashScreen(const SplashScreen&); + SplashScreen(void); + SplashScreen operator =(const SplashScreen&); + + SplashScreen(const Reference< XMultiServiceFactory >& xFactory); + + DECL_LINK( AppEventListenerHdl, VclWindowEvent * ); + virtual ~SplashScreen(); + void loadConfig(); + void updateStatus(); + void SetScreenBitmap(BitmapEx &rBitmap); + void determineProgressRatioValues( double& rXRelPos, double& rYRelPos, double& rRelWidth, double& rRelHeight ); + + static SplashScreen *_pINSTANCE; + + static osl::Mutex _aMutex; + Reference< XMultiServiceFactory > _rFactory; + + VirtualDevice _vdev; + BitmapEx _aIntroBmp; + Color _cProgressFrameColor; + Color _cProgressBarColor; + bool _bNativeProgress; + OUString _sAppName; + OUString _sProgressText; + std::vector< FullScreenProgressRatioValue > _sFullScreenProgressRatioValues; + + sal_Int32 _iMax; + sal_Int32 _iProgress; + BitmapMode _eBitmapMode; + sal_Bool _bPaintBitmap; + sal_Bool _bPaintProgress; + sal_Bool _bVisible; + sal_Bool _bShowLogo; + sal_Bool _bFullScreenSplash; + sal_Bool _bProgressEnd; + long _height, _width, _tlx, _tly, _barwidth; + long _barheight, _barspace; + double _fXPos, _fYPos; + double _fWidth, _fHeight; + const long _xoffset, _yoffset; + +public: + static const char* interfaces[]; + static const sal_Char *serviceName; + static const sal_Char *implementationName; + static const sal_Char *supportedServiceNames[]; + + static Reference< XInterface > getInstance(const Reference < XMultiServiceFactory >& xFactory); + + // XStatusIndicator + virtual void SAL_CALL end() throw ( RuntimeException ); + virtual void SAL_CALL reset() throw ( RuntimeException ); + virtual void SAL_CALL setText(const OUString& aText) throw ( RuntimeException ); + virtual void SAL_CALL setValue(sal_Int32 nValue) throw ( RuntimeException ); + virtual void SAL_CALL start(const OUString& aText, sal_Int32 nRange) throw ( RuntimeException ); + + // XInitialize + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments ) + throw ( RuntimeException ); + + // workwindow + virtual void Paint( const Rectangle& ); + +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/test/deployment/active/Addons.xcu b/desktop/test/deployment/active/Addons.xcu new file mode 100644 index 000000000000..cc75f2ab8f64 --- /dev/null +++ b/desktop/test/deployment/active/Addons.xcu @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<o:component-data xmlns:o="http://openoffice.org/2001/registry" + o:package="org.openoffice.Office" o:name="Addons"> + <node o:name="AddonUI"> + <node o:name="OfficeMenuBar"> + <node o:name="org.openoffice.test.desktop.deployment.active" + o:op="replace"> + <prop o:name="Title" xml:lang="en-US"> + <value>active</value> + </prop> + <node o:name="Submenu"> + <node o:name="1" o:op="replace"> + <prop o:name="URL"> + <value>vnd.org.openoffice.test.desktop.deployment.active_native:</value> + </prop> + <prop o:name="Title" xml:lang="en-US"> + <value>native</value> + </prop> + </node> + <node o:name="2" o:op="replace"> + <prop o:name="URL"> + <value>vnd.org.openoffice.test.desktop.deployment.active_java:</value> + </prop> + <prop o:name="Title" xml:lang="en-US"> + <value>java</value> + </prop> + </node> + <node o:name="3" o:op="replace"> + <prop o:name="URL"> + <value>vnd.org.openoffice.test.desktop.deployment.active_python:</value> + </prop> + <prop o:name="Title" xml:lang="en-US"> + <value>python</value> + </prop> + </node> + </node> + </node> + </node> + </node> +</o:component-data> diff --git a/desktop/test/deployment/active/Dispatch.java b/desktop/test/deployment/active/Dispatch.java new file mode 100755 index 000000000000..25443f96e092 --- /dev/null +++ b/desktop/test/deployment/active/Dispatch.java @@ -0,0 +1,101 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +************************************************************************/ + +package com.sun.star.comp.test.deployment.active_java; + +import com.sun.star.awt.MessageBoxButtons; +import com.sun.star.awt.Rectangle; +import com.sun.star.awt.XMessageBox; +import com.sun.star.awt.XMessageBoxFactory; +import com.sun.star.awt.XWindowPeer; +import com.sun.star.beans.PropertyValue; +import com.sun.star.frame.DispatchDescriptor; +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XDispatch; +import com.sun.star.frame.XStatusListener; +import com.sun.star.lang.WrappedTargetRuntimeException; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.util.URL; + +public final class Dispatch extends WeakBase implements XServiceInfo, XDispatch +{ + public Dispatch(XComponentContext context) { + this.context = context; + } + + public String getImplementationName() { return implementationName; } + + public boolean supportsService(String ServiceName) { + return false; //TODO + } + + public String[] getSupportedServiceNames() { + return serviceNames; + } + + public void dispatch(URL URL, PropertyValue[] Arguments) { + try { + XMultiComponentFactory smgr = UnoRuntime.queryInterface( + XMultiComponentFactory.class, context.getServiceManager()); + XMessageBox box = UnoRuntime.queryInterface( + XMessageBoxFactory.class, + smgr.createInstanceWithContext( + "com.sun.star.awt.Toolkit", context)). + createMessageBox( + UnoRuntime.queryInterface( + XWindowPeer.class, + (UnoRuntime.queryInterface( + XDesktop.class, + smgr.createInstanceWithContext( + "com.sun.star.frame.Desktop", context)). + getCurrentFrame().getComponentWindow())), + new Rectangle(), "infobox", MessageBoxButtons.BUTTONS_OK, + "active", "java"); + box.execute(); + UnoRuntime.queryInterface(XComponent.class, box).dispose(); + } catch (com.sun.star.uno.RuntimeException e) { + throw e; + } catch (com.sun.star.uno.Exception e) { + throw new WrappedTargetRuntimeException( + "wrapped: " + e.getMessage(), this, e); + } + } + + public void addStatusListener(XStatusListener Control, URL URL) {} + + public void removeStatusListener(XStatusListener Control, URL URL) {} + + private final XComponentContext context; + + static final String implementationName = + "com.sun.star.comp.test.deployment.active_java_singleton"; + + static final String[] serviceNames = new String[0]; +} diff --git a/desktop/test/deployment/active/MANIFEST.MF b/desktop/test/deployment/active/MANIFEST.MF new file mode 100755 index 000000000000..63480874dd55 --- /dev/null +++ b/desktop/test/deployment/active/MANIFEST.MF @@ -0,0 +1,3 @@ +Sealed: true +RegistrationClassName: com.sun.star.comp.test.deployment.active_java.Services +UNO-Type-Path: diff --git a/desktop/test/deployment/active/ProtocolHandler.xcu b/desktop/test/deployment/active/ProtocolHandler.xcu new file mode 100644 index 000000000000..017bdea72bea --- /dev/null +++ b/desktop/test/deployment/active/ProtocolHandler.xcu @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<o:component-data xmlns:o="http://openoffice.org/2001/registry" + o:package="org.openoffice.Office" o:name="ProtocolHandler"> + <node o:name="HandlerSet"> + <node o:name="com.sun.star.test.deployment.active_native" o:op="replace"> + <prop o:name="Protocols"> + <value>vnd.org.openoffice.test.desktop.deployment.active_native:*</value> + </prop> + </node> + <node o:name="com.sun.star.test.deployment.active_java" o:op="replace"> + <prop o:name="Protocols"> + <value>vnd.org.openoffice.test.desktop.deployment.active_java:*</value> + </prop> + </node> + <node o:name="com.sun.star.test.deployment.active_python" o:op="replace"> + <prop o:name="Protocols"> + <value>vnd.org.openoffice.test.desktop.deployment.active_python:*</value> + </prop> + </node> + </node> +</o:component-data> diff --git a/desktop/test/deployment/active/Provider.java b/desktop/test/deployment/active/Provider.java new file mode 100755 index 000000000000..df31979f4b9d --- /dev/null +++ b/desktop/test/deployment/active/Provider.java @@ -0,0 +1,81 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +************************************************************************/ + +package com.sun.star.comp.test.deployment.active_java; + +import com.sun.star.frame.DispatchDescriptor; +import com.sun.star.frame.XDispatch; +import com.sun.star.frame.XDispatchProvider; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.util.URL; + +public final class Provider extends WeakBase + implements XServiceInfo, XDispatchProvider +{ + public Provider(XComponentContext context) { + this.context = context; + } + + public String getImplementationName() { return implementationName; } + + public boolean supportsService(String ServiceName) { + return ServiceName.equals(getSupportedServiceNames()[0]); //TODO + } + + public String[] getSupportedServiceNames() { + return serviceNames; + } + + public XDispatch queryDispatch( + URL URL, String TargetFrameName, int SearchFlags) + { + return UnoRuntime.queryInterface( + XDispatch.class, + context.getValueByName( + "/singletons/" + + "com.sun.star.test.deployment.active_java_singleton")); + } + + public XDispatch[] queryDispatches(DispatchDescriptor[] Requests) { + XDispatch[] s = new XDispatch[Requests.length]; + for (int i = 0; i < s.length; ++i) { + s[i] = queryDispatch( + Requests[i].FeatureURL, Requests[i].FrameName, + Requests[i].SearchFlags); + } + return s; + } + + private final XComponentContext context; + + static final String implementationName = + "com.sun.star.comp.test.deployment.active_java"; + + static final String[] serviceNames = new String[] { + "com.sun.star.test.deployment.active_java" }; +} diff --git a/desktop/test/deployment/active/Services.java b/desktop/test/deployment/active/Services.java new file mode 100755 index 000000000000..4ea19f4b7a71 --- /dev/null +++ b/desktop/test/deployment/active/Services.java @@ -0,0 +1,72 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +************************************************************************/ + +package com.sun.star.comp.test.deployment.active_java; + +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lib.uno.helper.Factory; +import com.sun.star.registry.InvalidRegistryException; +import com.sun.star.registry.XRegistryKey; + +public final class Services { + private Services() {} + + public static XSingleComponentFactory __getComponentFactory( + String implementation) + { + if (implementation.equals(Dispatch.implementationName)) { + return Factory.createComponentFactory( + Dispatch.class, Dispatch.implementationName, + Dispatch.serviceNames); + } else if (implementation.equals(Provider.implementationName)) { + return Factory.createComponentFactory( + Provider.class, Provider.implementationName, + Provider.serviceNames); + } else { + return null; + } + } + + public static boolean __writeRegistryServiceInfo(XRegistryKey key) { + if (!(Factory.writeRegistryServiceInfo( + Dispatch.implementationName, Dispatch.serviceNames, key) && + Factory.writeRegistryServiceInfo( + Provider.implementationName, Provider.serviceNames, key))) + { + return false; + } + try { + key. + createKey( + "/" + Dispatch.implementationName + + "/UNO/SINGLETONS/" + + "com.sun.star.test.deployment.active_java_singleton"). + setStringValue(Dispatch.implementationName); + } catch (InvalidRegistryException e) { + return false; + } + return true; + } +} diff --git a/desktop/test/deployment/active/active_native.cxx b/desktop/test/deployment/active/active_native.cxx new file mode 100644 index 000000000000..6507cdb0d7f7 --- /dev/null +++ b/desktop/test/deployment/active/active_native.cxx @@ -0,0 +1,314 @@ +/************************************************************************* +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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 "precompiled_desktop.hxx" +#include "sal/config.h" + +#include "boost/noncopyable.hpp" +#include "com/sun/star/awt/MessageBoxButtons.hpp" +#include "com/sun/star/awt/Rectangle.hpp" +#include "com/sun/star/awt/XMessageBox.hpp" +#include "com/sun/star/awt/XMessageBoxFactory.hpp" +#include "com/sun/star/awt/XWindowPeer.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/frame/DispatchDescriptor.hpp" +#include "com/sun/star/frame/XDesktop.hpp" +#include "com/sun/star/frame/XDispatch.hpp" +#include "com/sun/star/frame/XDispatchProvider.hpp" +#include "com/sun/star/frame/XFrame.hpp" +#include "com/sun/star/frame/XStatusListener.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/uno/DeploymentException.hpp" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/URL.hpp" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/diagnose.h" +#include "rtl/textenc.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "uno/lbnames.h" + +namespace { + +namespace css = com::sun::star; + +class Provider: + public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::frame::XDispatchProvider >, + private boost::noncopyable +{ +public: + static css::uno::Reference< css::uno::XInterface > SAL_CALL static_create( + css::uno::Reference< css::uno::XComponentContext > const & xContext) + SAL_THROW((css::uno::Exception)) + { return static_cast< cppu::OWeakObject * >(new Provider(xContext)); } + + static rtl::OUString SAL_CALL static_getImplementationName(); + + static css::uno::Sequence< rtl::OUString > SAL_CALL + static_getSupportedServiceNames(); + +private: + Provider( + css::uno::Reference< css::uno::XComponentContext > const & context): + context_(context) { OSL_ASSERT(context.is()); } + + virtual ~Provider() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return static_getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName) + throw (css::uno::RuntimeException) + { return ServiceName == getSupportedServiceNames()[0]; } //TODO + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return static_getSupportedServiceNames(); } + + virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( + css::util::URL const &, rtl::OUString const &, sal_Int32) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > + SAL_CALL queryDispatches( + css::uno::Sequence< css::frame::DispatchDescriptor > const & Requests) + throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context_; +}; + +rtl::OUString Provider::static_getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.test.deployment.active_native")); +} + +css::uno::Sequence< rtl::OUString > Provider::static_getSupportedServiceNames() +{ + rtl::OUString name( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.test.deployment.active_native")); + return css::uno::Sequence< rtl::OUString >(&name, 1); +} + +css::uno::Reference< css::frame::XDispatch > Provider::queryDispatch( + css::util::URL const &, rtl::OUString const &, sal_Int32) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::frame::XDispatch > dispatch; + if (!(context_->getValueByName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.test.deployment." + "active_native_singleton"))) >>= + dispatch) || + !dispatch.is()) + { + throw css::uno::DeploymentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "component context fails to supply singleton" + " com.sun.star.test.deployment.active_native_singleton of" + " type com.sun.star.frame.XDispatch")), + context_); + } + return dispatch; +} + +css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > +Provider::queryDispatches( + css::uno::Sequence< css::frame::DispatchDescriptor > const & Requests) + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > s( + Requests.getLength()); + for (sal_Int32 i = 0; i < s.getLength(); ++i) { + s[i] = queryDispatch( + Requests[i].FeatureURL, Requests[i].FrameName, + Requests[i].SearchFlags); + } + return s; +} + +class Dispatch: + public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::frame::XDispatch >, + private boost::noncopyable +{ +public: + static css::uno::Reference< css::uno::XInterface > SAL_CALL static_create( + css::uno::Reference< css::uno::XComponentContext > const & xContext) + SAL_THROW((css::uno::Exception)) + { return static_cast< cppu::OWeakObject * >(new Dispatch(xContext)); } + + static rtl::OUString SAL_CALL static_getImplementationName(); + + static css::uno::Sequence< rtl::OUString > SAL_CALL + static_getSupportedServiceNames() + { return css::uno::Sequence< rtl::OUString >(); } + +private: + Dispatch( + css::uno::Reference< css::uno::XComponentContext > const & context): + context_(context) { OSL_ASSERT(context.is()); } + + virtual ~Dispatch() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return static_getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const &) + throw (css::uno::RuntimeException) + { return false; } //TODO + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return static_getSupportedServiceNames(); } + + virtual void SAL_CALL dispatch( + css::util::URL const &, + css::uno::Sequence< css::beans::PropertyValue > const &) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL addStatusListener( + css::uno::Reference< css::frame::XStatusListener > const &, + css::util::URL const &) + throw (css::uno::RuntimeException) + {} + + virtual void SAL_CALL removeStatusListener( + css::uno::Reference< css::frame::XStatusListener > const &, + css::util::URL const &) + throw (css::uno::RuntimeException) + {} + + css::uno::Reference< css::uno::XComponentContext > context_; +}; + +rtl::OUString Dispatch::static_getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.test.deployment.active_native_singleton")); +} + +void Dispatch::dispatch( + css::util::URL const &, + css::uno::Sequence< css::beans::PropertyValue > const &) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::lang::XMultiComponentFactory > smgr( + context_->getServiceManager(), css::uno::UNO_SET_THROW); + css::uno::Reference< css::awt::XMessageBox > box( + css::uno::Reference< css::awt::XMessageBoxFactory >( + smgr->createInstanceWithContext( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.awt.Toolkit")), context_), + css::uno::UNO_QUERY_THROW)->createMessageBox( + css::uno::Reference< css::awt::XWindowPeer >( + css::uno::Reference< css::frame::XFrame >( + css::uno::Reference< css::frame::XDesktop >( + smgr->createInstanceWithContext( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.Desktop")), + context_), + css::uno::UNO_QUERY_THROW)->getCurrentFrame(), + css::uno::UNO_SET_THROW)->getComponentWindow(), + css::uno::UNO_QUERY_THROW), + css::awt::Rectangle(), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("infobox")), + css::awt::MessageBoxButtons::BUTTONS_OK, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("active")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("native"))), + css::uno::UNO_SET_THROW); + box->execute(); + css::uno::Reference< css::lang::XComponent >( + box, css::uno::UNO_QUERY_THROW)->dispose(); +} + +static cppu::ImplementationEntry const services[] = { + { &Provider::static_create, &Provider::static_getImplementationName, + &Provider::static_getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, + { &Dispatch::static_create, &Dispatch::static_getImplementationName, + &Dispatch::static_getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, + { 0, 0, 0, 0, 0, 0 } +}; + +} + +extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + char const * pImplName, void * pServiceManager, void * pRegistryKey) +{ + return cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, services); +} + +extern "C" sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey) +{ + if (!component_writeInfoHelper(pServiceManager, pRegistryKey, services)) { + return false; + } + try { + css::uno::Reference< css::registry::XRegistryKey >( + (css::uno::Reference< css::registry::XRegistryKey >( + static_cast< css::registry::XRegistryKey * >(pRegistryKey))-> + createKey( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + + Dispatch::static_getImplementationName() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "/UNO/SINGLETONS/com.sun.star.test.deployment." + "active_native_singleton")))), + css::uno::UNO_SET_THROW)-> + setStringValue(Dispatch::static_getImplementationName()); + } catch (css::uno::Exception & e) { + (void) e; + OSL_TRACE( + "active_native component_writeInfo exception: %s", + rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + return true; +} diff --git a/desktop/test/deployment/active/active_python.py b/desktop/test/deployment/active/active_python.py new file mode 100755 index 000000000000..8ba0947b6bf8 --- /dev/null +++ b/desktop/test/deployment/active/active_python.py @@ -0,0 +1,120 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#***********************************************************************/ + +import uno +import unohelper + +from com.sun.star.awt import Rectangle +from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK +from com.sun.star.frame import XDispatch, XDispatchProvider +from com.sun.star.lang import XServiceInfo +from com.sun.star.registry import InvalidRegistryException + +class Provider(unohelper.Base, XServiceInfo, XDispatchProvider): + implementationName = "com.sun.star.comp.test.deployment.active_python" + + serviceNames = ("com.sun.star.test.deployment.active_python",) + + def __init__(self, context): + self.context = context + + def getImplementationName(self): + return self.implementationName + + def supportsService(self, ServiceName): + return ServiceName in self.serviceNames + + def getSupportedServiceNames(self): + return self.serviceNames + + def queryDispatch(self, URL, TargetFrame, SearchFlags): + return self.context.getValueByName( \ + "/singletons/com.sun.star.test.deployment.active_python_singleton") + + def queryDispatches(self, Requests): + tuple( \ + self.queryDispatch(i.FeatureURL, i.FrameName, i.SearchFlags) \ + for i in Requests) + +class Dispatch(unohelper.Base, XServiceInfo, XDispatch): + implementationName = \ + "com.sun.star.comp.test.deployment.active_python_singleton" + + serviceNames = () + + def __init__(self, context): + self.context = context + + def getImplementationName(self): + return self.implementationName + + def supportsService(self, ServiceName): + return ServiceName in self.serviceNames + + def getSupportedServiceNames(self): + return self.serviceNames + + def dispatch(self, URL, Arguments): + smgr = self.context.getServiceManager() + box = smgr.createInstanceWithContext( \ + "com.sun.star.awt.Toolkit", self.context).createMessageBox( \ + smgr.createInstanceWithContext( \ + "com.sun.star.frame.Desktop", self.context). \ + getCurrentFrame().getComponentWindow(), \ + Rectangle(), "infobox", BUTTONS_OK, "active", "python") + box.execute(); + box.dispose(); + + def addStatusListener(self, Control, URL): + pass + + def removeStatusListener(self, Control, URL): + pass + +def getComponentFactory(implementationName, smgr, regKey): + if implementationName == Provider.implementationName: + return unohelper.createSingleServiceFactory( \ + Provider, Provider.implementationName, Provider.serviceNames) + elif implementationName == Dispatch.implementationName: + return unohelper.createSingleServiceFactory( \ + Dispatch, Dispatch.implementationName, Dispatch.serviceNames) + else: + return None + +def writeRegistryInfo(smgr, regKey): + try: + for i in (Provider, Dispatch): + key = regKey.createKey("/" + i.implementationName + "/UNO") + for j in i.serviceNames: + key.createKey("/SERVICES/" + j); + regKey.createKey( \ + "/" + Dispatch.implementationName + "/UNO/SINGLETONS/" \ + "com.sun.star.test.deployment.active_python_singleton"). \ + setStringValue(Dispatch.implementationName) + except InvalidRegistryException: + return False + return True diff --git a/desktop/test/deployment/active/description.xml b/desktop/test/deployment/active/description.xml new file mode 100755 index 000000000000..fd7049e0cc3d --- /dev/null +++ b/desktop/test/deployment/active/description.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<d:description xmlns:d="http://openoffice.org/extensions/description/2006"> + <d:identifier + value="org.openoffice/framework/desktop/test/deployment/active"/> + <d:version value="1"/> + <d:dependencies> + <d:OpenOffice.org-minimal-version d:name="OpenOffice.org 3.4" value="3.4"/> + </d:dependencies> +</d:description> diff --git a/desktop/test/deployment/active/makefile.mk b/desktop/test/deployment/active/makefile.mk new file mode 100755 index 000000000000..05c19eb236e3 --- /dev/null +++ b/desktop/test/deployment/active/makefile.mk @@ -0,0 +1,87 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = test_deployment_active + +ENABLE_EXCEPTIONS = TRUE + +PACKAGE = com/sun/star/comp/test/deployment/active_java +JAVAFILES = Dispatch.java Provider.java Services.java +JARFILES = juh.jar ridl.jar unoil.jar + +.INCLUDE: settings.mk + +DLLPRE = + +SLOFILES = $(SHL1OBJS) + +SHL1TARGET = active_native.uno +SHL1OBJS = $(SLO)/active_native.obj +SHL1RPATH = OXT +SHL1STDLIBS = $(CPPUHELPERLIB) $(CPPULIB) $(SALLIB) +SHL1VERSIONMAP = $(SOLARENV)/src/reg-component.map +DEF1NAME = $(SHL1TARGET) + +.INCLUDE: target.mk + +.IF "$(SOLAR_JAVA)" != "" + +ALLTAR : $(MISC)/active.oxt + +$(MISC)/active.oxt : manifest.xml description.xml Addons.xcu \ + ProtocolHandler.xcu $(SHL1TARGETN) $(MISC)/$(TARGET)/active_java.jar \ + active_python.py + $(RM) $@ + $(RM) -r $(MISC)/$(TARGET)/active.oxt-zip + $(MKDIR) $(MISC)/$(TARGET)/active.oxt-zip + $(MKDIRHIER) $(MISC)/$(TARGET)/active.oxt-zip/META-INF + $(SED) -e 's|@PATH@|$(SHL1TARGETN:f)|g' \ + -e 's|@PLATFORM@|$(RTL_OS:l)_$(RTL_ARCH:l)|g' < manifest.xml \ + > $(MISC)/$(TARGET)/active.oxt-zip/META-INF/manifest.xml + $(COPY) description.xml Addons.xcu ProtocolHandler.xcu $(SHL1TARGETN) \ + $(MISC)/$(TARGET)/active_java.jar active_python.py \ + $(MISC)/$(TARGET)/active.oxt-zip/ + cd $(MISC)/$(TARGET)/active.oxt-zip && zip ../../active.oxt \ + META-INF/manifest.xml description.xml Addons.xcu ProtocolHandler.xcu \ + $(SHL1TARGETN:f) active_java.jar active_python.py + +$(MISC)/$(TARGET)/active_java.jar : MANIFEST.MF $(JAVATARGET) + $(MKDIRHIER) $(@:d) + $(RM) $@ + $(RM) -r $(MISC)/$(TARGET)/active_java.jar-zip + $(MKDIR) $(MISC)/$(TARGET)/active_java.jar-zip + $(MKDIRHIER) $(MISC)/$(TARGET)/active_java.jar-zip/META-INF \ + $(MISC)/$(TARGET)/active_java.jar-zip/$(PACKAGE) + $(COPY) MANIFEST.MF $(MISC)/$(TARGET)/active_java.jar-zip/META-INF/ + $(COPY) $(foreach,i,$(JAVAFILES:b) $(CLASSDIR)/$(PACKAGE)/$i.class) \ + $(MISC)/$(TARGET)/active_java.jar-zip/$(PACKAGE)/ + cd $(MISC)/$(TARGET)/active_java.jar-zip && zip ../active_java.jar \ + META-INF/MANIFEST.MF $(foreach,i,$(JAVAFILES:b) $(PACKAGE)/$i.class) + +.ENDIF diff --git a/desktop/test/deployment/active/manifest.xml b/desktop/test/deployment/active/manifest.xml new file mode 100755 index 000000000000..4f076696663b --- /dev/null +++ b/desktop/test/deployment/active/manifest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<m:manifest xmlns:m="http://openoffice.org/2001/manifest"> + <m:file-entry m:media-type="application/vnd.sun.star.configuration-data" + m:full-path="Addons.xcu"/> + <m:file-entry m:media-type="application/vnd.sun.star.configuration-data" + m:full-path="ProtocolHandler.xcu"/> + <m:file-entry + m:media-type="application/vnd.sun.star.uno-component;type=native;platform=@PLATFORM@" + m:full-path="@PATH@"/> + <m:file-entry + m:media-type="application/vnd.sun.star.uno-component;type=Java" + m:full-path="active_java.jar"/> + <m:file-entry + m:media-type="application/vnd.sun.star.uno-component;type=Python" + m:full-path="active_python.py"/> +</m:manifest> diff --git a/desktop/test/deployment/boxt/Addons.xcu b/desktop/test/deployment/boxt/Addons.xcu new file mode 100644 index 000000000000..3df7e2de274c --- /dev/null +++ b/desktop/test/deployment/boxt/Addons.xcu @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<o:component-data xmlns:o="http://openoffice.org/2001/registry" + o:package="org.openoffice.Office" o:name="Addons"> + <node o:name="AddonUI"> + <node o:name="OfficeMenuBar"> + <node o:name="org.openoffice.test.desktop.deployment.boxt" o:op="replace"> + <prop o:name="Title" xml:lang="en-US"> + <value>boxt</value> + </prop> + <node o:name="Submenu"> + <node o:name="1" o:op="replace"> + <prop o:name="URL"> + <value>vnd.org.openoffice.test.desktop.deployment.boxt:</value> + </prop> + <prop o:name="Title" xml:lang="en-US"> + <value>boxt</value> + </prop> + </node> + </node> + </node> + </node> + </node> +</o:component-data> diff --git a/desktop/test/deployment/boxt/ProtocolHandler.xcu b/desktop/test/deployment/boxt/ProtocolHandler.xcu new file mode 100644 index 000000000000..fe448aedbe17 --- /dev/null +++ b/desktop/test/deployment/boxt/ProtocolHandler.xcu @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<o:component-data xmlns:o="http://openoffice.org/2001/registry" + o:package="org.openoffice.Office" o:name="ProtocolHandler"> + <node o:name="HandlerSet"> + <node o:name="com.sun.star.test.deployment.boxt" o:op="replace"> + <prop o:name="Protocols"> + <value>vnd.org.openoffice.test.desktop.deployment.boxt:*</value> + </prop> + </node> + </node> +</o:component-data> diff --git a/desktop/test/deployment/boxt/boxt.cxx b/desktop/test/deployment/boxt/boxt.cxx new file mode 100644 index 000000000000..b67625d588f0 --- /dev/null +++ b/desktop/test/deployment/boxt/boxt.cxx @@ -0,0 +1,184 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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 "precompiled_desktop.hxx" +#include "sal/config.h" + +#include "boost/noncopyable.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/frame/DispatchDescriptor.hpp" +#include "com/sun/star/frame/XDispatch.hpp" +#include "com/sun/star/frame/XDispatchProvider.hpp" +#include "com/sun/star/frame/XStatusListener.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/URL.hpp" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase3.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/weak.hxx" +#include "filter/msfilter/countryid.hxx" +#include "osl/diagnose.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "uno/lbnames.h" +#include "vcl/svapp.hxx" + +namespace { + +namespace css = com::sun::star; + +class Service: + public cppu::WeakImplHelper3< + css::lang::XServiceInfo, css::frame::XDispatchProvider, + css::frame::XDispatch >, + private boost::noncopyable +{ +public: + static css::uno::Reference< css::uno::XInterface > SAL_CALL static_create( + css::uno::Reference< css::uno::XComponentContext > const &) + SAL_THROW((css::uno::Exception)) + { return static_cast< cppu::OWeakObject * >(new Service); } + + static rtl::OUString SAL_CALL static_getImplementationName(); + + static css::uno::Sequence< rtl::OUString > SAL_CALL + static_getSupportedServiceNames(); + +private: + Service() {} + + virtual ~Service() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return static_getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName) + throw (css::uno::RuntimeException) + { return ServiceName == getSupportedServiceNames()[0]; } //TODO + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return static_getSupportedServiceNames(); } + + virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( + css::util::URL const &, rtl::OUString const &, sal_Int32) + throw (css::uno::RuntimeException) + { return this; } + + virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > + SAL_CALL queryDispatches( + css::uno::Sequence< css::frame::DispatchDescriptor > const & Requests) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL dispatch( + css::util::URL const &, + css::uno::Sequence< css::beans::PropertyValue > const &) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL addStatusListener( + css::uno::Reference< css::frame::XStatusListener > const &, + css::util::URL const &) + throw (css::uno::RuntimeException) + {} + + virtual void SAL_CALL removeStatusListener( + css::uno::Reference< css::frame::XStatusListener > const &, + css::util::URL const &) + throw (css::uno::RuntimeException) + {} +}; + +rtl::OUString Service::static_getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.test.deployment.boxt")); +} + +css::uno::Sequence< rtl::OUString > Service::static_getSupportedServiceNames() { + rtl::OUString name( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.test.deployment.boxt")); + return css::uno::Sequence< rtl::OUString >(&name, 1); +} + +css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > +Service::queryDispatches( + css::uno::Sequence< css::frame::DispatchDescriptor > const & Requests) + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > s( + Requests.getLength()); + for (sal_Int32 i = 0; i < s.getLength(); ++i) { + s[i] = queryDispatch( + Requests[i].FeatureURL, Requests[i].FrameName, + Requests[i].SearchFlags); + } + return s; +} + +void Service::dispatch( + css::util::URL const &, + css::uno::Sequence< css::beans::PropertyValue > const &) + throw (css::uno::RuntimeException) +{ + msfilter::ConvertCountryToLanguage(msfilter::COUNTRY_DONTKNOW); + // link against some obscure library that is unlikely already loaded + Application::ShowNativeErrorBox( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("boxt")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("test"))); +} + +static cppu::ImplementationEntry const services[] = { + { &Service::static_create, &Service::static_getImplementationName, + &Service::static_getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, + { 0, 0, 0, 0, 0, 0 } +}; + +} + +extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + char const * pImplName, void * pServiceManager, void * pRegistryKey) +{ + return cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, services); +} + +extern "C" sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey) +{ + return component_writeInfoHelper(pServiceManager, pRegistryKey, services); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/test/deployment/boxt/description.xml b/desktop/test/deployment/boxt/description.xml new file mode 100755 index 000000000000..5a67bf3e949f --- /dev/null +++ b/desktop/test/deployment/boxt/description.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<d:description xmlns:d="http://openoffice.org/extensions/description/2006"> + <d:identifier value="org.openoffice/framework/desktop/test/deployment/boxt"/> + <d:version value="@VERSION@"/> + <d:platform value="@PLATFORM@"/> + <d:dependencies> + <d:OpenOffice.org-minimal-version d:name="OpenOffice.org @VERSION@" + value="@VERSION@"/> + <d:OpenOffice.org-maximal-version d:name="OpenOffice.org @VERSION@ or older" + d:OpenOffice.org-minimal-version="2.3" value="@VERSION@"/> + </d:dependencies> +</d:description> diff --git a/desktop/test/deployment/boxt/makefile.mk b/desktop/test/deployment/boxt/makefile.mk new file mode 100755 index 000000000000..88e72aef4ab8 --- /dev/null +++ b/desktop/test/deployment/boxt/makefile.mk @@ -0,0 +1,68 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = test_deployment_boxt + +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE: settings.mk +.INCLUDE: rtlbootstrap.mk +.INCLUDE: versionlist.mk + +my_version = $(OOOBASEVERSIONMAJOR).$(OOOBASEVERSIONMINOR) + +DLLPRE = + +SLOFILES = $(SHL1OBJS) + +SHL1TARGET = boxt.uno +SHL1OBJS = $(SLO)/boxt.obj +SHL1RPATH = BOXT +SHL1STDLIBS = \ + $(CPPUHELPERLIB) $(CPPULIB) $(MSFILTERLIB) $(SALLIB) $(TOOLSLIB) $(VCLLIB) +SHL1VERSIONMAP = $(SOLARENV)/src/reg-component.map +DEF1NAME = $(SHL1TARGET) + +.INCLUDE: target.mk + +ALLTAR : $(MISC)/boxt.oxt + +$(MISC)/boxt.oxt .ERRREMOVE : manifest.xml description.xml Addons.xcu \ + ProtocolHandler.xcu $(SHL1TARGETN) + $(RM) -r $@ $(MISC)/$(TARGET).zip + $(MKDIR) $(MISC)/$(TARGET).zip + $(MKDIR) $(MISC)/$(TARGET).zip/META-INF + $(SED) -e 's|@PATH@|$(SHL1TARGETN:f)|g' < manifest.xml \ + > $(MISC)/$(TARGET).zip/META-INF/manifest.xml + $(SED) -e 's|@PLATFORM@|$(RTL_OS:l)_$(RTL_ARCH:l)|g' \ + -e 's|@VERSION@|$(my_version)|g' < description.xml \ + > $(MISC)/$(TARGET).zip/description.xml + $(COPY) Addons.xcu ProtocolHandler.xcu $(SHL1TARGETN) $(MISC)/$(TARGET).zip + cd $(MISC)/$(TARGET).zip && zip ../boxt.oxt META-INF/manifest.xml \ + description.xml Addons.xcu ProtocolHandler.xcu $(SHL1TARGETN:f) diff --git a/desktop/test/deployment/boxt/manifest.xml b/desktop/test/deployment/boxt/manifest.xml new file mode 100755 index 000000000000..73ebfc306e30 --- /dev/null +++ b/desktop/test/deployment/boxt/manifest.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<m:manifest xmlns:m="http://openoffice.org/2001/manifest"> + <m:file-entry m:media-type="application/vnd.sun.star.configuration-data" + m:full-path="Addons.xcu"/> + <m:file-entry m:media-type="application/vnd.sun.star.configuration-data" + m:full-path="ProtocolHandler.xcu"/> + <m:file-entry + m:media-type="application/vnd.sun.star.uno-component;type=native" + m:full-path="@PATH@"/> +</m:manifest> diff --git a/desktop/test/deployment/dependencies/broken-dependency.oxt b/desktop/test/deployment/dependencies/broken-dependency.oxt Binary files differnew file mode 100644 index 000000000000..11bab0a95092 --- /dev/null +++ b/desktop/test/deployment/dependencies/broken-dependency.oxt diff --git a/desktop/test/deployment/dependencies/double-dependencies.oxt b/desktop/test/deployment/dependencies/double-dependencies.oxt Binary files differnew file mode 100644 index 000000000000..055c27ea53ba --- /dev/null +++ b/desktop/test/deployment/dependencies/double-dependencies.oxt diff --git a/desktop/test/deployment/dependencies/empty-dependencies.oxt b/desktop/test/deployment/dependencies/empty-dependencies.oxt Binary files differnew file mode 100644 index 000000000000..ebb18dcbf51b --- /dev/null +++ b/desktop/test/deployment/dependencies/empty-dependencies.oxt diff --git a/desktop/test/deployment/dependencies/funny-dependency.oxt b/desktop/test/deployment/dependencies/funny-dependency.oxt Binary files differnew file mode 100644 index 000000000000..9b683e6d1e4b --- /dev/null +++ b/desktop/test/deployment/dependencies/funny-dependency.oxt diff --git a/desktop/test/deployment/dependencies/license-dependency.oxt b/desktop/test/deployment/dependencies/license-dependency.oxt Binary files differnew file mode 100644 index 000000000000..b01da4b5ca8a --- /dev/null +++ b/desktop/test/deployment/dependencies/license-dependency.oxt diff --git a/desktop/test/deployment/dependencies/many-dependencies.oxt b/desktop/test/deployment/dependencies/many-dependencies.oxt Binary files differnew file mode 100644 index 000000000000..367568143778 --- /dev/null +++ b/desktop/test/deployment/dependencies/many-dependencies.oxt diff --git a/desktop/test/deployment/dependencies/minattr22.oxt b/desktop/test/deployment/dependencies/minattr22.oxt Binary files differnew file mode 100644 index 000000000000..a6c8e3758cf4 --- /dev/null +++ b/desktop/test/deployment/dependencies/minattr22.oxt diff --git a/desktop/test/deployment/dependencies/minattr23.oxt b/desktop/test/deployment/dependencies/minattr23.oxt Binary files differnew file mode 100644 index 000000000000..83d17938c425 --- /dev/null +++ b/desktop/test/deployment/dependencies/minattr23.oxt diff --git a/desktop/test/deployment/dependencies/minattr24.oxt b/desktop/test/deployment/dependencies/minattr24.oxt Binary files differnew file mode 100644 index 000000000000..00f053f487ec --- /dev/null +++ b/desktop/test/deployment/dependencies/minattr24.oxt diff --git a/desktop/test/deployment/dependencies/no-dependencies.oxt b/desktop/test/deployment/dependencies/no-dependencies.oxt Binary files differnew file mode 100644 index 000000000000..6487eb66ae14 --- /dev/null +++ b/desktop/test/deployment/dependencies/no-dependencies.oxt diff --git a/desktop/test/deployment/dependencies/no-description.oxt b/desktop/test/deployment/dependencies/no-description.oxt Binary files differnew file mode 100644 index 000000000000..1e6579cd7dd4 --- /dev/null +++ b/desktop/test/deployment/dependencies/no-description.oxt diff --git a/desktop/test/deployment/dependencies/readme.txt b/desktop/test/deployment/dependencies/readme.txt new file mode 100755 index 000000000000..a99fade00225 --- /dev/null +++ b/desktop/test/deployment/dependencies/readme.txt @@ -0,0 +1,82 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +no-description.oxt, no-dependencies.oxt, empty-dependencies.oxt effectively have +no dependencies and should thus install successfully. + +broken-dependencies.oxt contains a malformed description.xml and should thus +display an error and not install. + +double-dependencies.oxt contains a description.xml with two dependencies +elements. This is not allowed by the spec but behaviour is unspecified. In the +current implementation, it combines the two elements, and thus finds two +unsatisfied dependencies, displays the Unsatisfied Dependencies dialog and does +not install. + +version21.oxt contains a dependency on OOo 2.1 (and should thus only install in +OOo 2.1 or later); version21ns.oxt is the same, but with a different way of +using XML namespaces; version21other.oxt additionally contains an unsatisfied +dependency (and should thus not install in any OOo version). version22.oxt +contains a dependency on OOo 2.2 (and should thus only install in OOo 2.2 or +later). version23.oxt contains a dependency on OOo 2.3 (and should thus only +install in OOo 2.3 or later). version10000.oxt contains a dependency on the +hypothetical OOo version 10000 (and should thus not install in any OOo version). +versionempty.oxt contains an empty value attribute and versionnone.oxt lacks the +value attribute; neither is allowed by the spec, but the current implementation +treats both as pre OOo 2.1 versions (and the extensions should thus install in +OOo 2.1 or later). + +maxversion30.oxt contains a maximal version dependency on OOo 3.0 (and should +thus only install in OOo 3.0 or earlier, back to OOo 2.3, thanks to the +additionally specified OpenOffice.org-minimal-version attribute). +maxversion10000.oxt contains a maximal version dependency on the hypothetical +OOo version 10000 (and should thus install in any OOo version 3.1 or later; +OpenOffice.org-maximal-version was introduced in OOo 3.1, and no OpenOffice.org- +minimal-version attribute is specified). bad-minmaxversion.oxt contains a +minimal version dependency on OOo 3.2 and a maximal version dependency on +OOo 3.1 (and should thus not install in any OOo version). + +minattr22.oxt contains a (hypothetical, most probably never satisfied) +UNSATISFIED dependency with an OpenOffice.org-minimal-version attribute of +"2.2" (and should thus install in OOo 2.3 or later); minattr23.oxt is similar, +but with an OpenOffice.org-minimal-version attribute of "2.3" (and should thus +also install in OOo 2.3 or later); minattr24.oxt is similar, but with an +OpenOffice.org-minimal-version attribute of "2.4" (and should thus only install +in OOo 2.4 or later). + +All of the following testcases should result in the Unsatisfied Dependencies +dialog being displayed and the extension not being installed: + +unknown-dependency.oxt contains a dependency without a name attribute, and +should thus display "Unknown" (localized). + +funny-dependency.oxt, many-dependencies.oxt contain somewhat extreme input. + +license-dependency.oxt contains both a license to be accepted by the user and +dependencies. What is important here is that the Unsatisfied Dependencies +dialog is displayed, but not the license (as installation aborts as soon as +unsatisfied dependencies are found). diff --git a/desktop/test/deployment/dependencies/unknown-dependency.oxt b/desktop/test/deployment/dependencies/unknown-dependency.oxt Binary files differnew file mode 100644 index 000000000000..7c2a22c6d5da --- /dev/null +++ b/desktop/test/deployment/dependencies/unknown-dependency.oxt diff --git a/desktop/test/deployment/dependencies/version10000.oxt b/desktop/test/deployment/dependencies/version10000.oxt Binary files differnew file mode 100644 index 000000000000..c15b7a117c8c --- /dev/null +++ b/desktop/test/deployment/dependencies/version10000.oxt diff --git a/desktop/test/deployment/dependencies/version21.oxt b/desktop/test/deployment/dependencies/version21.oxt Binary files differnew file mode 100644 index 000000000000..922b2795555c --- /dev/null +++ b/desktop/test/deployment/dependencies/version21.oxt diff --git a/desktop/test/deployment/dependencies/version21ns.oxt b/desktop/test/deployment/dependencies/version21ns.oxt Binary files differnew file mode 100644 index 000000000000..5efb2ed90220 --- /dev/null +++ b/desktop/test/deployment/dependencies/version21ns.oxt diff --git a/desktop/test/deployment/dependencies/version21other.oxt b/desktop/test/deployment/dependencies/version21other.oxt Binary files differnew file mode 100644 index 000000000000..d88a8155af65 --- /dev/null +++ b/desktop/test/deployment/dependencies/version21other.oxt diff --git a/desktop/test/deployment/dependencies/version22.oxt b/desktop/test/deployment/dependencies/version22.oxt Binary files differnew file mode 100644 index 000000000000..4c8a207b68ba --- /dev/null +++ b/desktop/test/deployment/dependencies/version22.oxt diff --git a/desktop/test/deployment/dependencies/version23.oxt b/desktop/test/deployment/dependencies/version23.oxt Binary files differnew file mode 100644 index 000000000000..6c08d2949ced --- /dev/null +++ b/desktop/test/deployment/dependencies/version23.oxt diff --git a/desktop/test/deployment/dependencies/versionempty.oxt b/desktop/test/deployment/dependencies/versionempty.oxt Binary files differnew file mode 100644 index 000000000000..a06bb01294f4 --- /dev/null +++ b/desktop/test/deployment/dependencies/versionempty.oxt diff --git a/desktop/test/deployment/dependencies/versionnone.oxt b/desktop/test/deployment/dependencies/versionnone.oxt Binary files differnew file mode 100644 index 000000000000..ace2a11651ff --- /dev/null +++ b/desktop/test/deployment/dependencies/versionnone.oxt diff --git a/desktop/test/deployment/description/desc1.oxt b/desktop/test/deployment/description/desc1.oxt Binary files differnew file mode 100644 index 000000000000..e447fd6eae78 --- /dev/null +++ b/desktop/test/deployment/description/desc1.oxt diff --git a/desktop/test/deployment/description/desc2.oxt b/desktop/test/deployment/description/desc2.oxt Binary files differnew file mode 100644 index 000000000000..8df2f33fa6de --- /dev/null +++ b/desktop/test/deployment/description/desc2.oxt diff --git a/desktop/test/deployment/description/desc3.oxt b/desktop/test/deployment/description/desc3.oxt Binary files differnew file mode 100644 index 000000000000..fbd1136b039a --- /dev/null +++ b/desktop/test/deployment/description/desc3.oxt diff --git a/desktop/test/deployment/description/desc4.oxt b/desktop/test/deployment/description/desc4.oxt Binary files differnew file mode 100644 index 000000000000..0c97f5fd4426 --- /dev/null +++ b/desktop/test/deployment/description/desc4.oxt diff --git a/desktop/test/deployment/description/desc5.oxt b/desktop/test/deployment/description/desc5.oxt Binary files differnew file mode 100644 index 000000000000..8110073499ca --- /dev/null +++ b/desktop/test/deployment/description/desc5.oxt diff --git a/desktop/test/deployment/description/readme.txt b/desktop/test/deployment/description/readme.txt new file mode 100755 index 000000000000..bb133ba516ce --- /dev/null +++ b/desktop/test/deployment/description/readme.txt @@ -0,0 +1,23 @@ +The folder contains extensions which use in the description.xml the following:
+-The <extension-description> element The element contains localized child
+elements.
+
+The following table shows what localized item is used, when the Office the locale
+en-US uses. The displayed extension description contains the locale.
+
+
+Localization:
+
+Installed office: en-US
+ | locale
+=========================
+desc1.oxt | en-US
+-------------------------
+desc2.oxt | en-US-region1
+--------------------------
+desc3.oxt | en
+--------------------------
+desc4.oxt | en-GB
+--------------------------
+desc5.oxt | de
+
diff --git a/desktop/test/deployment/display_name/name1.oxt b/desktop/test/deployment/display_name/name1.oxt Binary files differnew file mode 100644 index 000000000000..5a53690d6935 --- /dev/null +++ b/desktop/test/deployment/display_name/name1.oxt diff --git a/desktop/test/deployment/display_name/name2.oxt b/desktop/test/deployment/display_name/name2.oxt Binary files differnew file mode 100644 index 000000000000..f6cbcae3bcbd --- /dev/null +++ b/desktop/test/deployment/display_name/name2.oxt diff --git a/desktop/test/deployment/display_name/name3.oxt b/desktop/test/deployment/display_name/name3.oxt Binary files differnew file mode 100644 index 000000000000..8df750ce62a5 --- /dev/null +++ b/desktop/test/deployment/display_name/name3.oxt diff --git a/desktop/test/deployment/display_name/name4.oxt b/desktop/test/deployment/display_name/name4.oxt Binary files differnew file mode 100644 index 000000000000..6ce4822e3701 --- /dev/null +++ b/desktop/test/deployment/display_name/name4.oxt diff --git a/desktop/test/deployment/display_name/name5.oxt b/desktop/test/deployment/display_name/name5.oxt Binary files differnew file mode 100644 index 000000000000..56973be7817b --- /dev/null +++ b/desktop/test/deployment/display_name/name5.oxt diff --git a/desktop/test/deployment/display_name/readme.txt b/desktop/test/deployment/display_name/readme.txt new file mode 100755 index 000000000000..23173bde63dd --- /dev/null +++ b/desktop/test/deployment/display_name/readme.txt @@ -0,0 +1,26 @@ +The folder contains extensions which use in the description.xml the following: +-The <display-name> element +The element contains localized child elements. + +To test the display name in the update dialog use the extensions in +desktop/test/deployment/update/simple + + +The following table shows what localized item is used, when the Office the locale +en-US uses. + + +Localization: + +Installed office: en-US + | publisher | release notes +============================================= +name1.oxt | en-US | en-US +--------------------------------------------- +name2.oxt | en-US-region1 | en-US-region1 +--------------------------------------------- +name3.oxt | en | en +--------------------------------------------- +name4.oxt | en-GB | en-GB +--------------------------------------------- +name5.oxt | de | de diff --git a/desktop/test/deployment/executable_content/build/hello.c b/desktop/test/deployment/executable_content/build/hello.c new file mode 100755 index 000000000000..4af0b02ff888 --- /dev/null +++ b/desktop/test/deployment/executable_content/build/hello.c @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <stdio.h> + +int main(int argc , char** argv, char** envp) +{ + //prevent warning about unused parameters + //we need to provide parameter names in C + (void)argc; + (void)argv; + (void)envp; + + fprintf(stdout,"Hello world!\n"); + return 0; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/test/deployment/executable_content/build/makefile.mk b/desktop/test/deployment/executable_content/build/makefile.mk new file mode 100755 index 000000000000..038051c97499 --- /dev/null +++ b/desktop/test/deployment/executable_content/build/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = hello +LIBTARGET=NO +NO_DEFAULT_STL=TRUE +LIBSALCPPRT= + +.INCLUDE : settings.mk + + +APP1NOSAL = TRUE +APP1OBJS = \ + $(OBJ)$/hello.obj + + +APP1TARGET = $(TARGET) + +DEPOBJFILES = \ + $(OBJ)$/hello.obj + + +.INCLUDE : target.mk + diff --git a/desktop/test/deployment/executable_content/build/readme.txt b/desktop/test/deployment/executable_content/build/readme.txt new file mode 100755 index 000000000000..4f956e573e07 --- /dev/null +++ b/desktop/test/deployment/executable_content/build/readme.txt @@ -0,0 +1,2 @@ +This folder contains the sources to build the hello executable which is contained +in the hello.oxt. diff --git a/desktop/test/deployment/executable_content/hello.oxt b/desktop/test/deployment/executable_content/hello.oxt Binary files differnew file mode 100644 index 000000000000..97d6d14a3128 --- /dev/null +++ b/desktop/test/deployment/executable_content/hello.oxt diff --git a/desktop/test/deployment/executable_content/readme.txt b/desktop/test/deployment/executable_content/readme.txt new file mode 100755 index 000000000000..ad3c01097e14 --- /dev/null +++ b/desktop/test/deployment/executable_content/readme.txt @@ -0,0 +1,12 @@ +When the executable is installed try to execute the executable "hello". The executable +file attribute (not on Windows) should be set. + +CD into the extension directory in /user|share)/uno_packages/cache/uno_packages/xyz_ +Then there are the directories for different platforms: + +windows, +solaris, +linux + +Each directory contains a hello executable. On linux one should execute it in a +shell with an build environment, so that the c++ runtime is found. diff --git a/desktop/test/deployment/identifier/explicit/identifier.oxt b/desktop/test/deployment/identifier/explicit/identifier.oxt Binary files differnew file mode 100644 index 000000000000..3851e291c970 --- /dev/null +++ b/desktop/test/deployment/identifier/explicit/identifier.oxt diff --git a/desktop/test/deployment/identifier/legacy/identifier.oxt b/desktop/test/deployment/identifier/legacy/identifier.oxt Binary files differnew file mode 100644 index 000000000000..df8bb8449241 --- /dev/null +++ b/desktop/test/deployment/identifier/legacy/identifier.oxt diff --git a/desktop/test/deployment/identifier/readme.txt b/desktop/test/deployment/identifier/readme.txt new file mode 100755 index 000000000000..8a791c586a78 --- /dev/null +++ b/desktop/test/deployment/identifier/readme.txt @@ -0,0 +1,33 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +legacy/identifier.oxt and explicit/identifier.oxt are two different extensions +that happen to have the same file name. legacy/identifier.oxt does not have an +explicit extension identifier, so it gets the implicit one "org.openoffice. +legacy.identifier.oxt". explicit/identifier.oxt has the +explicit extension identifier "org.openoffice/framework/desktop/test/deployment/ +identifier/explicit/identifier.oxt". diff --git a/desktop/test/deployment/locationtest/LocationTest.idl b/desktop/test/deployment/locationtest/LocationTest.idl new file mode 100644 index 000000000000..2bcc6818c168 --- /dev/null +++ b/desktop/test/deployment/locationtest/LocationTest.idl @@ -0,0 +1,40 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _com_sun_star_comp_smoketest_LocationTest_idl_ +#define _com_sun_star_comp_smoketest_LocationTest_idl_ + +#include <com/sun/star/lang/XServiceInfo.idl> + + +module com { module sun { module star { module comp { module smoketest { + // example service, XServiceInfo is implemented here for demonstration + // issues. XServiceInfo must be implemented by all components. + service TestExtension: ::com::sun::star::lang::XServiceInfo; +};};};};}; + +#endif diff --git a/desktop/test/deployment/locationtest/LocationTest.java b/desktop/test/deployment/locationtest/LocationTest.java new file mode 100755 index 000000000000..c5d24f4b0ecc --- /dev/null +++ b/desktop/test/deployment/locationtest/LocationTest.java @@ -0,0 +1,165 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + *************************************************************************/ +package com.sun.star.comp.smoketest; + +import com.sun.star.lib.uno.helper.Factory; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.lang.XInitialization; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.uno.Type; + +/** This class capsulates the class, that implements the minimal component, a + * factory for creating the service (<CODE>__getComponentFactory</CODE>) and a + * method, that writes the information into the given registry key + * (<CODE>__writeRegistryServiceInfo</CODE>). + */ +public class LocationTest { + /** This class implements the component. At least the interfaces XServiceInfo, + * XTypeProvider, and XInitialization should be provided by the service. + */ + public static class _LocationTest extends WeakBase + implements XServiceInfo { + /** The service name, that must be used to get an instance of this service. + */ + static private final String __serviceName = + "com.sun.star.comp.smoketest.LocationTest"; + + /** The initial component contextr, that gives access to + * the service manager, supported singletons, ... + * It's often later used + */ + private XComponentContext m_cmpCtx; + + /** The service manager, that gives access to all registered services. + * It's often later used + */ + private XMultiComponentFactory m_xMCF; + + /** The constructor of the inner class has a XMultiServiceFactory parameter. + * @param xmultiservicefactoryInitialization A special service factory + * could be introduced while initializing. + */ + public _LocationTest(XComponentContext xCompContext) { + try { + m_cmpCtx = xCompContext; + m_xMCF = m_cmpCtx.getServiceManager(); + } + catch( Exception e ) { + e.printStackTrace(); + } + } + + /** This method returns an array of all supported service names. + * @return Array of supported service names. + */ + public String[] getSupportedServiceNames() { + return getServiceNames(); + } + + /** This method is a simple helper function to used in the + * static component initialisation functions as well as in + * getSupportedServiceNames. + */ + public static String[] getServiceNames() { + String[] sSupportedServiceNames = { __serviceName }; + return sSupportedServiceNames; + } + + /** This method returns true, if the given service will be + * supported by the component. + * @param sServiceName Service name. + * @return True, if the given service name will be supported. + */ + public boolean supportsService( String sServiceName ) { + return sServiceName.equals( __serviceName ); + } + + /** Return the class name of the component. + * @return Class name of the component. + */ + public String getImplementationName() { + return _LocationTest.class.getName(); + } + } + + + /** + * Gives a factory for creating the service. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns a <code>XSingleComponentFactory</code> for creating + * the component + * @param sImplName the name of the implementation for which a + * service is desired + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleComponentFactory __getComponentFactory(String sImplName) + { + XSingleComponentFactory xFactory = null; + + if ( sImplName.equals( _LocationTest.class.getName() ) ) + xFactory = Factory.createComponentFactory(_LocationTest.class, + _LocationTest.getServiceNames()); + + return xFactory; + } + + /** + * Writes the service information into the given registry key. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns true if the operation succeeded + * @param regKey the registryKey + * @see com.sun.star.comp.loader.JavaLoader + */ + public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { + return Factory.writeRegistryServiceInfo(_LocationTest.class.getName(), + _LocationTest.getServiceNames(), + regKey); + } + + /** This method is a member of the interface for initializing an object + * directly after its creation. + * @param object This array of arbitrary objects will be passed to the + * component after its creation. + * @throws Exception Every exception will not be handled, but will be + * passed to the caller. + */ + public void initialize( Object[] object ) + throws com.sun.star.uno.Exception { + /* The component describes what arguments its expected and in which + * order!At this point you can read the objects and can intialize + * your component using these objects. + */ + } +} diff --git a/desktop/test/deployment/locationtest/LocationTest.odt b/desktop/test/deployment/locationtest/LocationTest.odt Binary files differnew file mode 100644 index 000000000000..8e1aa70078db --- /dev/null +++ b/desktop/test/deployment/locationtest/LocationTest.odt diff --git a/desktop/test/deployment/locationtest/MANIFEST.MF b/desktop/test/deployment/locationtest/MANIFEST.MF new file mode 100755 index 000000000000..a2fa8c34b7f9 --- /dev/null +++ b/desktop/test/deployment/locationtest/MANIFEST.MF @@ -0,0 +1,2 @@ +RegistrationClassName: com.sun.star.comp.smoketest.LocationTest + diff --git a/desktop/test/deployment/locationtest/delzip b/desktop/test/deployment/locationtest/delzip new file mode 100755 index 000000000000..636fda90bfcb --- /dev/null +++ b/desktop/test/deployment/locationtest/delzip @@ -0,0 +1 @@ +ECHO is OFF diff --git a/desktop/test/deployment/locationtest/description.xml b/desktop/test/deployment/locationtest/description.xml new file mode 100755 index 000000000000..b8874dd4da85 --- /dev/null +++ b/desktop/test/deployment/locationtest/description.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:d="http://openoffice.org/extensions/description/2006" > + <identifier value="org.openoffice.extensions.testarea.desktop.location"/> + <version value="1.0" /> + <dependencies > + <OpenOffice.org-minimal-version value="2.2" d:name="OpenOffice.org 2.2"/> + </dependencies> + <update-information> + <src xlink:href="http://update.services.openoffice.org/ProductUpdateService/check.Update?product=extension&extensionid=org.openoffice.extensions.testarea.desktop.updateinfo&refresh=true"/> + </update-information> +</description> diff --git a/desktop/test/deployment/locationtest/makefile.mk b/desktop/test/deployment/locationtest/makefile.mk new file mode 100755 index 000000000000..24be56c28d7e --- /dev/null +++ b/desktop/test/deployment/locationtest/makefile.mk @@ -0,0 +1,87 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = location_test +PACKAGE = com$/sun$/star$/comp$/smoketest +TARGET = com_sun_star_comp_smoketest + +no_common_build_zip:=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +JARFILES = ridl.jar jurt.jar unoil.jar juh.jar + +JARTARGET = LocationTest.jar +JARCOMPRESS = TRUE +CUSTOMMANIFESTFILE = MANIFEST.MF + +ZIP1TARGET=locationtest +ZIP1LIST=* +ZIPFLAGS=-r +ZIP1DIR=$(MISC)$/$(TARGET) +ZIP1EXT=.oxt + +# --- Files -------------------------------------------------------- + +COPY_OXT_MANIFEST:= $(MISC)$/$(TARGET)$/META-INF$/manifest.xml +JAVAFILES = LocationTest.java + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(JARTARGETN) : $(MISC)$/$(TARGET).javamaker.done + +$(JAVACLASSFILES) : $(MISC)$/$(TARGET).javamaker.done + +$(MISC)$/$(TARGET).javamaker.done: $(BIN)$/LocationTest.rdb + $(JAVAMAKER) -O$(CLASSDIR) -BUCR -nD -X$(SOLARBINDIR)/types.rdb $< + $(TOUCH) $@ + +$(BIN)$/LocationTest.rdb: LocationTest.idl + $(IDLC) -O$(MISC) -I$(SOLARIDLDIR) -cid -we $< + +-$(RM) $@ + $(REGMERGE) $@ /UCR $(MISC)$/LocationTest.urd + +$(MISC)$/$(ZIP1TARGET).createdir : + +$(MKDIRHIER) $(MISC)$/$(TARGET)$/META-INF >& $(NULLDEV) && $(TOUCH) $@ + +$(MISC)$/$(TARGET)_resort : manifest.xml $(JARTARGETN) $(MISC)$/$(ZIP1TARGET).createdir $(BIN)$/LocationTest.rdb description.xml + $(COPY) manifest.xml $(MISC)$/$(TARGET)$/META-INF$/manifest.xml + $(COPY) $(JARTARGETN) $(MISC)$/$(TARGET)$/$(JARTARGET) + $(COPY) $(BIN)$/LocationTest.rdb $(MISC)$/$(TARGET)$/LocationTest.rdb + $(COPY) description.xml $(MISC)$/$(TARGET)$/description.xml + $(TOUCH) $@ + +.IF "$(ZIP1TARGETN)"!="" +$(ZIP1TARGETN) : $(MISC)$/$(TARGET)_resort $(MISC)$/$(ZIP1TARGET).createdir + +.ENDIF # "$(ZIP1TARGETN)"!="" + diff --git a/desktop/test/deployment/locationtest/manifest.xml b/desktop/test/deployment/locationtest/manifest.xml new file mode 100755 index 000000000000..3dd6460faffa --- /dev/null +++ b/desktop/test/deployment/locationtest/manifest.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest"> + <manifest:file-entry manifest:full-path="LocationTest.jar" manifest:media-type="application/vnd.sun.star.uno-component;type=Java"/> + <manifest:file-entry manifest:full-path="LocationTest.rdb" manifest:media-type="application/vnd.sun.star.uno-typelibrary;type=RDB"/> +</manifest:manifest> diff --git a/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/MANIFEST.MF b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/MANIFEST.MF new file mode 100755 index 000000000000..fba55a6e0d5a --- /dev/null +++ b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/MANIFEST.MF @@ -0,0 +1,2 @@ +RegistrationClassName: com.sun.star.comp.extensionoptions.OptionsEventHandler + diff --git a/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/OptionsEventHandler.java b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/OptionsEventHandler.java new file mode 100755 index 000000000000..bb38108e5eea --- /dev/null +++ b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/OptionsEventHandler.java @@ -0,0 +1,449 @@ +************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + *************************************************************************/ +package com.sun.star.comp.extensionoptions; + +import com.sun.star.lib.uno.helper.Factory; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.XInitialization; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.Any; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.Exception; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.awt.XContainerWindowEventHandler; +import com.sun.star.awt.XControl; +import com.sun.star.awt.XControlModel; +import com.sun.star.awt.XControlContainer; +import com.sun.star.container.XNameAccess; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.PropertyState; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.util.XChangesBatch; + +/** A handler which supports multiple options pages which all + * have the same controls. + */ +public class OptionsEventHandler { + + public static class _OptionsEventHandler extends WeakBase + implements XServiceInfo, XContainerWindowEventHandler { + + static private final String __serviceName = + "com.sun.star.comp.extensionoptions.OptionsEventHandler"; + + private XComponentContext m_cmpCtx; + + private XMultiComponentFactory m_xMCF; + + private XNameAccess m_xAccessLeaves; + + /**Names of supported options pages. + */ + private String[] m_arWindowNames = { + "Writer1", "Writer2", "Writer3", "Calc1", "Calc2", "Calc3", + "Draw1", "Draw2", "Draw3", "Node1_1", "Node1_2", "Node1_3", + "Node2_1", "Node2_2", "Node2_3", "Node3_1", "Node3_2", "Node3_3"}; + + /**Names of the controls which are supported by this handler. All these + *controls must have a "Text" property. + */ + private String[] m_arStringControls = { + "String0", "String1", "String2", "String3", "String4"}; + + public _OptionsEventHandler(XComponentContext xCompContext) { + m_cmpCtx = xCompContext; + m_xMCF = m_cmpCtx.getServiceManager(); + + //Create the com.sun.star.configuration.ConfigurationUpdateAccess + //for the registry node which contains the data for our option + //pages. + XMultiServiceFactory xConfig; + try { + xConfig = (XMultiServiceFactory) UnoRuntime.queryInterface( + XMultiServiceFactory.class, + m_cmpCtx.getServiceManager().createInstanceWithContext( + "com.sun.star.configuration.ConfigurationProvider", m_cmpCtx)); + } catch (com.sun.star.uno.Exception e) { + e.printStackTrace(); + return; + } + + //One argument for creating the ConfigurationUpdateAccess is the "nodepath". + //Our nodepath point to the node of which the direct subnodes represent the + //different options pages. + Object[] args = new Object[1]; + args[0] = new PropertyValue( + "nodepath", 0, "/org.openoffice.desktop.deployment.options.ExtensionData/Leaves", + PropertyState.DIRECT_VALUE); + + //We get the com.sun.star.container.XNameAccess from the instance of + //ConfigurationUpdateAccess and save it for later use. + try { + m_xAccessLeaves = (XNameAccess) UnoRuntime.queryInterface( + XNameAccess.class, xConfig.createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationUpdateAccess", args)); + + } catch (com.sun.star.uno.Exception e) { + e.printStackTrace(); + return; + } + } + + /** This method returns an array of all supported service names. + * @return Array of supported service names. + */ + public String[] getSupportedServiceNames() { + return getServiceNames(); + } + + /** This method is a simple helper function to used in the + * static component initialisation functions as well as in + * getSupportedServiceNames. + */ + public static String[] getServiceNames() { + String[] sSupportedServiceNames = { __serviceName }; + return sSupportedServiceNames; + } + + /** This method returns true, if the given service will be + * supported by the component. + * @param sServiceName Service name. + * @return True, if the given service name will be supported. + */ + public boolean supportsService( String sServiceName ) { + return sServiceName.equals( __serviceName ); + } + + /** Return the class name of the component. + * @return Class name of the component. + */ + public String getImplementationName() { + return _OptionsEventHandler.class.getName(); + } + + //XContainerWindowEventHandler + public boolean callHandlerMethod(com.sun.star.awt.XWindow aWindow, + Object aEventObject, String sMethod) + throws WrappedTargetException { + if (sMethod.equals("external_event") ){ + try { + return handleExternalEvent(aWindow, aEventObject); + } catch (com.sun.star.uno.RuntimeException re) { + throw re; + } catch (com.sun.star.uno.Exception e) { + throw new WrappedTargetException(sMethod, this, e); + } + } + + return true; + } + + //XContainerWindowEventHandler + public String[] getSupportedMethodNames() { + return new String[] {"external_event"}; + } + + private boolean handleExternalEvent(com.sun.star.awt.XWindow aWindow, Object aEventObject) + throws com.sun.star.uno.Exception { + try { + String sMethod = AnyConverter.toString(aEventObject); + if (sMethod.equals("ok")) { + saveData(aWindow); + } else if (sMethod.equals("back") || sMethod.equals("initialize")) { + loadData(aWindow); + } + } catch (com.sun.star.lang.IllegalArgumentException e) { + throw new com.sun.star.lang.IllegalArgumentException( + "Method external_event requires a string in the event object argument.", + this, (short) -1); + } + + return true; + } + + private void saveData(com.sun.star.awt.XWindow aWindow) + throws com.sun.star.lang.IllegalArgumentException, + com.sun.star.uno.Exception { + + //Determine the name of the options page. This serves two purposes. First, if this + //options page is supported by this handler and second we use the name two locate + //the corresponding data in the registry. + String sWindowName = getWindowName(aWindow); + if (sWindowName == null) + throw new com.sun.star.lang.IllegalArgumentException( + "This window is not supported by this handler", this, (short) -1); + + //To access the separate controls of the window we need to obtain the + //XControlContainer from the window implementation + XControlContainer xContainer = (XControlContainer) UnoRuntime.queryInterface( + XControlContainer.class, aWindow); + if (xContainer == null) + throw new com.sun.star.uno.Exception( + "Could not get XControlContainer from window.", this); + + //This is an implementation which will be used for several options pages + //which all have the same controls. m_arStringControls is an array which + //contains the names. + for (int i = 0; i < m_arStringControls.length; i++) { + + //To obtain the data from the controls we need to get their model. + //First get the respective control from the XControlContainer. + XControl xControl = xContainer.getControl(m_arStringControls[i]); + + //This generic handler and the corresponding registry schema support + //up to five text controls. However, if a options page does not use all + //five controls then we will not complain here. + if (xControl == null) + continue; + + //From the control we get the model, which in turn supports the + //XPropertySet interface, which we finally use to get the data from + //the control. + XPropertySet xProp = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, xControl.getModel()); + + if (xProp == null) + throw new com.sun.star.uno.Exception( + "Could not get XPropertySet from control.", this); + //Get the "Text" property. + Object aText = xProp.getPropertyValue("Text"); + String sValue = null; + + //The value is still contained in a com.sun.star.uno.Any - so convert it. + try { + sValue = AnyConverter.toString(aText); + } catch (com.sun.star.lang.IllegalArgumentException e) { + throw new com.sun.star.lang.IllegalArgumentException( + "Wrong property type.", this, (short) -1); + } + + //Now we have the actual string value of the control. What we need now is + //the XPropertySet of the respective property in the registry, so that we + //can store the value. + //To access the registry we have previously created a service instance + //of com.sun.star.configuration.ConfigurationUpdateAccess which supports + //com.sun.star.container.XNameAccess. The XNameAccess is used to get the + //particular registry node which represents this options page. + //Fortunately the name of the window is the same as the registry node. + XPropertySet xLeaf = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, m_xAccessLeaves.getByName(sWindowName)); + if (xLeaf == null) + throw new com.sun.star.uno.Exception( + "XPropertySet not supported.", this); + + //Finally we can set the value + xLeaf.setPropertyValue(m_arStringControls[i], sValue); + } + + //Committing the changes will cause or changes to be written to the registry. + XChangesBatch xUpdateCommit = + (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class, m_xAccessLeaves); + xUpdateCommit.commitChanges(); + } + + private void loadData(com.sun.star.awt.XWindow aWindow) + throws com.sun.star.uno.Exception { + + //Determine the name of the window. This serves two purposes. First, if this + //window is supported by this handler and second we use the name two locate + //the corresponding data in the registry. + String sWindowName = getWindowName(aWindow); + if (sWindowName == null) + throw new com.sun.star.lang.IllegalArgumentException( + "The window is not supported by this handler", this, (short) -1); + + //To acces the separate controls of the window we need to obtain the + //XControlContainer from window implementation + XControlContainer xContainer = (XControlContainer) UnoRuntime.queryInterface( + XControlContainer.class, aWindow); + if (xContainer == null) + throw new com.sun.star.uno.Exception( + "Could not get XControlContainer from window.", this); + + //This is an implementation which will be used for several options pages + //which all have the same controls. m_arStringControls is an array which + //contains the names. + for (int i = 0; i < m_arStringControls.length; i++) { + + //load the values from the registry + //To access the registry we have previously created a service instance + //of com.sun.star.configuration.ConfigurationUpdateAccess which supports + //com.sun.star.container.XNameAccess. We obtain now the section + //of the registry which is assigned to this options page. + XPropertySet xLeaf = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, m_xAccessLeaves.getByName(sWindowName)); + if (xLeaf == null) + throw new com.sun.star.uno.Exception( + "XPropertySet not supported.", this); + + //The properties in the registry have the same name as the respective + //controls. We use the names now to obtain the property values. + Object aValue = xLeaf.getPropertyValue(m_arStringControls[i]); + + //Now that we have the value we need to set it at the corresponding + //control in the window. The XControlContainer, which we obtained earlier + //is the means to get hold of all the controls. + XControl xControl = xContainer.getControl(m_arStringControls[i]); + + //This generic handler and the corresponding registry schema support + //up to five text controls. However, if a options page does not use all + //five controls then we will not complain here. + if (xControl == null) + continue; + + //From the control we get the model, which in turn supports the + //XPropertySet interface, which we finally use to set the data at the + //control + XPropertySet xProp = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, xControl.getModel()); + + if (xProp == null) + throw new com.sun.star.uno.Exception( + "Could not get XPropertySet from control.", this); + + //This handler supports only text controls, which are named "Pattern Field" + //in the dialog editor. We set the "Text" property. + xProp.setPropertyValue("Text", aValue); + } + } + + //Checks if the name property of the window is one of the supported names and returns + //always a valid string or null + private String getWindowName(com.sun.star.awt.XWindow aWindow) + throws com.sun.star.uno.Exception { + + if (aWindow == null) + new com.sun.star.lang.IllegalArgumentException( + "Method external_event requires that a window is passed as argument", + this, (short) -1); + + //We need to get the control model of the window. Therefore the first step is + //to query for it. + XControl xControlDlg = (XControl) UnoRuntime.queryInterface( + XControl.class, aWindow); + + if (xControlDlg == null) + throw new com.sun.star.uno.Exception( + "Cannot obtain XControl from XWindow in method external_event."); + //Now get model + XControlModel xModelDlg = xControlDlg.getModel(); + + if (xModelDlg == null) + throw new com.sun.star.uno.Exception( + "Cannot obtain XControlModel from XWindow in method external_event.", this); + //The model itself does not provide any information except that its + //implementation supports XPropertySet which is used to access the data. + XPropertySet xPropDlg = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, xModelDlg); + if (xPropDlg == null) + throw new com.sun.star.uno.Exception( + "Cannot obtain XPropertySet from window in method external_event.", this); + + //Get the "Name" property of the window + Object aWindowName = xPropDlg.getPropertyValue("Name"); + + //Get the string from the returned com.sun.star.uno.Any + String sName = null; + try { + sName = AnyConverter.toString(aWindowName); + } catch (com.sun.star.lang.IllegalArgumentException e) { + throw new com.sun.star.uno.Exception( + "Name - property of window is not a string.", this); + } + + //Eventually we can check if we this handler can "handle" this options page. + //The class has a member m_arWindowNames which contains all names of windows + //for which it is intended + for (int i = 0; i < m_arWindowNames.length; i++) { + if (m_arWindowNames[i].equals(sName)) { + return sName; + } + } + return null; + } + } + + + /** + * Gives a factory for creating the service. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns a <code>XSingleComponentFactory</code> for creating + * the component + * @param sImplName the name of the implementation for which a + * service is desired + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleComponentFactory __getComponentFactory(String sImplName) + { + XSingleComponentFactory xFactory = null; + + if ( sImplName.equals( _OptionsEventHandler.class.getName() ) ) + xFactory = Factory.createComponentFactory(_OptionsEventHandler.class, + _OptionsEventHandler.getServiceNames()); + + return xFactory; + } + + /** + * Writes the service information into the given registry key. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns true if the operation succeeded + * @param regKey the registryKey + * @see com.sun.star.comp.loader.JavaLoader + */ + public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { + return Factory.writeRegistryServiceInfo(_OptionsEventHandler.class.getName(), + _OptionsEventHandler.getServiceNames(), + regKey); + } + + /** This method is a member of the interface for initializing an object + * directly after its creation. + * @param object This array of arbitrary objects will be passed to the + * component after its creation. + * @throws Exception Every exception will not be handled, but will be + * passed to the caller. + */ + public void initialize( Object[] object ) + throws com.sun.star.uno.Exception { + } + +} diff --git a/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/makefile.mk b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/makefile.mk new file mode 100755 index 000000000000..662fffce407c --- /dev/null +++ b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 +PACKAGE = com$/sun$/star$/comp$/extensionoptions +TARGET = options + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +JARFILES = ridl.jar jurt.jar unoil.jar juh.jar + + +JARTARGET = extensionoptions.jar +JARCOMPRESS = TRUE +CUSTOMMANIFESTFILE = MANIFEST.MF +JARCLASSDIRS=com + + +# --- Files -------------------------------------------------------- + +JAVAFILES = OptionsEventHandler.java + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/desktop/test/deployment/options/leaf1.oxt b/desktop/test/deployment/options/leaf1.oxt Binary files differnew file mode 100644 index 000000000000..9c3ff86985b6 --- /dev/null +++ b/desktop/test/deployment/options/leaf1.oxt diff --git a/desktop/test/deployment/options/leaf1mod.oxt b/desktop/test/deployment/options/leaf1mod.oxt Binary files differnew file mode 100644 index 000000000000..d5d9fe6896f8 --- /dev/null +++ b/desktop/test/deployment/options/leaf1mod.oxt diff --git a/desktop/test/deployment/options/leaf2.oxt b/desktop/test/deployment/options/leaf2.oxt Binary files differnew file mode 100644 index 000000000000..b95628900c40 --- /dev/null +++ b/desktop/test/deployment/options/leaf2.oxt diff --git a/desktop/test/deployment/options/leaves1.oxt b/desktop/test/deployment/options/leaves1.oxt Binary files differnew file mode 100644 index 000000000000..037389a018b8 --- /dev/null +++ b/desktop/test/deployment/options/leaves1.oxt diff --git a/desktop/test/deployment/options/leaves2.oxt b/desktop/test/deployment/options/leaves2.oxt Binary files differnew file mode 100644 index 000000000000..531b38566352 --- /dev/null +++ b/desktop/test/deployment/options/leaves2.oxt diff --git a/desktop/test/deployment/options/leaves3.oxt b/desktop/test/deployment/options/leaves3.oxt Binary files differnew file mode 100644 index 000000000000..f5bb0f226239 --- /dev/null +++ b/desktop/test/deployment/options/leaves3.oxt diff --git a/desktop/test/deployment/options/modules1.oxt b/desktop/test/deployment/options/modules1.oxt Binary files differnew file mode 100644 index 000000000000..bae652ffbc39 --- /dev/null +++ b/desktop/test/deployment/options/modules1.oxt diff --git a/desktop/test/deployment/options/modules2.oxt b/desktop/test/deployment/options/modules2.oxt Binary files differnew file mode 100644 index 000000000000..d6d7956d459c --- /dev/null +++ b/desktop/test/deployment/options/modules2.oxt diff --git a/desktop/test/deployment/options/nodes1.oxt b/desktop/test/deployment/options/nodes1.oxt Binary files differnew file mode 100644 index 000000000000..b1dfa18d3efa --- /dev/null +++ b/desktop/test/deployment/options/nodes1.oxt diff --git a/desktop/test/deployment/options/nodes2.oxt b/desktop/test/deployment/options/nodes2.oxt Binary files differnew file mode 100644 index 000000000000..a35cfaba9dc8 --- /dev/null +++ b/desktop/test/deployment/options/nodes2.oxt diff --git a/desktop/test/deployment/options/nodes3.oxt b/desktop/test/deployment/options/nodes3.oxt Binary files differnew file mode 100644 index 000000000000..db0bc49da522 --- /dev/null +++ b/desktop/test/deployment/options/nodes3.oxt diff --git a/desktop/test/deployment/options/nodes4.oxt b/desktop/test/deployment/options/nodes4.oxt Binary files differnew file mode 100644 index 000000000000..fe0550fdc655 --- /dev/null +++ b/desktop/test/deployment/options/nodes4.oxt diff --git a/desktop/test/deployment/options/nodes5.oxt b/desktop/test/deployment/options/nodes5.oxt Binary files differnew file mode 100644 index 000000000000..893e9ee3e216 --- /dev/null +++ b/desktop/test/deployment/options/nodes5.oxt diff --git a/desktop/test/deployment/options/readme.txt b/desktop/test/deployment/options/readme.txt new file mode 100755 index 000000000000..9879a72ceffa --- /dev/null +++ b/desktop/test/deployment/options/readme.txt @@ -0,0 +1,200 @@ +Important: The hander component extensionoptions.jar in the extensions may not +contain exactly the same sources as the one build in the handler directory. To +make sure that debugging works build the handler directory and put the +extensionoptions.jar into the extension. + + + +leaf1.oxt: Defines a leaf under the node WriterNode +================================================================================ + +leaf1mod.oxt: Defines a leaf under the node WriterNode + +It has a douplicate entry in the manifest.xml (OptionsDialog.xcu). This would cause a DisposedException when uninstalling on OOo 3.0 and prevent the extension from being uninstalled. This is actually a bug of the extensions. However, the error is difficult to investigate. Therefore this was fixed to make OOo more robust (i96690). +================================================================================ + +leaf2.oxt: Defines a leaf under a node that has a name which requires special +"xml encoding". The name is "My Writer's & Settings". The node is not assigned +to a Module and the Node/AllModules property is not true. This is a typical +scenario when a Node had been added to an existing Module and later the Module +was removed. This is a situation which actually should not occur. In this case +DO NOT show the Node in the OOo's options dialog, because it shows only nodes +for a particular module and in this case the Module for the Node is unknown. +In the Extension Manager's +options dialog this Node can be shown because the Module is irrelevant. +See also nodes5.oxt. +================================================================================ + +leaves1.oxt: multiple ordered leaves under available nodes. The leaves Lables are +localized for en-US and de. The following leaves should appear: + +Writer: +-leaves1 Writer 1 en-US +-leaves1 Writer 2 en-US +-leaves1 Writer 3 en-US + +Calc: +-leaves1 Calc 3 en-US +-leaves1 Calc 3 en-US +-leaves1 Calc 3 en-US + +Draw: +-leaves1 Draw 3 en-US +-leaves1 Draw 3 en-US +-leaves1 Draw 3 en-US + +If a german office is used then the strings contain "de" instead of "en-US". +================================================================================ + +leaves2.oxt: Same as leaves1.oxt. Use together with leaves1.oxt to test the +grouping of leaves. +================================================================================ + +leaves3.oxt: Same as leaves1.oxt, but the leaves are not ordered. +================================================================================ + +nodes1.oxt: Defines one node which has AllModules set and which has +no children. Therefore this node should not be displayed. +================================================================================ + +nodes2.oxt: Defines 3 nodes which use AllModules and which form an +ordered group. Every node defines also 3 nodes which have a determined order. + +-nodes2 node 1 en-US + -nodes2 node 1 leaf 1 en-US + -nodes2 node 1 leaf 2 en-US + -nodes2 node 1 leaf 3 en-US + +-nodes2 node 2 en-US + -nodes2 node 2 leaf 1 en-US + -nodes2 node 2 leaf 2 en-US + -nodes2 node 2 leaf 3 en-US + +-nodes2 node 3 en-US + -nodes2 node 3 leaf 1 en-US + -nodes2 node 3 leaf 2 en-US + -nodes2 node 3 leaf 3 en-US + +================================================================================ + +nodes3.oxt: Defines 3 nodes which are placed under different existing Modules. +The nodes and there leaves are ordered. + +Context Writer: +- nodes3 node 1 + nodes3 node 1 leaf 1 en-US + nodes3 node 1 leaf 2 en-US + nodes3 node 1 leaf 3 en-US + +- nodes3 node 2 + nodes3 node 2 leaf 1 en-US + nodes3 node 2 leaf 2 en-US + nodes3 node 2 leaf 3 en-US + +- nodes3 node 3 + nodes3 node 3 leaf 1 en-US + nodes3 node 3 leaf 2 en-US + nodes3 node 3 leaf 3 en-US + +Context Calc: +- nodes3 node 1 + nodes3 node 1 leaf 1 en-US + nodes3 node 1 leaf 2 en-US + nodes3 node 1 leaf 3 en-US + +- nodes3 node 3 + nodes3 node 3 leaf 1 en-US + nodes3 node 3 leaf 2 en-US + nodes3 node 3 leaf 3 en-US + +Context Draw: +- nodes3 node 2 + nodes3 node 2 leaf 1 en-US + nodes3 node 2 leaf 2 en-US + nodes3 node 2 leaf 3 en-US + +================================================================================ + +nodes4.oxt: Same as nodes3.oxt. Use together with nodes3.txt to test the +grouping of nodes. +================================================================================ + +nodes5.oxt: Defines a node which in turn defines 3 leaves. The Node +is not assigned to a Module and the AllModule property is false (which is the +default).This may happen when a node +had been added to an already existing Module and then this Module was removed. For +example, an extension adds a node to the "Writer Module" and the +next office update removes the "Writer Module" (which is rather inconceivable). +Then the node and its leaves MUST NOT be displayed in OOo's options dialog, +because the Module is not known. However, it can be displayed in the +options dialog of the Extension Manager. See also the description for leaf2.oxt. +================================================================================ + +modules1.oxt: Defines two Modules and three Nodes. The Nodes may not +be displayed in OOo's options dialog because there is currently no application +which uses this Module. However the Nodes are displayed in the options dialog +of the Extension Manager. +There are three Nodes defined. The relation ship is this: + +-module1 + -node 1 + -leaf 1 + -leaf 2 + -leaf 3 + -node 2 + -leaf 1 + -leaf 2 + -leaf 3 + -node 3 + -leaf 1 + -leaf 2 + -leaf 3 + +-module2 + -node1 + -leaf 1 + -leaf 2 + -leaf 3 + -node3 + -leaf 1 + -leaf 2 + -leaf 3 + +The options dialog of the Extension Manager shall display only three nodes: + + -node 1 + -leaf 1 + -leaf 2 + -leaf 3 + -node 2 + -leaf 1 + -leaf 2 + -leaf 3 + -node 3 + -leaf 1 + -leaf 2 + -leaf 3 + +or + + -node 1 + -leaf 1 + -leaf 2 + -leaf 3 + -node 3 + -leaf 1 + -leaf 2 + -leaf 3 + -node 2 + -leaf 1 + -leaf 2 + -leaf 3 + +Since the order of Module|s is not defined, the dialog may display first the +Nodes from module2 and then from module1. If a node is already displayed then +it is not shown again. + +================================================================================ + +modules2.oxt: Same as modules1, except that the order of nodes and leaves +is not defined. diff --git a/desktop/test/deployment/passive/Addons.xcu b/desktop/test/deployment/passive/Addons.xcu new file mode 100644 index 000000000000..61578d7426e9 --- /dev/null +++ b/desktop/test/deployment/passive/Addons.xcu @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<o:component-data xmlns:o="http://openoffice.org/2001/registry" + o:package="org.openoffice.Office" o:name="Addons"> + <node o:name="AddonUI"> + <node o:name="OfficeMenuBar"> + <node o:name="org.openoffice.test.desktop.deployment.passive" + o:op="replace"> + <prop o:name="Title" xml:lang="en-US"> + <value>passive</value> + </prop> + <node o:name="Submenu"> + <node o:name="1" o:op="replace"> + <prop o:name="URL"> + <value>vnd.org.openoffice.test.desktop.deployment.passive_native:</value> + </prop> + <prop o:name="Title" xml:lang="en-US"> + <value>native</value> + </prop> + </node> + <node o:name="2" o:op="replace"> + <prop o:name="URL"> + <value>vnd.org.openoffice.test.desktop.deployment.passive_java:</value> + </prop> + <prop o:name="Title" xml:lang="en-US"> + <value>java</value> + </prop> + </node> + <node o:name="3" o:op="replace"> + <prop o:name="URL"> + <value>vnd.org.openoffice.test.desktop.deployment.passive_python:</value> + </prop> + <prop o:name="Title" xml:lang="en-US"> + <value>python</value> + </prop> + </node> + </node> + </node> + </node> + </node> +</o:component-data> diff --git a/desktop/test/deployment/passive/Dispatch.java b/desktop/test/deployment/passive/Dispatch.java new file mode 100755 index 000000000000..295f34d599da --- /dev/null +++ b/desktop/test/deployment/passive/Dispatch.java @@ -0,0 +1,101 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +************************************************************************/ + +package com.sun.star.comp.test.deployment.passive_java; + +import com.sun.star.awt.MessageBoxButtons; +import com.sun.star.awt.Rectangle; +import com.sun.star.awt.XMessageBox; +import com.sun.star.awt.XMessageBoxFactory; +import com.sun.star.awt.XWindowPeer; +import com.sun.star.beans.PropertyValue; +import com.sun.star.frame.DispatchDescriptor; +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XDispatch; +import com.sun.star.frame.XStatusListener; +import com.sun.star.lang.WrappedTargetRuntimeException; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.util.URL; + +public final class Dispatch extends WeakBase implements XServiceInfo, XDispatch +{ + public Dispatch(XComponentContext context) { + this.context = context; + } + + public String getImplementationName() { return implementationName; } + + public boolean supportsService(String ServiceName) { + return false; //TODO + } + + public String[] getSupportedServiceNames() { + return serviceNames; + } + + public void dispatch(URL URL, PropertyValue[] Arguments) { + try { + XMultiComponentFactory smgr = UnoRuntime.queryInterface( + XMultiComponentFactory.class, context.getServiceManager()); + XMessageBox box = UnoRuntime.queryInterface( + XMessageBoxFactory.class, + smgr.createInstanceWithContext( + "com.sun.star.awt.Toolkit", context)). + createMessageBox( + UnoRuntime.queryInterface( + XWindowPeer.class, + (UnoRuntime.queryInterface( + XDesktop.class, + smgr.createInstanceWithContext( + "com.sun.star.frame.Desktop", context)). + getCurrentFrame().getComponentWindow())), + new Rectangle(), "infobox", MessageBoxButtons.BUTTONS_OK, + "passive", "java"); + box.execute(); + UnoRuntime.queryInterface(XComponent.class, box).dispose(); + } catch (com.sun.star.uno.RuntimeException e) { + throw e; + } catch (com.sun.star.uno.Exception e) { + throw new WrappedTargetRuntimeException( + "wrapped: " + e.getMessage(), this, e); + } + } + + public void addStatusListener(XStatusListener Control, URL URL) {} + + public void removeStatusListener(XStatusListener Control, URL URL) {} + + private final XComponentContext context; + + static final String implementationName = + "com.sun.star.comp.test.deployment.passive_java_singleton"; + + static final String[] serviceNames = new String[0]; +} diff --git a/desktop/test/deployment/passive/MANIFEST.MF b/desktop/test/deployment/passive/MANIFEST.MF new file mode 100755 index 000000000000..45a04bf263dc --- /dev/null +++ b/desktop/test/deployment/passive/MANIFEST.MF @@ -0,0 +1,3 @@ +Sealed: true +RegistrationClassName: com.sun.star.comp.test.deployment.passive_java.Services +UNO-Type-Path: diff --git a/desktop/test/deployment/passive/ProtocolHandler.xcu b/desktop/test/deployment/passive/ProtocolHandler.xcu new file mode 100644 index 000000000000..bc0355be41df --- /dev/null +++ b/desktop/test/deployment/passive/ProtocolHandler.xcu @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<o:component-data xmlns:o="http://openoffice.org/2001/registry" + o:package="org.openoffice.Office" o:name="ProtocolHandler"> + <node o:name="HandlerSet"> + <node o:name="com.sun.star.test.deployment.passive_native" o:op="replace"> + <prop o:name="Protocols"> + <value>vnd.org.openoffice.test.desktop.deployment.passive_native:*</value> + </prop> + </node> + <node o:name="com.sun.star.test.deployment.passive_java" o:op="replace"> + <prop o:name="Protocols"> + <value>vnd.org.openoffice.test.desktop.deployment.passive_java:*</value> + </prop> + </node> + <node o:name="com.sun.star.test.deployment.passive_python" o:op="replace"> + <prop o:name="Protocols"> + <value>vnd.org.openoffice.test.desktop.deployment.passive_python:*</value> + </prop> + </node> + </node> +</o:component-data> diff --git a/desktop/test/deployment/passive/Provider.java b/desktop/test/deployment/passive/Provider.java new file mode 100755 index 000000000000..6f74ed9eb89e --- /dev/null +++ b/desktop/test/deployment/passive/Provider.java @@ -0,0 +1,81 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +************************************************************************/ + +package com.sun.star.comp.test.deployment.passive_java; + +import com.sun.star.frame.DispatchDescriptor; +import com.sun.star.frame.XDispatch; +import com.sun.star.frame.XDispatchProvider; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.util.URL; + +public final class Provider extends WeakBase + implements XServiceInfo, XDispatchProvider +{ + public Provider(XComponentContext context) { + this.context = context; + } + + public String getImplementationName() { return implementationName; } + + public boolean supportsService(String ServiceName) { + return ServiceName.equals(getSupportedServiceNames()[0]); //TODO + } + + public String[] getSupportedServiceNames() { + return serviceNames; + } + + public XDispatch queryDispatch( + URL URL, String TargetFrameName, int SearchFlags) + { + return UnoRuntime.queryInterface( + XDispatch.class, + context.getValueByName( + "/singletons/" + + "com.sun.star.test.deployment.passive_java_singleton")); + } + + public XDispatch[] queryDispatches(DispatchDescriptor[] Requests) { + XDispatch[] s = new XDispatch[Requests.length]; + for (int i = 0; i < s.length; ++i) { + s[i] = queryDispatch( + Requests[i].FeatureURL, Requests[i].FrameName, + Requests[i].SearchFlags); + } + return s; + } + + private final XComponentContext context; + + static final String implementationName = + "com.sun.star.comp.test.deployment.passive_java"; + + static final String[] serviceNames = new String[] { + "com.sun.star.test.deployment.passive_java" }; +} diff --git a/desktop/test/deployment/passive/Services.java b/desktop/test/deployment/passive/Services.java new file mode 100755 index 000000000000..799df3e70222 --- /dev/null +++ b/desktop/test/deployment/passive/Services.java @@ -0,0 +1,49 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +************************************************************************/ + +package com.sun.star.comp.test.deployment.passive_java; + +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lib.uno.helper.Factory; + +public final class Services { + private Services() {} + + public static XSingleComponentFactory __getComponentFactory( + String implementation) + { + if (implementation.equals(Dispatch.implementationName)) { + return Factory.createComponentFactory( + Dispatch.class, Dispatch.implementationName, + Dispatch.serviceNames); + } else if (implementation.equals(Provider.implementationName)) { + return Factory.createComponentFactory( + Provider.class, Provider.implementationName, + Provider.serviceNames); + } else { + return null; + } + } +} diff --git a/desktop/test/deployment/passive/description.xml b/desktop/test/deployment/passive/description.xml new file mode 100755 index 000000000000..468dfa065fb1 --- /dev/null +++ b/desktop/test/deployment/passive/description.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<d:description xmlns:d="http://openoffice.org/extensions/description/2006"> + <d:identifier + value="org.openoffice/framework/desktop/test/deployment/passive"/> + <d:version value="1"/> + <d:dependencies> + <d:OpenOffice.org-minimal-version d:name="OpenOffice.org 3.4" value="3.4"/> + </d:dependencies> +</d:description> diff --git a/desktop/test/deployment/passive/makefile.mk b/desktop/test/deployment/passive/makefile.mk new file mode 100755 index 000000000000..05defbe6d16e --- /dev/null +++ b/desktop/test/deployment/passive/makefile.mk @@ -0,0 +1,141 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = test_deployment_passive + +ENABLE_EXCEPTIONS = TRUE + +PACKAGE = com/sun/star/comp/test/deployment/passive_java +JAVAFILES = Dispatch.java Provider.java Services.java +JARFILES = juh.jar ridl.jar unoil.jar + +my_platform_components = passive_native +my_generic_components = passive_java passive_python + +.INCLUDE: settings.mk + + +DLLPRE = + +SLOFILES = $(SHL1OBJS) + +SHL1TARGET = passive_native.uno +SHL1OBJS = $(SLO)/passive_native.obj +SHL1RPATH = OXT +SHL1STDLIBS = $(CPPUHELPERLIB) $(CPPULIB) $(SALLIB) +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +DEF1NAME = $(SHL1TARGET) + +.INCLUDE: target.mk + +.IF "$(SOLAR_JAVA)" != "" + +ALLTAR : $(MISC)/passive.oxt + +$(MISC)/passive.oxt : manifest.xml description.xml Addons.xcu \ + ProtocolHandler.xcu $(MISC)/$(TARGET)/platform.components \ + $(MISC)/$(TARGET)/generic.components $(SHL1TARGETN) \ + $(MISC)/$(TARGET)/passive_java.jar passive_python.py + $(RM) $@ + $(RM) -r $(MISC)/$(TARGET)/passive.oxt-zip + $(MKDIR) $(MISC)/$(TARGET)/passive.oxt-zip + $(MKDIRHIER) $(MISC)/$(TARGET)/passive.oxt-zip/META-INF + $(SED) -e 's|@PLATFORM@|$(RTL_OS:l)_$(RTL_ARCH:l)|g' < manifest.xml \ + > $(MISC)/$(TARGET)/passive.oxt-zip/META-INF/manifest.xml + $(COPY) description.xml Addons.xcu ProtocolHandler.xcu \ + $(MISC)/$(TARGET)/platform.components \ + $(MISC)/$(TARGET)/generic.components $(SHL1TARGETN) \ + $(MISC)/$(TARGET)/passive_java.jar passive_python.py \ + $(MISC)/$(TARGET)/passive.oxt-zip/ + cd $(MISC)/$(TARGET)/passive.oxt-zip && zip ../../passive.oxt \ + META-INF/manifest.xml description.xml Addons.xcu ProtocolHandler.xcu \ + platform.components generic.components $(SHL1TARGETN:f) \ + passive_java.jar passive_python.py + +$(MISC)/$(TARGET)/platform.components : $(SOLARENV)/bin/packcomponents.xslt \ + $(MISC)/$(TARGET)/platform.components.input \ + $(my_platform_components:^"$(MISC)/$(TARGET)/":+".component") + $(XSLTPROC) --nonet --stringparam prefix $(PWD)/$(MISC)/$(TARGET)/ -o $@ \ + $(SOLARENV)/bin/packcomponents.xslt \ + $(MISC)/$(TARGET)/platform.components.input + +$(MISC)/$(TARGET)/platform.components.input : + $(MKDIRHIER) $(@:d) + echo '<list>' \ + '$(my_platform_components:^"<filename>":+".component</filename>")' \ + '</list>' > $@ + +$(MISC)/$(TARGET)/generic.components : $(SOLARENV)/bin/packcomponents.xslt \ + $(MISC)/$(TARGET)/generic.components.input \ + $(my_generic_components:^"$(MISC)/$(TARGET)/":+".component") + $(XSLTPROC) --nonet --stringparam prefix $(PWD)/$(MISC)/$(TARGET)/ -o $@ \ + $(SOLARENV)/bin/packcomponents.xslt \ + $(MISC)/$(TARGET)/generic.components.input + +$(MISC)/$(TARGET)/generic.components.input : + $(MKDIRHIER) $(@:d) + echo '<list>' \ + '$(my_generic_components:^"<filename>":+".component</filename>")' \ + '</list>' > $@ + +$(MISC)/$(TARGET)/passive_native.component : \ + $(SOLARENV)/bin/createcomponent.xslt passive_native.component + $(MKDIRHIER) $(@:d) + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_EXTENSION)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt passive_native.component + +$(MISC)/$(TARGET)/passive_java.component : \ + $(SOLARENV)/bin/createcomponent.xslt passive_java.component + $(MKDIRHIER) $(@:d) + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_EXTENSION)passive_java.jar' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt passive_java.component + +$(MISC)/$(TARGET)/passive_python.component : \ + $(SOLARENV)/bin/createcomponent.xslt passive_python.component + $(MKDIRHIER) $(@:d) + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_EXTENSION)passive_python.py' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt passive_python.component + +$(MISC)/$(TARGET)/passive_java.jar : MANIFEST.MF $(JAVATARGET) + $(MKDIRHIER) $(@:d) + $(RM) $@ + $(RM) -r $(MISC)/$(TARGET)/passive_java.jar-zip + $(MKDIR) $(MISC)/$(TARGET)/passive_java.jar-zip + $(MKDIRHIER) $(MISC)/$(TARGET)/passive_java.jar-zip/META-INF \ + $(MISC)/$(TARGET)/passive_java.jar-zip/$(PACKAGE) + $(COPY) MANIFEST.MF $(MISC)/$(TARGET)/passive_java.jar-zip/META-INF/ + $(COPY) $(foreach,i,$(JAVAFILES:b) $(CLASSDIR)/$(PACKAGE)/$i.class) \ + $(MISC)/$(TARGET)/passive_java.jar-zip/$(PACKAGE)/ + cd $(MISC)/$(TARGET)/passive_java.jar-zip && zip ../passive_java.jar \ + META-INF/MANIFEST.MF $(foreach,i,$(JAVAFILES:b) $(PACKAGE)/$i.class) + +.ENDIF diff --git a/desktop/test/deployment/passive/manifest.xml b/desktop/test/deployment/passive/manifest.xml new file mode 100755 index 000000000000..5b8ac8419bb9 --- /dev/null +++ b/desktop/test/deployment/passive/manifest.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<m:manifest xmlns:m="http://openoffice.org/2001/manifest"> + <m:file-entry m:media-type="application/vnd.sun.star.configuration-data" + m:full-path="Addons.xcu"/> + <m:file-entry m:media-type="application/vnd.sun.star.configuration-data" + m:full-path="ProtocolHandler.xcu"/> + <m:file-entry + m:media-type="application/vnd.sun.star.uno-components;platform=@PLATFORM@" + m:full-path="platform.components"/> + <m:file-entry + m:media-type="application/vnd.sun.star.uno-components" + m:full-path="generic.components"/> +</m:manifest> diff --git a/desktop/test/deployment/passive/passive_java.component b/desktop/test/deployment/passive/passive_java.component new file mode 100755 index 000000000000..74be57177dfe --- /dev/null +++ b/desktop/test/deployment/passive/passive_java.component @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.Java2" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.test.deployment.passive_java"> + <service name="com.sun.star.test.deployment.passive_java"/> + </implementation> + <implementation + name="com.sun.star.comp.test.deployment.passive_java_singleton"> + <singleton name="com.sun.star.test.deployment.passive_java_singleton"/> + </implementation> +</component> diff --git a/desktop/test/deployment/passive/passive_native.component b/desktop/test/deployment/passive/passive_native.component new file mode 100755 index 000000000000..c14fd7ff0062 --- /dev/null +++ b/desktop/test/deployment/passive/passive_native.component @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.test.deployment.passive_native"> + <service name="com.sun.star.test.deployment.passive_native"/> + </implementation> + <implementation + name="com.sun.star.comp.test.deployment.passive_native_singleton"> + <singleton name="com.sun.star.test.deployment.passive_native_singleton"/> + </implementation> +</component> diff --git a/desktop/test/deployment/passive/passive_native.cxx b/desktop/test/deployment/passive/passive_native.cxx new file mode 100644 index 000000000000..939e8208f57f --- /dev/null +++ b/desktop/test/deployment/passive/passive_native.cxx @@ -0,0 +1,283 @@ +/************************************************************************* +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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 "precompiled_desktop.hxx" +#include "sal/config.h" + +#include "boost/noncopyable.hpp" +#include "com/sun/star/awt/MessageBoxButtons.hpp" +#include "com/sun/star/awt/Rectangle.hpp" +#include "com/sun/star/awt/XMessageBox.hpp" +#include "com/sun/star/awt/XMessageBoxFactory.hpp" +#include "com/sun/star/awt/XWindowPeer.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/frame/DispatchDescriptor.hpp" +#include "com/sun/star/frame/XDesktop.hpp" +#include "com/sun/star/frame/XDispatch.hpp" +#include "com/sun/star/frame/XDispatchProvider.hpp" +#include "com/sun/star/frame/XFrame.hpp" +#include "com/sun/star/frame/XStatusListener.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/uno/DeploymentException.hpp" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/URL.hpp" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/diagnose.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "uno/lbnames.h" + +namespace { + +namespace css = com::sun::star; + +class Provider: + public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::frame::XDispatchProvider >, + private boost::noncopyable +{ +public: + static css::uno::Reference< css::uno::XInterface > SAL_CALL static_create( + css::uno::Reference< css::uno::XComponentContext > const & xContext) + SAL_THROW((css::uno::Exception)) + { return static_cast< cppu::OWeakObject * >(new Provider(xContext)); } + + static rtl::OUString SAL_CALL static_getImplementationName(); + + static css::uno::Sequence< rtl::OUString > SAL_CALL + static_getSupportedServiceNames(); + +private: + Provider( + css::uno::Reference< css::uno::XComponentContext > const & context): + context_(context) { OSL_ASSERT(context.is()); } + + virtual ~Provider() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return static_getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName) + throw (css::uno::RuntimeException) + { return ServiceName == getSupportedServiceNames()[0]; } //TODO + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return static_getSupportedServiceNames(); } + + virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( + css::util::URL const &, rtl::OUString const &, sal_Int32) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > + SAL_CALL queryDispatches( + css::uno::Sequence< css::frame::DispatchDescriptor > const & Requests) + throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context_; +}; + +rtl::OUString Provider::static_getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.test.deployment.passive_native")); +} + +css::uno::Sequence< rtl::OUString > Provider::static_getSupportedServiceNames() +{ + rtl::OUString name( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.test.deployment.passive_native")); + return css::uno::Sequence< rtl::OUString >(&name, 1); +} + +css::uno::Reference< css::frame::XDispatch > Provider::queryDispatch( + css::util::URL const &, rtl::OUString const &, sal_Int32) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::frame::XDispatch > dispatch; + if (!(context_->getValueByName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.test.deployment." + "passive_native_singleton"))) >>= + dispatch) || + !dispatch.is()) + { + throw css::uno::DeploymentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "component context fails to supply singleton" + " com.sun.star.test.deployment.passive_native_singleton of" + " type com.sun.star.frame.XDispatch")), + context_); + } + return dispatch; +} + +css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > +Provider::queryDispatches( + css::uno::Sequence< css::frame::DispatchDescriptor > const & Requests) + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > s( + Requests.getLength()); + for (sal_Int32 i = 0; i < s.getLength(); ++i) { + s[i] = queryDispatch( + Requests[i].FeatureURL, Requests[i].FrameName, + Requests[i].SearchFlags); + } + return s; +} + +class Dispatch: + public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::frame::XDispatch >, + private boost::noncopyable +{ +public: + static css::uno::Reference< css::uno::XInterface > SAL_CALL static_create( + css::uno::Reference< css::uno::XComponentContext > const & xContext) + SAL_THROW((css::uno::Exception)) + { return static_cast< cppu::OWeakObject * >(new Dispatch(xContext)); } + + static rtl::OUString SAL_CALL static_getImplementationName(); + + static css::uno::Sequence< rtl::OUString > SAL_CALL + static_getSupportedServiceNames() + { return css::uno::Sequence< rtl::OUString >(); } + +private: + Dispatch( + css::uno::Reference< css::uno::XComponentContext > const & context): + context_(context) { OSL_ASSERT(context.is()); } + + virtual ~Dispatch() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return static_getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const &) + throw (css::uno::RuntimeException) + { return false; } //TODO + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return static_getSupportedServiceNames(); } + + virtual void SAL_CALL dispatch( + css::util::URL const &, + css::uno::Sequence< css::beans::PropertyValue > const &) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL addStatusListener( + css::uno::Reference< css::frame::XStatusListener > const &, + css::util::URL const &) + throw (css::uno::RuntimeException) + {} + + virtual void SAL_CALL removeStatusListener( + css::uno::Reference< css::frame::XStatusListener > const &, + css::util::URL const &) + throw (css::uno::RuntimeException) + {} + + css::uno::Reference< css::uno::XComponentContext > context_; +}; + +rtl::OUString Dispatch::static_getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.test.deployment.passive_native_singleton")); +} + +void Dispatch::dispatch( + css::util::URL const &, + css::uno::Sequence< css::beans::PropertyValue > const &) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::lang::XMultiComponentFactory > smgr( + context_->getServiceManager(), css::uno::UNO_SET_THROW); + css::uno::Reference< css::awt::XMessageBox > box( + css::uno::Reference< css::awt::XMessageBoxFactory >( + smgr->createInstanceWithContext( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.awt.Toolkit")), context_), + css::uno::UNO_QUERY_THROW)->createMessageBox( + css::uno::Reference< css::awt::XWindowPeer >( + css::uno::Reference< css::frame::XFrame >( + css::uno::Reference< css::frame::XDesktop >( + smgr->createInstanceWithContext( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.Desktop")), + context_), + css::uno::UNO_QUERY_THROW)->getCurrentFrame(), + css::uno::UNO_SET_THROW)->getComponentWindow(), + css::uno::UNO_QUERY_THROW), + css::awt::Rectangle(), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("infobox")), + css::awt::MessageBoxButtons::BUTTONS_OK, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("passive")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("native"))), + css::uno::UNO_SET_THROW); + box->execute(); + css::uno::Reference< css::lang::XComponent >( + box, css::uno::UNO_QUERY_THROW)->dispose(); +} + +static cppu::ImplementationEntry const services[] = { + { &Provider::static_create, &Provider::static_getImplementationName, + &Provider::static_getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, + { &Dispatch::static_create, &Dispatch::static_getImplementationName, + &Dispatch::static_getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, + { 0, 0, 0, 0, 0, 0 } +}; + +} + +extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + char const * pImplName, void * pServiceManager, void * pRegistryKey) +{ + return cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, services); +} diff --git a/desktop/test/deployment/passive/passive_python.component b/desktop/test/deployment/passive/passive_python.component new file mode 100755 index 000000000000..ea7a1992b534 --- /dev/null +++ b/desktop/test/deployment/passive/passive_python.component @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.Python" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.test.deployment.passive_python"> + <service name="com.sun.star.test.deployment.passive_python"/> + </implementation> + <implementation + name="com.sun.star.comp.test.deployment.passive_python_singleton"> + <singleton name="com.sun.star.test.deployment.passive_python_singleton"/> + </implementation> +</component> diff --git a/desktop/test/deployment/passive/passive_python.py b/desktop/test/deployment/passive/passive_python.py new file mode 100755 index 000000000000..dda68cccdb2f --- /dev/null +++ b/desktop/test/deployment/passive/passive_python.py @@ -0,0 +1,101 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#***********************************************************************/ + +import uno +import unohelper + +from com.sun.star.awt import Rectangle +from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK +from com.sun.star.frame import XDispatch, XDispatchProvider +from com.sun.star.lang import XServiceInfo + +class Provider(unohelper.Base, XServiceInfo, XDispatchProvider): + implementationName = "com.sun.star.comp.test.deployment.passive_python" + + serviceNames = ("com.sun.star.test.deployment.passive_python",) + + def __init__(self, context): + self.context = context + + def getImplementationName(self): + return self.implementationName + + def supportsService(self, ServiceName): + return ServiceName in self.serviceNames + + def getSupportedServiceNames(self): + return self.serviceNames + + def queryDispatch(self, URL, TargetFrame, SearchFlags): + return self.context.getValueByName( \ + "/singletons/com.sun.star.test.deployment.passive_python_singleton") + + def queryDispatches(self, Requests): + tuple( \ + self.queryDispatch(i.FeatureURL, i.FrameName, i.SearchFlags) \ + for i in Requests) + +class Dispatch(unohelper.Base, XServiceInfo, XDispatch): + implementationName = \ + "com.sun.star.comp.test.deployment.passive_python_singleton" + + serviceNames = () + + def __init__(self, context): + self.context = context + + def getImplementationName(self): + return self.implementationName + + def supportsService(self, ServiceName): + return ServiceName in self.serviceNames + + def getSupportedServiceNames(self): + return self.serviceNames + + def dispatch(self, URL, Arguments): + smgr = self.context.getServiceManager() + box = smgr.createInstanceWithContext( \ + "com.sun.star.awt.Toolkit", self.context).createMessageBox( \ + smgr.createInstanceWithContext( \ + "com.sun.star.frame.Desktop", self.context). \ + getCurrentFrame().getComponentWindow(), \ + Rectangle(), "infobox", BUTTONS_OK, "passive", "python") + box.execute(); + box.dispose(); + + def addStatusListener(self, Control, URL): + pass + + def removeStatusListener(self, Control, URL): + pass + +g_ImplementationHelper = unohelper.ImplementationHelper() +g_ImplementationHelper.addImplementation( \ + Provider, Provider.implementationName, Provider.serviceNames) +g_ImplementationHelper.addImplementation( \ + Dispatch, Dispatch.implementationName, Dispatch.serviceNames) diff --git a/desktop/test/deployment/simple_license/BadDesc.oxt b/desktop/test/deployment/simple_license/BadDesc.oxt Binary files differnew file mode 100644 index 000000000000..436778d54dd4 --- /dev/null +++ b/desktop/test/deployment/simple_license/BadDesc.oxt diff --git a/desktop/test/deployment/simple_license/BadNamespace.oxt b/desktop/test/deployment/simple_license/BadNamespace.oxt Binary files differnew file mode 100644 index 000000000000..e439c9e171de --- /dev/null +++ b/desktop/test/deployment/simple_license/BadNamespace.oxt diff --git a/desktop/test/deployment/simple_license/BadRoot.oxt b/desktop/test/deployment/simple_license/BadRoot.oxt Binary files differnew file mode 100644 index 000000000000..1f6c60c992ba --- /dev/null +++ b/desktop/test/deployment/simple_license/BadRoot.oxt diff --git a/desktop/test/deployment/simple_license/Locale1.oxt b/desktop/test/deployment/simple_license/Locale1.oxt Binary files differnew file mode 100644 index 000000000000..51ecb5c75c6c --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale1.oxt diff --git a/desktop/test/deployment/simple_license/Locale2.oxt b/desktop/test/deployment/simple_license/Locale2.oxt Binary files differnew file mode 100644 index 000000000000..bb6b236a5d07 --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale2.oxt diff --git a/desktop/test/deployment/simple_license/Locale3.oxt b/desktop/test/deployment/simple_license/Locale3.oxt Binary files differnew file mode 100644 index 000000000000..56bfedc24025 --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale3.oxt diff --git a/desktop/test/deployment/simple_license/Locale4.oxt b/desktop/test/deployment/simple_license/Locale4.oxt Binary files differnew file mode 100644 index 000000000000..9a465bc7cff3 --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale4.oxt diff --git a/desktop/test/deployment/simple_license/Locale5.oxt b/desktop/test/deployment/simple_license/Locale5.oxt Binary files differnew file mode 100644 index 000000000000..ce16830c13fa --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale5.oxt diff --git a/desktop/test/deployment/simple_license/Locale6.oxt b/desktop/test/deployment/simple_license/Locale6.oxt Binary files differnew file mode 100644 index 000000000000..770d32506ee3 --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale6.oxt diff --git a/desktop/test/deployment/simple_license/LongLic.oxt b/desktop/test/deployment/simple_license/LongLic.oxt Binary files differnew file mode 100644 index 000000000000..a0a49daebacf --- /dev/null +++ b/desktop/test/deployment/simple_license/LongLic.oxt diff --git a/desktop/test/deployment/simple_license/MissingLic.oxt b/desktop/test/deployment/simple_license/MissingLic.oxt Binary files differnew file mode 100644 index 000000000000..04d58fd117a2 --- /dev/null +++ b/desktop/test/deployment/simple_license/MissingLic.oxt diff --git a/desktop/test/deployment/simple_license/MissingLicRef.oxt b/desktop/test/deployment/simple_license/MissingLicRef.oxt Binary files differnew file mode 100644 index 000000000000..01c9d19a2833 --- /dev/null +++ b/desktop/test/deployment/simple_license/MissingLicRef.oxt diff --git a/desktop/test/deployment/simple_license/NoDefLang.oxt b/desktop/test/deployment/simple_license/NoDefLang.oxt Binary files differnew file mode 100644 index 000000000000..3eadd5254ccc --- /dev/null +++ b/desktop/test/deployment/simple_license/NoDefLang.oxt diff --git a/desktop/test/deployment/simple_license/NoDesc.oxt b/desktop/test/deployment/simple_license/NoDesc.oxt Binary files differnew file mode 100644 index 000000000000..ac83dac97eba --- /dev/null +++ b/desktop/test/deployment/simple_license/NoDesc.oxt diff --git a/desktop/test/deployment/simple_license/NoLang.oxt b/desktop/test/deployment/simple_license/NoLang.oxt Binary files differnew file mode 100644 index 000000000000..a4f3dd43a079 --- /dev/null +++ b/desktop/test/deployment/simple_license/NoLang.oxt diff --git a/desktop/test/deployment/simple_license/Prefix.oxt b/desktop/test/deployment/simple_license/Prefix.oxt Binary files differnew file mode 100644 index 000000000000..3e09b8d804e9 --- /dev/null +++ b/desktop/test/deployment/simple_license/Prefix.oxt diff --git a/desktop/test/deployment/simple_license/ShortLicense.oxt b/desktop/test/deployment/simple_license/ShortLicense.oxt Binary files differnew file mode 100644 index 000000000000..efcfdc98e125 --- /dev/null +++ b/desktop/test/deployment/simple_license/ShortLicense.oxt diff --git a/desktop/test/deployment/simple_license/ShortLicenseShared.oxt b/desktop/test/deployment/simple_license/ShortLicenseShared.oxt Binary files differnew file mode 100644 index 000000000000..775559a2c7a3 --- /dev/null +++ b/desktop/test/deployment/simple_license/ShortLicenseShared.oxt diff --git a/desktop/test/deployment/simple_license/suppress_license.oxt b/desktop/test/deployment/simple_license/suppress_license.oxt Binary files differnew file mode 100644 index 000000000000..2bacd6aa378b --- /dev/null +++ b/desktop/test/deployment/simple_license/suppress_license.oxt diff --git a/desktop/test/deployment/simple_license/tests_simple_license.odt b/desktop/test/deployment/simple_license/tests_simple_license.odt Binary files differnew file mode 100644 index 000000000000..b0c86e11c69b --- /dev/null +++ b/desktop/test/deployment/simple_license/tests_simple_license.odt diff --git a/desktop/test/deployment/update/changing_display_name/change1.oxt b/desktop/test/deployment/update/changing_display_name/change1.oxt Binary files differnew file mode 100644 index 000000000000..c919129ab6d7 --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/change1.oxt diff --git a/desktop/test/deployment/update/changing_display_name/change1_mod.oxt b/desktop/test/deployment/update/changing_display_name/change1_mod.oxt Binary files differnew file mode 100644 index 000000000000..5ab99d7bf224 --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/change1_mod.oxt diff --git a/desktop/test/deployment/update/changing_display_name/readme.txt b/desktop/test/deployment/update/changing_display_name/readme.txt new file mode 100755 index 000000000000..905f0be9a962 --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/readme.txt @@ -0,0 +1,13 @@ + +The default display name, if nothing is provided by the extension, is the file name. +The display name could be changed in different versions. There are three versions +of change1.oxt available: + +v1: no display name +v2: change1 de +v3: change1 de - changed display name - + +change1_mod.oxt is the same as change1.oxt version 1 except that is has a display name. +This situation should actually never arise, because the version should always be +changed when the extension is changed - and be it only the display name. + diff --git a/desktop/test/deployment/update/changing_display_name/update1/change1.oxt b/desktop/test/deployment/update/changing_display_name/update1/change1.oxt Binary files differnew file mode 100644 index 000000000000..ef034f94459f --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/update1/change1.oxt diff --git a/desktop/test/deployment/update/changing_display_name/update1/change1.update.xml b/desktop/test/deployment/update/changing_display_name/update1/change1.update.xml new file mode 100755 index 000000000000..a4fefb6d96ba --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/update1/change1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice/framework/desktop/changing_display_name/change1" /> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/changing_display_name/update1/change1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/changing_display_name/update2/change1.oxt b/desktop/test/deployment/update/changing_display_name/update2/change1.oxt Binary files differnew file mode 100644 index 000000000000..551f5a3f48c3 --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/update2/change1.oxt diff --git a/desktop/test/deployment/update/changing_display_name/update2/change1.update.xml b/desktop/test/deployment/update/changing_display_name/update2/change1.update.xml new file mode 100755 index 000000000000..8e52ce3c2b2d --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/update2/change1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice/framework/desktop/changing_display_name/change1" /> + <version value="3.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/changing_display_name/update2/change1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/default_url/default1.oxt b/desktop/test/deployment/update/default_url/default1.oxt Binary files differnew file mode 100644 index 000000000000..3fa8c9f08f8d --- /dev/null +++ b/desktop/test/deployment/update/default_url/default1.oxt diff --git a/desktop/test/deployment/update/default_url/default2.oxt b/desktop/test/deployment/update/default_url/default2.oxt Binary files differnew file mode 100644 index 000000000000..d54ce88c51d6 --- /dev/null +++ b/desktop/test/deployment/update/default_url/default2.oxt diff --git a/desktop/test/deployment/update/default_url/readme.txt b/desktop/test/deployment/update/default_url/readme.txt new file mode 100755 index 000000000000..4ae7936bfc18 --- /dev/null +++ b/desktop/test/deployment/update/default_url/readme.txt @@ -0,0 +1,9 @@ +Tests for using the default URL for update information. This URL is currently contained in +the version.ini (ExtensionUpdateURL) and is used to obtain update information for extensions which do not provide +an URL themselves. + +The extensions default1.oxt and default2.oxt do not have a URL for update information. + +To test this one has to put this entry into the version.ini: + +ExtensionUpdateURL=http://extensions.openoffice.org/testarea/desktop/default_url/update/feed1.xml diff --git a/desktop/test/deployment/update/default_url/update/default1.oxt b/desktop/test/deployment/update/default_url/update/default1.oxt Binary files differnew file mode 100644 index 000000000000..198395c76e5d --- /dev/null +++ b/desktop/test/deployment/update/default_url/update/default1.oxt diff --git a/desktop/test/deployment/update/default_url/update/default1.update.xml b/desktop/test/deployment/update/default_url/update/default1.update.xml new file mode 100755 index 000000000000..b3d78e29e814 --- /dev/null +++ b/desktop/test/deployment/update/default_url/update/default1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.default1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/default_url/update/default1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/default_url/update/default2.oxt b/desktop/test/deployment/update/default_url/update/default2.oxt Binary files differnew file mode 100644 index 000000000000..198395c76e5d --- /dev/null +++ b/desktop/test/deployment/update/default_url/update/default2.oxt diff --git a/desktop/test/deployment/update/default_url/update/default2.update.xml b/desktop/test/deployment/update/default_url/update/default2.update.xml new file mode 100755 index 000000000000..a5894a18b05b --- /dev/null +++ b/desktop/test/deployment/update/default_url/update/default2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.default2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/default_url/update/default2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/default_url/update/feed1.xml b/desktop/test/deployment/update/default_url/update/feed1.xml new file mode 100755 index 000000000000..b504b7b4b00c --- /dev/null +++ b/desktop/test/deployment/update/default_url/update/feed1.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"> + + <title>OpenOffice.org Update Feed</title> + <link rel="alternate" type="text/html" href="http://update.services.openoffice.org/ooo/snapshot.html"/> + <updated>2006-11-06T18:30:02Z</updated> + <author> + <name>The OpenOffice.org Project</name> + <uri>http://openoffice.org</uri> + <email>updatefeed@openoffice.org</email> + </author> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566e9d</id> + <entry> + <title>default1.oxt version 2.0 available</title> + <link rel="alternate" type="text/html" + href="http://extensions.openoffice.org"/> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566e9f</id> + <category term="org.openoffice.legacy.default1.oxt" label="default1.oxt" /> + <updated>2006-11-06T18:30:02Z</updated> + <summary>Click here to go to the download page.</summary> + <content type="application/xml" src="http://extensions.openoffice.org/testarea/desktop/default_url/update/default1.update.xml" /> + </entry> + <entry> + <title>default2.oxt version 2.0 available</title> + <link rel="alternate" type="text/html" + href="http://extensions.openoffice.org"/> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566eaf</id> + <category term="org.openoffice.legacy.default2.oxt" label="default2.oxt" /> + <updated>2006-11-06T18:30:02Z</updated> + <summary>Click here to go to the download page.</summary> + <content type="application/xml" src="http://extensions.openoffice.org/testarea/desktop/default_url/update/default2.update.xml" /> + </entry> +</feed> diff --git a/desktop/test/deployment/update/defect/fail1.oxt b/desktop/test/deployment/update/defect/fail1.oxt Binary files differnew file mode 100644 index 000000000000..5b5cdba2cdbc --- /dev/null +++ b/desktop/test/deployment/update/defect/fail1.oxt diff --git a/desktop/test/deployment/update/defect/fail2.oxt b/desktop/test/deployment/update/defect/fail2.oxt Binary files differnew file mode 100644 index 000000000000..61b0306f0947 --- /dev/null +++ b/desktop/test/deployment/update/defect/fail2.oxt diff --git a/desktop/test/deployment/update/defect/fail3.oxt b/desktop/test/deployment/update/defect/fail3.oxt Binary files differnew file mode 100644 index 000000000000..9da26d48a636 --- /dev/null +++ b/desktop/test/deployment/update/defect/fail3.oxt diff --git a/desktop/test/deployment/update/defect/fail4.oxt b/desktop/test/deployment/update/defect/fail4.oxt Binary files differnew file mode 100644 index 000000000000..66b87caa14b7 --- /dev/null +++ b/desktop/test/deployment/update/defect/fail4.oxt diff --git a/desktop/test/deployment/update/defect/info1.oxt b/desktop/test/deployment/update/defect/info1.oxt Binary files differnew file mode 100644 index 000000000000..9ffd373fa11f --- /dev/null +++ b/desktop/test/deployment/update/defect/info1.oxt diff --git a/desktop/test/deployment/update/defect/info2.oxt b/desktop/test/deployment/update/defect/info2.oxt Binary files differnew file mode 100644 index 000000000000..229a52c3bc69 --- /dev/null +++ b/desktop/test/deployment/update/defect/info2.oxt diff --git a/desktop/test/deployment/update/defect/info3.oxt b/desktop/test/deployment/update/defect/info3.oxt Binary files differnew file mode 100644 index 000000000000..b702f3e00417 --- /dev/null +++ b/desktop/test/deployment/update/defect/info3.oxt diff --git a/desktop/test/deployment/update/defect/readme.txt b/desktop/test/deployment/update/defect/readme.txt new file mode 100755 index 000000000000..5e8322f5cf26 --- /dev/null +++ b/desktop/test/deployment/update/defect/readme.txt @@ -0,0 +1,15 @@ +The updates, that is the newer versions, are defect. However, only fail2.oxt fails to install. The other extensions can be installed directly and through an update.
+
+fail1.oxt: in version2 the contained t.rdb was renamed so that it is not found (t.rdb is referenced in the manifest.xml).
+
+fail2.oxt: in version 2 the contained t.rdb is corrupted. It is a renamed .txt file which contains some text.
+
+fail3.oxt: in version 2 the contained t.rdb is corrupted. It is a renamed .txt file which does not contain any text.
+
+fail4.oxt: the version 2 references by fail4.update.xml is empty.
+
+info1.oxt: The update information file has length null.
+
+info2.oxt: The update information does not contain xml.
+
+info3.oxt: The update information contain an error: the tag update information contains two opening brackets (<<update-information>)
\ No newline at end of file diff --git a/desktop/test/deployment/update/defect/update/fail1.oxt b/desktop/test/deployment/update/defect/update/fail1.oxt Binary files differnew file mode 100644 index 000000000000..dbcc7cd73eb9 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail1.oxt diff --git a/desktop/test/deployment/update/defect/update/fail1.update.xml b/desktop/test/deployment/update/defect/update/fail1.update.xml new file mode 100755 index 000000000000..40f2d1c7df9f --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.fail1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/defect/update/fail1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/defect/update/fail2.oxt b/desktop/test/deployment/update/defect/update/fail2.oxt Binary files differnew file mode 100644 index 000000000000..6df0c3cf9977 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail2.oxt diff --git a/desktop/test/deployment/update/defect/update/fail2.update.xml b/desktop/test/deployment/update/defect/update/fail2.update.xml new file mode 100755 index 000000000000..d6bdaccb30e9 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.fail2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/defect/update/fail2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/defect/update/fail3.oxt b/desktop/test/deployment/update/defect/update/fail3.oxt Binary files differnew file mode 100644 index 000000000000..2d340f41443b --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail3.oxt diff --git a/desktop/test/deployment/update/defect/update/fail3.update.xml b/desktop/test/deployment/update/defect/update/fail3.update.xml new file mode 100755 index 000000000000..e7f2606d604c --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail3.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.fail3.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/defect/update/fail3.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/defect/update/fail4.oxt b/desktop/test/deployment/update/defect/update/fail4.oxt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail4.oxt diff --git a/desktop/test/deployment/update/defect/update/fail4.update.xml b/desktop/test/deployment/update/defect/update/fail4.update.xml new file mode 100755 index 000000000000..4b293f28e034 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail4.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.fail4.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/defect/update/fail4.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/defect/update/info1.update.xml b/desktop/test/deployment/update/defect/update/info1.update.xml new file mode 100755 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/info1.update.xml diff --git a/desktop/test/deployment/update/defect/update/info2.update.xml b/desktop/test/deployment/update/defect/update/info2.update.xml new file mode 100755 index 000000000000..1446608022f0 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/info2.update.xml @@ -0,0 +1 @@ +This is a invalid update information file!!! diff --git a/desktop/test/deployment/update/defect/update/info3.oxt b/desktop/test/deployment/update/defect/update/info3.oxt Binary files differnew file mode 100644 index 000000000000..60debac57c4e --- /dev/null +++ b/desktop/test/deployment/update/defect/update/info3.oxt diff --git a/desktop/test/deployment/update/defect/update/info3.update.xml b/desktop/test/deployment/update/defect/update/info3.update.xml new file mode 100755 index 000000000000..62306e55b693 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/info3.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.info3.oxt"/> + <version value="2.0" /> + <<update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/defect/update/info3.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/dependencies/publisher_en.html b/desktop/test/deployment/update/dependencies/publisher_en.html new file mode 100755 index 000000000000..37dbc2b9d6ce --- /dev/null +++ b/desktop/test/deployment/update/dependencies/publisher_en.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My Extension Company</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/dependencies/readme.txt b/desktop/test/deployment/update/dependencies/readme.txt new file mode 100755 index 000000000000..3c71da24884d --- /dev/null +++ b/desktop/test/deployment/update/dependencies/readme.txt @@ -0,0 +1,32 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* + +update-dependencies.oxt is an extension that itself has no dependencies, but +whose update has unsatisfied dependencies (and also uses update-website). + +The update information contain also publisher and release notes information, +which should be displayed in the update dialog. diff --git a/desktop/test/deployment/update/dependencies/release-notes_en.html b/desktop/test/deployment/update/dependencies/release-notes_en.html new file mode 100755 index 000000000000..0971f78d1484 --- /dev/null +++ b/desktop/test/deployment/update/dependencies/release-notes_en.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/dependencies/update-dependencies.oxt b/desktop/test/deployment/update/dependencies/update-dependencies.oxt Binary files differnew file mode 100644 index 000000000000..513b25d20763 --- /dev/null +++ b/desktop/test/deployment/update/dependencies/update-dependencies.oxt diff --git a/desktop/test/deployment/update/dependencies/update/update-dependencies.update.xml b/desktop/test/deployment/update/dependencies/update/update-dependencies.update.xml new file mode 100755 index 000000000000..bf8a399da116 --- /dev/null +++ b/desktop/test/deployment/update/dependencies/update/update-dependencies.update.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--*********************************************************************** + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + Copyright 2000, 2010 Oracle and/or its affiliates. + + OpenOffice.org - a multi-platform office productivity suite + + 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. + + ************************************************************************ --> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:d="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice/framework/desktop/test/deployment/update/dependencies/update-dependencies.oxt"/> + <version value="2.0"/> + <dependencies> + <dependency d:name="& < > ' " > ' tab	. crlf
. em-dash—. line-separator
. paragraph-separator
. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/> + <dependency d:name="Dependency 1"/> + <dependency d:name="Dependency 2"/> + <dependency d:name="Dependency 3"/> + <dependency d:name="Dependency 4"/> + <dependency d:name="Dependency 5"/> + <dependency d:name="Dependency 6"/> + <dependency d:name="Dependency 7"/> + <dependency d:name="Dependency 8"/> + <dependency d:name="Dependency 9"/> + <dependency d:name="Dependency 10"/> + <dependency d:name="Dependency 11"/> + <dependency d:name="Dependency 12"/> + <dependency d:name="Dependency 13"/> + <dependency d:name="Dependency 14"/> + <dependency d:name="Dependency 15"/> + <dependency d:name="Dependency 16"/> + <dependency d:name="Dependency 17"/> + <dependency d:name="Dependency 18"/> + <dependency d:name="Dependency 19"/> + <dependency d:name="Dependency 20"/> + <dependency/> + <d:OpenOffice.org-minimal-version value="2.1" d:name="OpenOffice.org 2.1"/> + </dependencies> + <update-website> + <src xlink:href="http://nowhere.openoffice.org"/> + <src xlink:href="http://nowhere.openoffice.org/2"/> + </update-website> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/dependencies/publisher_en.html" lang="en">My Extension Company</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/dependencies/release-notes_en.html" lang="en" /> + </release-notes> + +</description> diff --git a/desktop/test/deployment/update/license/lic1.oxt b/desktop/test/deployment/update/license/lic1.oxt Binary files differnew file mode 100644 index 000000000000..43bfe3b77b2d --- /dev/null +++ b/desktop/test/deployment/update/license/lic1.oxt diff --git a/desktop/test/deployment/update/license/lic2.oxt b/desktop/test/deployment/update/license/lic2.oxt Binary files differnew file mode 100644 index 000000000000..266a45e9a857 --- /dev/null +++ b/desktop/test/deployment/update/license/lic2.oxt diff --git a/desktop/test/deployment/update/license/lic3.oxt b/desktop/test/deployment/update/license/lic3.oxt Binary files differnew file mode 100644 index 000000000000..3f1b98960043 --- /dev/null +++ b/desktop/test/deployment/update/license/lic3.oxt diff --git a/desktop/test/deployment/update/license/readme.txt b/desktop/test/deployment/update/license/readme.txt new file mode 100755 index 000000000000..03123d2c5812 --- /dev/null +++ b/desktop/test/deployment/update/license/readme.txt @@ -0,0 +1,9 @@ +The extensions contain a license which is displayed during installaion. If a the license is displayed during a update can be determined by the attribute +/description/registration/simple-license/@suppress-on-update + +The default value is false, which means that the attribute is not set, then the license is displayed during an update. + +lic1.oxt: attribute not set +lic2.oxt: attribute set to false +lic3.oxt: attribute set to true + diff --git a/desktop/test/deployment/update/license/update/lic1.oxt b/desktop/test/deployment/update/license/update/lic1.oxt Binary files differnew file mode 100644 index 000000000000..cc91e1ff16fe --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic1.oxt diff --git a/desktop/test/deployment/update/license/update/lic1.update.xml b/desktop/test/deployment/update/license/update/lic1.update.xml new file mode 100755 index 000000000000..6b23b97890fc --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.lic1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/license/update/lic1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/license/update/lic2.oxt b/desktop/test/deployment/update/license/update/lic2.oxt Binary files differnew file mode 100644 index 000000000000..351000792487 --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic2.oxt diff --git a/desktop/test/deployment/update/license/update/lic2.update.xml b/desktop/test/deployment/update/license/update/lic2.update.xml new file mode 100755 index 000000000000..40f3fa47bc99 --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.lic2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/license/update/lic2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/license/update/lic3.oxt b/desktop/test/deployment/update/license/update/lic3.oxt Binary files differnew file mode 100644 index 000000000000..6ac6e0fd0fd1 --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic3.oxt diff --git a/desktop/test/deployment/update/license/update/lic3.update.xml b/desktop/test/deployment/update/license/update/lic3.update.xml new file mode 100755 index 000000000000..a9c2a7995d7c --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic3.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.lic3.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/license/update/lic3.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/platform/all1.oxt b/desktop/test/deployment/update/platform/all1.oxt Binary files differnew file mode 100644 index 000000000000..ad9662a7c226 --- /dev/null +++ b/desktop/test/deployment/update/platform/all1.oxt diff --git a/desktop/test/deployment/update/platform/all2.oxt b/desktop/test/deployment/update/platform/all2.oxt Binary files differnew file mode 100644 index 000000000000..632d11b42938 --- /dev/null +++ b/desktop/test/deployment/update/platform/all2.oxt diff --git a/desktop/test/deployment/update/platform/all3.oxt b/desktop/test/deployment/update/platform/all3.oxt Binary files differnew file mode 100644 index 000000000000..ab781552a5aa --- /dev/null +++ b/desktop/test/deployment/update/platform/all3.oxt diff --git a/desktop/test/deployment/update/platform/freebsd_x86.oxt b/desktop/test/deployment/update/platform/freebsd_x86.oxt Binary files differnew file mode 100644 index 000000000000..338f5761deb1 --- /dev/null +++ b/desktop/test/deployment/update/platform/freebsd_x86.oxt diff --git a/desktop/test/deployment/update/platform/freebsd_x86_64.oxt b/desktop/test/deployment/update/platform/freebsd_x86_64.oxt Binary files differnew file mode 100644 index 000000000000..39fee6de1a77 --- /dev/null +++ b/desktop/test/deployment/update/platform/freebsd_x86_64.oxt diff --git a/desktop/test/deployment/update/platform/invalid1.oxt b/desktop/test/deployment/update/platform/invalid1.oxt Binary files differnew file mode 100644 index 000000000000..13d709f438fc --- /dev/null +++ b/desktop/test/deployment/update/platform/invalid1.oxt diff --git a/desktop/test/deployment/update/platform/invalid2.oxt b/desktop/test/deployment/update/platform/invalid2.oxt Binary files differnew file mode 100644 index 000000000000..f14257191b81 --- /dev/null +++ b/desktop/test/deployment/update/platform/invalid2.oxt diff --git a/desktop/test/deployment/update/platform/invalid3.oxt b/desktop/test/deployment/update/platform/invalid3.oxt Binary files differnew file mode 100644 index 000000000000..cadffa4f2ac1 --- /dev/null +++ b/desktop/test/deployment/update/platform/invalid3.oxt diff --git a/desktop/test/deployment/update/platform/linux_arm_eabi.oxt b/desktop/test/deployment/update/platform/linux_arm_eabi.oxt Binary files differnew file mode 100644 index 000000000000..9c504e841b98 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_arm_eabi.oxt diff --git a/desktop/test/deployment/update/platform/linux_arm_oabi.oxt b/desktop/test/deployment/update/platform/linux_arm_oabi.oxt Binary files differnew file mode 100644 index 000000000000..f2c987f645a7 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_arm_oabi.oxt diff --git a/desktop/test/deployment/update/platform/linux_ia64.oxt b/desktop/test/deployment/update/platform/linux_ia64.oxt Binary files differnew file mode 100644 index 000000000000..f579a18ab90d --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_ia64.oxt diff --git a/desktop/test/deployment/update/platform/linux_mips_eb.oxt b/desktop/test/deployment/update/platform/linux_mips_eb.oxt Binary files differnew file mode 100644 index 000000000000..bf0bd942332b --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_mips_eb.oxt diff --git a/desktop/test/deployment/update/platform/linux_mips_el.oxt b/desktop/test/deployment/update/platform/linux_mips_el.oxt Binary files differnew file mode 100644 index 000000000000..6bd56446831b --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_mips_el.oxt diff --git a/desktop/test/deployment/update/platform/linux_powerpc.oxt b/desktop/test/deployment/update/platform/linux_powerpc.oxt Binary files differnew file mode 100644 index 000000000000..e301a3fb3ad1 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_powerpc.oxt diff --git a/desktop/test/deployment/update/platform/linux_powerpc64.oxt b/desktop/test/deployment/update/platform/linux_powerpc64.oxt Binary files differnew file mode 100644 index 000000000000..e5f3ae063923 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_powerpc64.oxt diff --git a/desktop/test/deployment/update/platform/linux_s390.oxt b/desktop/test/deployment/update/platform/linux_s390.oxt Binary files differnew file mode 100644 index 000000000000..199702ebf056 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_s390.oxt diff --git a/desktop/test/deployment/update/platform/linux_s390x.oxt b/desktop/test/deployment/update/platform/linux_s390x.oxt Binary files differnew file mode 100644 index 000000000000..2ed250833fb1 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_s390x.oxt diff --git a/desktop/test/deployment/update/platform/linux_sparc.oxt b/desktop/test/deployment/update/platform/linux_sparc.oxt Binary files differnew file mode 100644 index 000000000000..53dfc71e0c4e --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_sparc.oxt diff --git a/desktop/test/deployment/update/platform/linux_x86.oxt b/desktop/test/deployment/update/platform/linux_x86.oxt Binary files differnew file mode 100644 index 000000000000..8379539cad34 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_x86.oxt diff --git a/desktop/test/deployment/update/platform/linux_x86_64.oxt b/desktop/test/deployment/update/platform/linux_x86_64.oxt Binary files differnew file mode 100644 index 000000000000..0fb18227522f --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_x86_64.oxt diff --git a/desktop/test/deployment/update/platform/macosx_powerpc.oxt b/desktop/test/deployment/update/platform/macosx_powerpc.oxt Binary files differnew file mode 100644 index 000000000000..7c146347127a --- /dev/null +++ b/desktop/test/deployment/update/platform/macosx_powerpc.oxt diff --git a/desktop/test/deployment/update/platform/macosx_x86.oxt b/desktop/test/deployment/update/platform/macosx_x86.oxt Binary files differnew file mode 100644 index 000000000000..a20aadfefffd --- /dev/null +++ b/desktop/test/deployment/update/platform/macosx_x86.oxt diff --git a/desktop/test/deployment/update/platform/mul1.oxt b/desktop/test/deployment/update/platform/mul1.oxt Binary files differnew file mode 100644 index 000000000000..b3b555969bdf --- /dev/null +++ b/desktop/test/deployment/update/platform/mul1.oxt diff --git a/desktop/test/deployment/update/platform/os2_x86.oxt b/desktop/test/deployment/update/platform/os2_x86.oxt Binary files differnew file mode 100644 index 000000000000..1c7fd40bef9f --- /dev/null +++ b/desktop/test/deployment/update/platform/os2_x86.oxt diff --git a/desktop/test/deployment/update/platform/readme.txt b/desktop/test/deployment/update/platform/readme.txt new file mode 100755 index 000000000000..2ab102a27d3c --- /dev/null +++ b/desktop/test/deployment/update/platform/readme.txt @@ -0,0 +1,49 @@ +Extension which only support one platform +======================================================== + +freebsd_x86.oxt: freebsd_x86 +freebsd_x86_86.oxt: freebsd_x86_64 +linux_arm_eabi.oxt: linux_arm_eabi +linux_arm_oabi.oxt: linux_arm_oabi +linux_ia64.oxt: linux_ia64 +linux_mips_eb.oxt: linux_mips_eb +linux_mips_el.oxt: linux_mips_el +linux_powerpc64.oxt: linux_powerpc64 +linux_powerpc.oxt: linux_powerpc +linux_s390.oxt: linux_s390 +linux_s390x.oxt: linux_s390x +linux_sparc.oxt: linux_sparc +linux_x86.oxt: linux_x86 +linux_x86_64.oxt: linux_x86_64 +macos_powerpc.oxt: macos_powerpc +macos_x86.oxt: macos_x86 +solaris_sparc.oxt: solaris_sparc +solaris_x86.oxt: solaris_x86 +windows_x86.oxt: windows_x86 +os2_x86.oxt: os/2_x86 + +Extensions which support multiple platforms +======================================================= +mul1.oxt: windows_x86, linux_x86, solaris_x86 + + +All platforms +========================================================= +all1.oxt: all, The <platform> element is missing. Default is "all". + +all2.oxt: all, <platform value="all" /> + +all3.oxt: all, no description.xml + + + +Invalid platforms +========================================================= +The following extensions cannot be installed because the platform element +is not correct. We assume that no valid platform is defined. + +invalid1.oxt: <platform /> + +invalid2.oxt: <platform value=""/> + +invalid3.oxt: <platform value="," /> diff --git a/desktop/test/deployment/update/platform/solaris_sparc.oxt b/desktop/test/deployment/update/platform/solaris_sparc.oxt Binary files differnew file mode 100644 index 000000000000..a61f81f43942 --- /dev/null +++ b/desktop/test/deployment/update/platform/solaris_sparc.oxt diff --git a/desktop/test/deployment/update/platform/solaris_x86.oxt b/desktop/test/deployment/update/platform/solaris_x86.oxt Binary files differnew file mode 100644 index 000000000000..44d43df69184 --- /dev/null +++ b/desktop/test/deployment/update/platform/solaris_x86.oxt diff --git a/desktop/test/deployment/update/platform/windows_x86.oxt b/desktop/test/deployment/update/platform/windows_x86.oxt Binary files differnew file mode 100644 index 000000000000..c66a9b1418fa --- /dev/null +++ b/desktop/test/deployment/update/platform/windows_x86.oxt diff --git a/desktop/test/deployment/update/publisher/pub1.oxt b/desktop/test/deployment/update/publisher/pub1.oxt Binary files differnew file mode 100644 index 000000000000..c44ee9f3bc56 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub1.oxt diff --git a/desktop/test/deployment/update/publisher/pub10.oxt b/desktop/test/deployment/update/publisher/pub10.oxt Binary files differnew file mode 100644 index 000000000000..1e7410ec1b2e --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub10.oxt diff --git a/desktop/test/deployment/update/publisher/pub11.oxt b/desktop/test/deployment/update/publisher/pub11.oxt Binary files differnew file mode 100644 index 000000000000..ef7fbca5e63a --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub11.oxt diff --git a/desktop/test/deployment/update/publisher/pub2.oxt b/desktop/test/deployment/update/publisher/pub2.oxt Binary files differnew file mode 100644 index 000000000000..438bcae830a3 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub2.oxt diff --git a/desktop/test/deployment/update/publisher/pub3.oxt b/desktop/test/deployment/update/publisher/pub3.oxt Binary files differnew file mode 100644 index 000000000000..62fd69f5595a --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub3.oxt diff --git a/desktop/test/deployment/update/publisher/pub4.oxt b/desktop/test/deployment/update/publisher/pub4.oxt Binary files differnew file mode 100644 index 000000000000..4f6224f780cd --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub4.oxt diff --git a/desktop/test/deployment/update/publisher/pub5.oxt b/desktop/test/deployment/update/publisher/pub5.oxt Binary files differnew file mode 100644 index 000000000000..1774e6cd35c3 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub5.oxt diff --git a/desktop/test/deployment/update/publisher/pub6.oxt b/desktop/test/deployment/update/publisher/pub6.oxt Binary files differnew file mode 100644 index 000000000000..791a37f8e710 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub6.oxt diff --git a/desktop/test/deployment/update/publisher/pub7.oxt b/desktop/test/deployment/update/publisher/pub7.oxt Binary files differnew file mode 100644 index 000000000000..96e96887d0b1 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub7.oxt diff --git a/desktop/test/deployment/update/publisher/pub8.oxt b/desktop/test/deployment/update/publisher/pub8.oxt Binary files differnew file mode 100644 index 000000000000..dc9f0ce34d95 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub8.oxt diff --git a/desktop/test/deployment/update/publisher/pub9.oxt b/desktop/test/deployment/update/publisher/pub9.oxt Binary files differnew file mode 100644 index 000000000000..5e8ba9ebc154 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub9.oxt diff --git a/desktop/test/deployment/update/publisher/publisher_de-DE-altmark.html b/desktop/test/deployment/update/publisher/publisher_de-DE-altmark.html new file mode 100755 index 000000000000..c770b914ad78 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_de-DE-altmark.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-DE-altmark</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_de-DE.html b/desktop/test/deployment/update/publisher/publisher_de-DE.html new file mode 100755 index 000000000000..b06ed7088f08 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_de-DE.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice de-DE</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_de.html b/desktop/test/deployment/update/publisher/publisher_de.html new file mode 100755 index 000000000000..4cba9f423d5b --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_de.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice de</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en-GB.html b/desktop/test/deployment/update/publisher/publisher_en-GB.html new file mode 100755 index 000000000000..c73cf6219b78 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en-GB.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-GB</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en-US-region1.html b/desktop/test/deployment/update/publisher/publisher_en-US-region1.html new file mode 100755 index 000000000000..68beac724894 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en-US-region1.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-US-region1</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en-US-region2.html b/desktop/test/deployment/update/publisher/publisher_en-US-region2.html new file mode 100755 index 000000000000..501adb659664 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en-US-region2.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-US-region2</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en-US.html b/desktop/test/deployment/update/publisher/publisher_en-US.html new file mode 100755 index 000000000000..fd2575150315 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en-US.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-US</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en-region3.html b/desktop/test/deployment/update/publisher/publisher_en-region3.html new file mode 100755 index 000000000000..b9fdc9d657b4 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en-region3.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-region3</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en.html b/desktop/test/deployment/update/publisher/publisher_en.html new file mode 100755 index 000000000000..416ab8124314 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/readme.txt b/desktop/test/deployment/update/publisher/readme.txt new file mode 100755 index 000000000000..1a659d8e875d --- /dev/null +++ b/desktop/test/deployment/update/publisher/readme.txt @@ -0,0 +1,212 @@ +--The folder contains extensions which use in the description.xml the following: + +-The <publisher> element +-The <release-notes> element + +Both element contain localized child elements. + +The following table shows what localized item is used, when the Office the locale +en-US uses. + + +Localization: + +Installed office en-US + | publisher | release notes +============================================= +pub1.oxt | en-US | en-US +--------------------------------------------- +pub2.oxt | en-US-region1 | en-US-region1 +--------------------------------------------- +pub3.oxt | en | en +--------------------------------------------- +pub4.oxt | en-GB | en-GB +--------------------------------------------- +pub5.oxt | de | de + + +================================================================================ +pub6.oxt +================================================================================ +like pub1 but without release notes. + + +================================================================================ +pub7.oxt +================================================================================ +like pub1 but without publisher name. + +================================================================================ +pub8.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop. + +pub8.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +pub8.oxt provides <publisher> and <release-notes>. These information should be transferred +in the update feed and not those entered in the repository. + +Test +---- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. This setting should be ignored + when generating the udpate feed. Instead the publisher name from the extension is used. + Enter "Publisher Title" : some arbitrary company + "Publisher URL": any arbitrary URL but not: + http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html + +-Create a new release for the extension. Upload the version 2.0 (update/pub8.oxt). + Provide release notes. These release notes should later not be seen when clicking on + the release notes link. + + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/publisher/pub8.oxt + +-Run the update in the Extension Manager + + +Result: +The Update Dialog should show the publisher name as provided in the description.xml. For example, +when lang=en-US was selected: My OpenOffice en-US + +A release notes link is displayed with an URL to the release notes as provided in +the description.xml. For example, when lang=en-US was selected: +"http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html + + +================================================================================ +pub9.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop. + +pub9.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +pub9.oxt provides <publisher>. That means the update feed should +contain the <publisher> as provided by the extension and the release notes as entered +in the repository. + +Test +---- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. This setting should be ignored + when generating the udpate feed. Instead the publisher name from the extension is used. + Enter "Publisher Title" : some arbitrary company name + "Publisher URL": any arbitrary URL but not: + http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html + +-Create a new release for the extension. Upload the version 2.0 (update/pub9.oxt). + Provide release notes. These release notes should later be displayed when clicking on + the release notes link. + + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/publisher/pub9.oxt + +-Run the update in the Extension Manager + + +Result: +The Update Dialog should show the publisher name as provided in the description.xml. For example, +when lang=en-US was selected: My OpenOffice en-US + +A release notes link is displayed with an URL to the release notes as provided in the release notes +field on the edit page for the extension in the repository. + +================================================================================ +pub10.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop. + +pub10.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +pub10.oxt provides <release-notes>. That means the update feed should +contain the <release-notes> as provided by the extension and the publisher name/URLs as entered +in the repository. + +Test +---- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. They should then be in the udpate + feed. + +-Create a new release for the extension. Upload the version 2.0 (update/pub10.oxt). + Provide release notes. These release notes should NOT be displayed when clicking on + the release notes link. Instead the release notes provided by pub10.oxt should be displayed. + + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/publisher/pub10.oxt + +-Run the update in the Extension Manager + + +Result: +The Update Dialog should show the publisher name as provided in the repository. + +A release notes link is displayed with an URL to the release notes as provided in the +pub10.oxt. For example, when the locale of the office is en-US then this page will be +displayed: +For example, +when lang=en-US was selected: My OpenOffice en-US + +================================================================================ +pub11.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop. + +pub11.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +pub10.oxt neither provides <release-notes> nor <publisher>. That means the update feed should +contain these data as provided by the user on the repository web site. + +Test +---- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. They should then be in the udpate + feed. + +-Create a new release for the extension. Upload the version 2.0 (update/pub11.oxt). + Provide release notes. These release notes should be displayed when clicking on + the release notes link. + + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/publisher/pub11.oxt + +-Run the update in the Extension Manager + + +Result: +The Update Dialog should show the publisher name as provided in the repository. + +A release notes link is displayed which leads to the release notes kept in the repository. + diff --git a/desktop/test/deployment/update/publisher/release-notes_de-DE-altmark.html b/desktop/test/deployment/update/publisher/release-notes_de-DE-altmark.html new file mode 100755 index 000000000000..81b38a9f5b44 --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_de-DE-altmark.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes de-DE-altmark</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_de-DE.html b/desktop/test/deployment/update/publisher/release-notes_de-DE.html new file mode 100755 index 000000000000..f8f0121f0215 --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_de-DE.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes de-DE</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_de.html b/desktop/test/deployment/update/publisher/release-notes_de.html new file mode 100755 index 000000000000..a9e1dc3647eb --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_de.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes de</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en-GB.html b/desktop/test/deployment/update/publisher/release-notes_en-GB.html new file mode 100755 index 000000000000..ca72ec1b9c6e --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en-GB.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en-GB</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en-US-region1.html b/desktop/test/deployment/update/publisher/release-notes_en-US-region1.html new file mode 100755 index 000000000000..0e6f99ce4c35 --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en-US-region1.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en-US-region1</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en-US-region2.html b/desktop/test/deployment/update/publisher/release-notes_en-US-region2.html new file mode 100755 index 000000000000..597bca0ebeef --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en-US-region2.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en-US-region2</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en-US.html b/desktop/test/deployment/update/publisher/release-notes_en-US.html new file mode 100755 index 000000000000..7f9d73e338f8 --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en-US.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en-US</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en-region3.html b/desktop/test/deployment/update/publisher/release-notes_en-region3.html new file mode 100755 index 000000000000..5d62c7bcb4cf --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en-region3.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en-region3</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en.html b/desktop/test/deployment/update/publisher/release-notes_en.html new file mode 100755 index 000000000000..d02e4f3330ee --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/update/pub1.oxt b/desktop/test/deployment/update/publisher/update/pub1.oxt Binary files differnew file mode 100644 index 000000000000..cd04a58d5585 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub1.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub1.update.xml b/desktop/test/deployment/update/publisher/update/pub1.update.xml new file mode 100755 index 000000000000..db25b56a8847 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub1.update.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub1"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en.html" lang="en">My OpenOffice en</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html" lang="en-US">My OpenOffice en-US</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region1.html" lang="en-US-region1">My OpenOffice en-US-region1</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region2.html" lang="en-US-region2">My OpenOffice en-US-region2</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US.html" lang="en-US" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub10.oxt b/desktop/test/deployment/update/publisher/update/pub10.oxt Binary files differnew file mode 100644 index 000000000000..501a843381a8 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub10.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub11.oxt b/desktop/test/deployment/update/publisher/update/pub11.oxt Binary files differnew file mode 100644 index 000000000000..692c0401f4a5 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub11.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub2.oxt b/desktop/test/deployment/update/publisher/update/pub2.oxt Binary files differnew file mode 100644 index 000000000000..2a0bd6c21fed --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub2.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub2.update.xml b/desktop/test/deployment/update/publisher/update/pub2.update.xml new file mode 100755 index 000000000000..d856348df87f --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub2.update.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub2"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en.html" lang="en">My OpenOffice en</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region1.html" lang="en-US-region1">My OpenOffice en-US-region1</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region2.html" lang="en-US-region2">My OpenOffice en-US-region2</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub3.oxt b/desktop/test/deployment/update/publisher/update/pub3.oxt Binary files differnew file mode 100644 index 000000000000..60675fc4d21e --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub3.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub3.update.xml b/desktop/test/deployment/update/publisher/update/pub3.update.xml new file mode 100755 index 000000000000..29a8e16b2ce4 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub3.update.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub3"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en.html" lang="en">My OpenOffice en</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub3.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub4.oxt b/desktop/test/deployment/update/publisher/update/pub4.oxt Binary files differnew file mode 100644 index 000000000000..19f7b7991bd4 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub4.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub4.update.xml b/desktop/test/deployment/update/publisher/update/pub4.update.xml new file mode 100755 index 000000000000..67b79f782412 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub4.update.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub4"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub4.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub5.oxt b/desktop/test/deployment/update/publisher/update/pub5.oxt Binary files differnew file mode 100644 index 000000000000..afc632d570f1 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub5.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub5.update.xml b/desktop/test/deployment/update/publisher/update/pub5.update.xml new file mode 100755 index 000000000000..3a58b298b549 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub5.update.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub5"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub5.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub6.oxt b/desktop/test/deployment/update/publisher/update/pub6.oxt Binary files differnew file mode 100644 index 000000000000..a68b445b8a1a --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub6.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub6.update.xml b/desktop/test/deployment/update/publisher/update/pub6.update.xml new file mode 100755 index 000000000000..ef187ce6cb5a --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub6.update.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub6"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en.html" lang="en">My OpenOffice en</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html" lang="en-US">My OpenOffice en-US</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region1.html" lang="en-US-region1">My OpenOffice en-US-region1</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region2.html" lang="en-US-region2">My OpenOffice en-US-region2</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub6.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub7.oxt b/desktop/test/deployment/update/publisher/update/pub7.oxt Binary files differnew file mode 100644 index 000000000000..1b4bee0442bb --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub7.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub7.update.xml b/desktop/test/deployment/update/publisher/update/pub7.update.xml new file mode 100755 index 000000000000..10984e08d72f --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub7.update.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub7"/> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US.html" lang="en-US" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub7.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub8.oxt b/desktop/test/deployment/update/publisher/update/pub8.oxt Binary files differnew file mode 100644 index 000000000000..5688ab9d24f5 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub8.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub9.oxt b/desktop/test/deployment/update/publisher/update/pub9.oxt Binary files differnew file mode 100644 index 000000000000..752cfbbcf0b0 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub9.oxt diff --git a/desktop/test/deployment/update/readme.txt b/desktop/test/deployment/update/readme.txt new file mode 100755 index 000000000000..b3fd9126cae3 --- /dev/null +++ b/desktop/test/deployment/update/readme.txt @@ -0,0 +1,68 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + + +The extensions in the subdirectories of the update folder are used for +testing the online update feature of extensions. The folder such as +simple, +license, +defect, etc. contain extensions which can be installed in OOo. The +corresponding update information file and the update are located on +the extensions.openoffice.org website (cvs: extensions/www/testarea). For example: + +desktop/test/deployment/update/simple/plain1.oxt + +is version 1 of this extension and it references + +http://extensions.openoffice.org/testarea/desktop/simple/update/plain1.update.xml + +which in turn references version 2 at + +http://extensions.openoffice.org/testarea/desktop/simple/update/plain1.oxt + + +To have all in one place the update information file and the update are also contained +in the desktop project. They are in the update subfolder of the different test folders. +For example + +.../update/simple/update +.../update/license/update +.../update/updatefeed/udpate + + +The different test folders for the update are also commited in project extensions/www +so that the files can be obtain via an URL. The structure and the contents is about the +same as the content +of desktop/test/deployment/udpate +For example in + +extensions/www/testarea/desktop + +are the subfolder defect, simple, updatefeed, wrong_url, etc. +they contain the extensions which are installed directly by the Extension Manager. +These folders contain also the update subfolder which contains the update information +and the actual updates. diff --git a/desktop/test/deployment/update/simple/plain1.oxt b/desktop/test/deployment/update/simple/plain1.oxt Binary files differnew file mode 100644 index 000000000000..6256f99d5e9c --- /dev/null +++ b/desktop/test/deployment/update/simple/plain1.oxt diff --git a/desktop/test/deployment/update/simple/plain2.oxt b/desktop/test/deployment/update/simple/plain2.oxt Binary files differnew file mode 100644 index 000000000000..03249c27774c --- /dev/null +++ b/desktop/test/deployment/update/simple/plain2.oxt diff --git a/desktop/test/deployment/update/simple/plain3.oxt b/desktop/test/deployment/update/simple/plain3.oxt Binary files differnew file mode 100644 index 000000000000..64838932d1ae --- /dev/null +++ b/desktop/test/deployment/update/simple/plain3.oxt diff --git a/desktop/test/deployment/update/simple/readme.txt b/desktop/test/deployment/update/simple/readme.txt new file mode 100755 index 000000000000..34ad6bedabf9 --- /dev/null +++ b/desktop/test/deployment/update/simple/readme.txt @@ -0,0 +1,31 @@ +The folder contains only simple extension. That is, they only contain +- META-INF +-t.rdb +-description.xml + +The description.xml contains a version, a display name, and one URL to the update data + +For example: + + +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="1.0" /> + + <display-name> + <name lang="de">plain1 de</name> + </display-name> + + <update-information> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/simple/plain1.update.xml" /> + </update-information> +</description> + +There is only one language as display name available, which will therefore always be displayed. + +The update information which is referenced in the update-information and the update is committed in the extensions/www project. To modify them get the project: + +cvs co extensions/wwww + +the files can be found under extensions/www/testarea/desktop diff --git a/desktop/test/deployment/update/simple/update/plain1.oxt b/desktop/test/deployment/update/simple/update/plain1.oxt Binary files differnew file mode 100644 index 000000000000..d73362e873bc --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain1.oxt diff --git a/desktop/test/deployment/update/simple/update/plain1.update.xml b/desktop/test/deployment/update/simple/update/plain1.update.xml new file mode 100755 index 000000000000..c9eb679cdba0 --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.plain1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/simple/update/plain1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/simple/update/plain2.oxt b/desktop/test/deployment/update/simple/update/plain2.oxt Binary files differnew file mode 100644 index 000000000000..3dc02aa97aa4 --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain2.oxt diff --git a/desktop/test/deployment/update/simple/update/plain2.update.xml b/desktop/test/deployment/update/simple/update/plain2.update.xml new file mode 100755 index 000000000000..5aeb8080446f --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.plain2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/simple/update/plain2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/simple/update/plain3.oxt b/desktop/test/deployment/update/simple/update/plain3.oxt Binary files differnew file mode 100644 index 000000000000..575152403bfe --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain3.oxt diff --git a/desktop/test/deployment/update/simple/update/plain3.update.xml b/desktop/test/deployment/update/simple/update/plain3.update.xml new file mode 100755 index 000000000000..6c1241dbdede --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain3.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.plain3.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/simple/update/plain3.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/updatefeed/feed1.oxt b/desktop/test/deployment/update/updatefeed/feed1.oxt Binary files differnew file mode 100644 index 000000000000..b1b11ecceabb --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/feed1.oxt diff --git a/desktop/test/deployment/update/updatefeed/feed2.oxt b/desktop/test/deployment/update/updatefeed/feed2.oxt Binary files differnew file mode 100644 index 000000000000..47dca1676c6a --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/feed2.oxt diff --git a/desktop/test/deployment/update/updatefeed/update/feed1.oxt b/desktop/test/deployment/update/updatefeed/update/feed1.oxt Binary files differnew file mode 100644 index 000000000000..82bb9665ae3d --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/update/feed1.oxt diff --git a/desktop/test/deployment/update/updatefeed/update/feed1.update.xml b/desktop/test/deployment/update/updatefeed/update/feed1.update.xml new file mode 100755 index 000000000000..31d0cfa61d3b --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/update/feed1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.feed1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/updatefeed/update/feed1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/updatefeed/update/feed1.xml b/desktop/test/deployment/update/updatefeed/update/feed1.xml new file mode 100755 index 000000000000..1c31851d8cfd --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/update/feed1.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"> + + <title>OpenOffice.org Update Feed</title> + <link rel="alternate" type="text/html" href="http://update.services.openoffice.org/ooo/snapshot.html"/> + <updated>2006-11-06T18:30:02Z</updated> + <author> + <name>The OpenOffice.org Project</name> + <uri>http://openoffice.org</uri> + <email>updatefeed@openoffice.org</email> + </author> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566e9d</id> + <entry> + <title>feed1.oxt version 2.0 available</title> + <link rel="alternate" type="text/html" + href="http://extensions.openoffice.org"/> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566e9f</id> + <category term="org.openoffice.legacy.feed1.oxt" label="feed1.oxt" /> + <updated>2006-11-06T18:30:02Z</updated> + <summary>Click here to go to the download page.</summary> + <content type="application/xml" src="http://extensions.openoffice.org/testarea/desktop/updatefeed/update/feed1.update.xml" /> + </entry> + <entry> + <title>feed2.oxt version 2.0 available</title> + <link rel="alternate" type="text/html" + href="http://extensions.openoffice.org"/> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566eaf</id> + <category term="org.openoffice.legacy.feed2.oxt" label="feed2.oxt" /> + <updated>2006-11-06T18:30:02Z</updated> + <summary>Click here to go to the download page.</summary> + <content type="application/xml" src="http://extensions.openoffice.org/testarea/desktop/updatefeed/update/feed2.update.xml" /> + </entry> +</feed> diff --git a/desktop/test/deployment/update/updatefeed/update/feed2.oxt b/desktop/test/deployment/update/updatefeed/update/feed2.oxt Binary files differnew file mode 100644 index 000000000000..9c867ae4a812 --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/update/feed2.oxt diff --git a/desktop/test/deployment/update/updatefeed/update/feed2.update.xml b/desktop/test/deployment/update/updatefeed/update/feed2.update.xml new file mode 100755 index 000000000000..8cbc5045fd5d --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/update/feed2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.feed2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/updatefeed/update/feed2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/updateinfocreation/build/MANIFEST.MF b/desktop/test/deployment/update/updateinfocreation/build/MANIFEST.MF new file mode 100755 index 000000000000..09e2f42ca0f6 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/MANIFEST.MF @@ -0,0 +1,2 @@ +RegistrationClassName: com.sun.star.comp.smoketest.TestExtension + diff --git a/desktop/test/deployment/update/updateinfocreation/build/TestExtension.idl b/desktop/test/deployment/update/updateinfocreation/build/TestExtension.idl new file mode 100644 index 000000000000..3f5fc3b53bbe --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/TestExtension.idl @@ -0,0 +1,40 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _com_sun_star_comp_smoketest_TestExtension_idl_ +#define _com_sun_star_comp_smoketest_TestExtension_idl_ + +#include <com/sun/star/lang/XServiceInfo.idl> + + +module com { module sun { module star { module comp { module smoketest { + // example service, XServiceInfo is implemented here for demonstration + // issues. XServiceInfo must be implemented by all components. + service TestExtension: ::com::sun::star::lang::XServiceInfo; +};};};};}; + +#endif diff --git a/desktop/test/deployment/update/updateinfocreation/build/TestExtension.java b/desktop/test/deployment/update/updateinfocreation/build/TestExtension.java new file mode 100755 index 000000000000..059715845c32 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/TestExtension.java @@ -0,0 +1,165 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + *************************************************************************/ +package com.sun.star.comp.smoketest; + +import com.sun.star.lib.uno.helper.Factory; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.lang.XInitialization; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.uno.Type; + +/** This class capsulates the class, that implements the minimal component, a + * factory for creating the service (<CODE>__getComponentFactory</CODE>) and a + * method, that writes the information into the given registry key + * (<CODE>__writeRegistryServiceInfo</CODE>). + */ +public class TestExtension { + /** This class implements the component. At least the interfaces XServiceInfo, + * XTypeProvider, and XInitialization should be provided by the service. + */ + public static class _TestExtension extends WeakBase + implements XServiceInfo { + /** The service name, that must be used to get an instance of this service. + */ + static private final String __serviceName = + "com.sun.star.comp.smoketest.TestExtension"; + + /** The initial component contextr, that gives access to + * the service manager, supported singletons, ... + * It's often later used + */ + private XComponentContext m_cmpCtx; + + /** The service manager, that gives access to all registered services. + * It's often later used + */ + private XMultiComponentFactory m_xMCF; + + /** The constructor of the inner class has a XMultiServiceFactory parameter. + * @param xmultiservicefactoryInitialization A special service factory + * could be introduced while initializing. + */ + public _TestExtension(XComponentContext xCompContext) { + try { + m_cmpCtx = xCompContext; + m_xMCF = m_cmpCtx.getServiceManager(); + } + catch( Exception e ) { + e.printStackTrace(); + } + } + + /** This method returns an array of all supported service names. + * @return Array of supported service names. + */ + public String[] getSupportedServiceNames() { + return getServiceNames(); + } + + /** This method is a simple helper function to used in the + * static component initialisation functions as well as in + * getSupportedServiceNames. + */ + public static String[] getServiceNames() { + String[] sSupportedServiceNames = { __serviceName }; + return sSupportedServiceNames; + } + + /** This method returns true, if the given service will be + * supported by the component. + * @param sServiceName Service name. + * @return True, if the given service name will be supported. + */ + public boolean supportsService( String sServiceName ) { + return sServiceName.equals( __serviceName ); + } + + /** Return the class name of the component. + * @return Class name of the component. + */ + public String getImplementationName() { + return _TestExtension.class.getName(); + } + } + + + /** + * Gives a factory for creating the service. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns a <code>XSingleComponentFactory</code> for creating + * the component + * @param sImplName the name of the implementation for which a + * service is desired + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleComponentFactory __getComponentFactory(String sImplName) + { + XSingleComponentFactory xFactory = null; + + if ( sImplName.equals( _TestExtension.class.getName() ) ) + xFactory = Factory.createComponentFactory(_TestExtension.class, + _TestExtension.getServiceNames()); + + return xFactory; + } + + /** + * Writes the service information into the given registry key. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns true if the operation succeeded + * @param regKey the registryKey + * @see com.sun.star.comp.loader.JavaLoader + */ + public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { + return Factory.writeRegistryServiceInfo(_TestExtension.class.getName(), + _TestExtension.getServiceNames(), + regKey); + } + /** This method is a member of the interface for initializing an object + * directly after its creation. + * @param object This array of arbitrary objects will be passed to the + * component after its creation. + * @throws Exception Every exception will not be handled, but will be + * passed to the caller. + */ + public void initialize( Object[] object ) + throws com.sun.star.uno.Exception { + /* The component describes what arguments its expected and in which + * order!At this point you can read the objects and can intialize + * your component using these objects. + */ + } + +} diff --git a/desktop/test/deployment/update/updateinfocreation/build/delzip b/desktop/test/deployment/update/updateinfocreation/build/delzip new file mode 100755 index 000000000000..636fda90bfcb --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/delzip @@ -0,0 +1 @@ +ECHO is OFF diff --git a/desktop/test/deployment/update/updateinfocreation/build/description.xml b/desktop/test/deployment/update/updateinfocreation/build/description.xml new file mode 100755 index 000000000000..257c48a79b79 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/description.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:d="http://openoffice.org/extensions/description/2006" > + <identifier value="org.openoffice.extensions.testarea.desktop.updateinfo"/> + <version value="2.0" /> + <dependencies > + <OpenOffice.org-minimal-version value="2.1" d:name="OpenOffice.org 2.1"/> + </dependencies> + <update-information> + <src xlink:href="http://update.services.openoffice.org/ProductUpdateService/check.Update?product=extension&extensionid=org.openoffice.extensions.testarea.desktop.updateinfo&refresh=true"/> + </update-information> +</description> diff --git a/desktop/test/deployment/update/updateinfocreation/build/makefile.mk b/desktop/test/deployment/update/updateinfocreation/build/makefile.mk new file mode 100755 index 000000000000..b0479c942b4f --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/makefile.mk @@ -0,0 +1,91 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = updateinfo +PACKAGE = com$/sun$/star$/comp$/smoketest +TARGET = com_sun_star_comp_smoketest + +no_common_build_zip:=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +JARFILES = ridl.jar jurt.jar unoil.jar juh.jar + + +JARTARGET = TestExtension.jar +JARCOMPRESS = TRUE +CUSTOMMANIFESTFILE = MANIFEST.MF + +ZIP1TARGET=updateinfo +ZIP1LIST=* +ZIPFLAGS=-r +ZIP1DIR=$(MISC)$/$(TARGET) +ZIP1EXT=.oxt + +EXTUPDATEINFO_NAME=org.openoffice.extensions.testarea.desktop.updateinfo.update.xml +EXTUPDATEINFO_SOURCE=description.xml +EXTUPDATEINFO_URLS = http://extensions.openoffice.org/testarea/desktop/updateinfocreation/update/updateinfo.oxt +# --- Files -------------------------------------------------------- + +COPY_OXT_MANIFEST:= $(MISC)$/$(TARGET)$/META-INF$/manifest.xml +JAVAFILES = TestExtension.java + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(JARTARGETN) : $(MISC)$/$(TARGET).javamaker.done + +$(JAVACLASSFILES) : $(MISC)$/$(TARGET).javamaker.done + +$(MISC)$/$(TARGET).javamaker.done: $(BIN)$/TestExtension.rdb + $(JAVAMAKER) -O$(CLASSDIR) -BUCR -nD -X$(SOLARBINDIR)/types.rdb $< + $(TOUCH) $@ + +$(BIN)$/TestExtension.rdb: TestExtension.idl + $(IDLC) -O$(MISC) -I$(SOLARIDLDIR) -cid -we $< + +-$(RM) $@ + $(REGMERGE) $@ /UCR $(MISC)$/TestExtension.urd + +$(MISC)$/$(ZIP1TARGET).createdir : + +$(MKDIRHIER) $(MISC)$/$(TARGET)$/META-INF >& $(NULLDEV) && $(TOUCH) $@ + +$(MISC)$/$(TARGET)_resort : manifest.xml $(JARTARGETN) $(MISC)$/$(ZIP1TARGET).createdir $(BIN)$/TestExtension.rdb description.xml + $(GNUCOPY) -u manifest.xml $(MISC)$/$(TARGET)$/META-INF$/manifest.xml + $(GNUCOPY) -u $(JARTARGETN) $(MISC)$/$(TARGET)$/$(JARTARGET) + $(GNUCOPY) -u $(BIN)$/TestExtension.rdb $(MISC)$/$(TARGET)$/TestExtension.rdb + $(GNUCOPY) -u description.xml $(MISC)$/$(TARGET)$/description.xml + $(TOUCH) $@ + +.IF "$(ZIP1TARGETN)"!="" +$(ZIP1TARGETN) : $(MISC)$/$(TARGET)_resort $(MISC)$/$(ZIP1TARGET).createdir + +.ENDIF # "$(ZIP1TARGETN)"!="" + diff --git a/desktop/test/deployment/update/updateinfocreation/build/manifest.xml b/desktop/test/deployment/update/updateinfocreation/build/manifest.xml new file mode 100755 index 000000000000..fcedabf96b4b --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/manifest.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest"> + <manifest:file-entry manifest:full-path="TestExtension.jar" manifest:media-type="application/vnd.sun.star.uno-component;type=Java"/> + <manifest:file-entry manifest:full-path="TestExtension.rdb" manifest:media-type="application/vnd.sun.star.uno-typelibrary;type=RDB"/> +</manifest:manifest> diff --git a/desktop/test/deployment/update/updateinfocreation/readme.txt b/desktop/test/deployment/update/updateinfocreation/readme.txt new file mode 100755 index 000000000000..c4fc059053e9 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/readme.txt @@ -0,0 +1,38 @@ +The extension build in this test uses an update information which is obtained +through a http get request. That is the URL does not reference an update +information file. Instead it invokes code on a webserver which returns the +update information. The URL used in this example is: + +http://update.services.openoffice.org/ProductUpdateService/check.Update?product=extension&extensionid=org.openoffice.extensions.testarea.desktop.updateinfo&refresh=true + +The updateinfo.oxt in this directory has the version 1.0 and in the sub-directory "update is the version 2 of this extension. Version 1.0 is also available here +/extensions/www/testarea/desktop/updateinfocreation/updateinfo.oxt +and version 2.0 here +/extensions/www/testarea/desktop/updateinfocreation/update/updateinfo.oxt + +Therefore they can be accessed through + +http://extensions.openoffice.org/testarea/desktop/updateinfocreation/updateinfo.oxt +and +http://extensions.openoffice.org/testarea/desktop/updateinfocreation/update/updateinfo.oxt + +The latter location (version 2.0) will also be referenced by the update information +which are returned by the webserver. + +The build sub-directory contains the code of the extension (version 2.0) and can +be build by calling dmake in this directory. The makefile uses the special macros: + +EXTUPDATEINFO_NAME=org.openoffice.extensions.testarea.desktop.updateinfo.update.xml +EXTUPDATEINFO_SOURCE=description.xml +EXTUPDATEINFO_URLS = http://extensions.openoffice.org/testarea/desktop/updateinfocreation/update/updateinfo.oxt + +This causes the generation of the update information file. This file could be +directly references by the URL in the <update-information> of the description.xml. +See also the Wiki entry at: +http://wiki.services.openoffice.org/wiki/Creating_update_information_for_extensions +This generated update information file can then be used by the webserver, when it +sends back the requested update information. The update information file will be +generated in the misc diretory of the output directory. + +The update information file needs to be copied into common.pro/pus.mxyz directory. +The project mwsfinish will process the files in the pus directory. diff --git a/desktop/test/deployment/update/updateinfocreation/update/updateinfo.oxt b/desktop/test/deployment/update/updateinfocreation/update/updateinfo.oxt Binary files differnew file mode 100644 index 000000000000..52ddd3158e31 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/update/updateinfo.oxt diff --git a/desktop/test/deployment/update/updateinfocreation/updateinfo.oxt b/desktop/test/deployment/update/updateinfocreation/updateinfo.oxt Binary files differnew file mode 100644 index 000000000000..43ac7003bc59 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/updateinfo.oxt diff --git a/desktop/test/deployment/update/website_update/readme.txt b/desktop/test/deployment/update/website_update/readme.txt new file mode 100755 index 000000000000..4ae5ddd9182f --- /dev/null +++ b/desktop/test/deployment/update/website_update/readme.txt @@ -0,0 +1,133 @@ +The folder contains extensions which need to be updated through a web site. +The "Updates dialog" of the Extension Manager will mark the updates for these +extensions as "browser based update". The Extension Manager will open a browser +for each of the extensions and navigate to the respective website. + +================================================================================ +web1.oxt - web5.oxt: +================================================================================ +They contain <update-information>. That is they reference directly the respective +webX.update.xml (for example, web1.update.xml) files which are available at +http://extensions.openoffice.org/testarea/desktop/website_update/update/... +For example: +http://extensions.openoffice.org/testarea/desktop/website_update/update/web2.update.xml + +The update information contain multiple URLs to "localized" web sites. Each URL is +assigned to a particular local. For example: + +<src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de"/> + +The Extension Manager will choose the URLs where the lang attribute matches most +closely the locale of the office. + +The following table shows what localized web site is used, when the office uses the locale +en-US. The web page will display the locale used. See update/web1_de.html, etc. + + +Localization: + +Installed office en-US + | publisher | release notes +============================================= +web1.oxt | en-US | en-US +--------------------------------------------- +web2.oxt | en-US-region1 | en-US-region1 +--------------------------------------------- +web3.oxt | en | en +--------------------------------------------- +web4.oxt | en-GB | en-GB +--------------------------------------------- +web5.oxt | de | de + + +================================================================================ +web6.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop. + +web6.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +Test +---- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. In our case this should be + http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html + +-Create a new release for the extension. Upload the description.xml of version 2.0 +(update/web6/description.xml). Provide a download URL for the web site (field + "Download from page / Open follow up page URL", which should be + http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html + Provide release notes. + + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/website_update/web6.oxt + +-Run the update in the Extension Manager + + +Result: +The Update Dialog should show the publisher name as provided in "Provider URL" field +of the extension edit page (not release). + +A release notes link is displayed with an URL to the release notes as provided in +the "Provider Title" field of the extension release edit page. + +When running the update then the web browser should navigate to +http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html + + +================================================================================ +web7.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop + +web7.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +The description.xml which will be uploaded contains URLs for release notes and publisher +names/ URLs. That is, these information are not generated from the information of the +repository web site. + +Test +----------- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. In our case these should be different + to those provided in the description.xml. These should NOT go into the update feed. + Choose for example as "Provider Title": FOO and as "Provider URL" some valid URL but NOT + http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html + +-Create a new release for the extension. Upload the description.xml of version 2.0 +(update/web7/description.xml). Provide a download URL for the web site (field + "Download from page / Open follow up page URL", which should be + http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html + Provide release notes. + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/website_update/web7.oxt + +-Run the update in the Extension Manager + +Result: +The Update Dialog should show the publisher name as provided in the description.xml. +That is: My OpenOffice en-US and NOT "FOO". + +A release notes link is displayed with an URL to the release notes as provided in +the description.xml. That is: +http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_xxx.html + +When running the update then the web browser should navigate to +http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html diff --git a/desktop/test/deployment/update/website_update/update/web1.oxt b/desktop/test/deployment/update/website_update/update/web1.oxt Binary files differnew file mode 100644 index 000000000000..157d5d952c60 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1.oxt diff --git a/desktop/test/deployment/update/website_update/update/web1.update.xml b/desktop/test/deployment/update/website_update/update/web1.update.xml new file mode 100755 index 000000000000..ad2379dd43ca --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1.update.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web1"/> + + <update-website> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html" lang="en-US" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-region3.html" lang="en-region3" /> + </update-website> +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web1_de-DE-altmark.html b/desktop/test/deployment/update/website_update/update/web1_de-DE-altmark.html new file mode 100755 index 000000000000..ffed5a52e892 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_de-DE-altmark.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>de-DE-altmark</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_de-DE.html b/desktop/test/deployment/update/website_update/update/web1_de-DE.html new file mode 100755 index 000000000000..33fb7f2ec8bc --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_de-DE.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>de-DE</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_de.html b/desktop/test/deployment/update/website_update/update/web1_de.html new file mode 100755 index 000000000000..31a53b91dbe4 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_de.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>de</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_en-GB.html b/desktop/test/deployment/update/website_update/update/web1_en-GB.html new file mode 100755 index 000000000000..c46328a82145 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en-GB.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>en-GB</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_en-US-region1.html b/desktop/test/deployment/update/website_update/update/web1_en-US-region1.html new file mode 100755 index 000000000000..80b41823b70f --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en-US-region1.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+<H1>Update Extensions</H1>
+<H1>en-US-region1</H1>
+<p><a href="web1.oxt">web1.oxt</a></p>
+<p><a href="web2.oxt">web2.oxt</a></p>
+<p><a href="web3.oxt">web3.oxt</a></p>
+<p><a href="web4.oxt">web4.oxt</a></p>
+<p><a href="web5.oxt">web5.oxt</a></p>
+<p><a href="web6.oxt">web6.oxt</a></p>
+<p><a href="web7.oxt">web7.oxt</a></p>
+
+
+</BODY>
+</HTML>
+
diff --git a/desktop/test/deployment/update/website_update/update/web1_en-US-region2.html b/desktop/test/deployment/update/website_update/update/web1_en-US-region2.html new file mode 100755 index 000000000000..1a501f520d85 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en-US-region2.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>en-US-region2</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_en-US.html b/desktop/test/deployment/update/website_update/update/web1_en-US.html new file mode 100755 index 000000000000..f861b09c0162 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en-US.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+<H1>Update Extensions</H1>
+<H1>en-US</H1>
+<p><a href="web1.oxt">web1.oxt</a></p>
+<p><a href="web2.oxt">web2.oxt</a></p>
+<p><a href="web3.oxt">web3.oxt</a></p>
+<p><a href="web4.oxt">web4.oxt</a></p>
+<p><a href="web5.oxt">web5.oxt</a></p>
+<p><a href="web6.oxt">web6.oxt</a></p>
+<p><a href="web7.oxt">web7.oxt</a></p>
+
+
+
+</BODY>
+</HTML>
+
diff --git a/desktop/test/deployment/update/website_update/update/web1_en-region3.html b/desktop/test/deployment/update/website_update/update/web1_en-region3.html new file mode 100755 index 000000000000..f55bcbe38135 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en-region3.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>en-region3</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_en.html b/desktop/test/deployment/update/website_update/update/web1_en.html new file mode 100755 index 000000000000..a0b422ebf20e --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>en</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web2.oxt b/desktop/test/deployment/update/website_update/update/web2.oxt Binary files differnew file mode 100644 index 000000000000..3a13e8114314 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web2.oxt diff --git a/desktop/test/deployment/update/website_update/update/web2.update.xml b/desktop/test/deployment/update/website_update/update/web2.update.xml new file mode 100755 index 000000000000..afdcdf078edf --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web2.update.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web2"/> + + <update-website> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-region3.html" lang="en-region3" /> + </update-website> +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web3.oxt b/desktop/test/deployment/update/website_update/update/web3.oxt Binary files differnew file mode 100644 index 000000000000..b3214a4e693f --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web3.oxt diff --git a/desktop/test/deployment/update/website_update/update/web3.update.xml b/desktop/test/deployment/update/website_update/update/web3.update.xml new file mode 100755 index 000000000000..ce6263656120 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web3.update.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web3"/> + + <update-website> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-region3.html" lang="en-region3" /> + </update-website> +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web4.oxt b/desktop/test/deployment/update/website_update/update/web4.oxt Binary files differnew file mode 100644 index 000000000000..93766fd44faf --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web4.oxt diff --git a/desktop/test/deployment/update/website_update/update/web4.update.xml b/desktop/test/deployment/update/website_update/update/web4.update.xml new file mode 100755 index 000000000000..d07f1dec149e --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web4.update.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web4"/> + + <update-website> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-region3.html" lang="en-region3" /> + </update-website> +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web5.oxt b/desktop/test/deployment/update/website_update/update/web5.oxt Binary files differnew file mode 100644 index 000000000000..1ae8f01b19cb --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web5.oxt diff --git a/desktop/test/deployment/update/website_update/update/web5.update.xml b/desktop/test/deployment/update/website_update/update/web5.update.xml new file mode 100755 index 000000000000..a392466c5785 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web5.update.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web5"/> + + <update-website> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE-altmark.html" lang="de-DE-altmark" /> + </update-website> +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web6.oxt b/desktop/test/deployment/update/website_update/update/web6.oxt Binary files differnew file mode 100644 index 000000000000..8bc16fb2c73a --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web6.oxt diff --git a/desktop/test/deployment/update/website_update/update/web6/description.xml b/desktop/test/deployment/update/website_update/update/web6/description.xml new file mode 100755 index 000000000000..243c1d8ff962 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web6/description.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web6"/> + <display-name> + <name lang="en">web-based update test 1</name> + </display-name> + +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web6/readme.txt b/desktop/test/deployment/update/website_update/update/web6/readme.txt new file mode 100755 index 000000000000..7a1ba06efaa3 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web6/readme.txt @@ -0,0 +1,5 @@ +This folder contains the description.xml from update/web6.oxt
+When creating the release 2.0 on the repository then this description.xml can be uploaded.
+
+
+This folder is not needed on extensions.openoffice.org/testarea/desktop/....
diff --git a/desktop/test/deployment/update/website_update/update/web7.oxt b/desktop/test/deployment/update/website_update/update/web7.oxt Binary files differnew file mode 100644 index 000000000000..4d6220a48af2 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web7.oxt diff --git a/desktop/test/deployment/update/website_update/update/web7/description.xml b/desktop/test/deployment/update/website_update/update/web7/description.xml new file mode 100755 index 000000000000..5b03e12ad436 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web7/description.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web7"/> + <display-name> + <name lang="en">web-based update test 1</name> + </display-name> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en.html" lang="en">My OpenOffice en</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html" lang="en-US">My OpenOffice en-US</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region1.html" lang="en-US-region1">My OpenOffice en-US-region1</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region2.html" lang="en-US-region2">My OpenOffice en-US-region2</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US.html" lang="en-US" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web7/readme.txt b/desktop/test/deployment/update/website_update/update/web7/readme.txt new file mode 100755 index 000000000000..8a6721b8e85c --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web7/readme.txt @@ -0,0 +1,5 @@ +This folder contains the description.xml from update/web7.oxt
+When creating the release 2.0 on the repository then this description.xml can be uploaded.
+
+
+This folder is not needed on extensions.openoffice.org/testarea/desktop/....
diff --git a/desktop/test/deployment/update/website_update/web1.oxt b/desktop/test/deployment/update/website_update/web1.oxt Binary files differnew file mode 100644 index 000000000000..7c17586e0454 --- /dev/null +++ b/desktop/test/deployment/update/website_update/web1.oxt diff --git a/desktop/test/deployment/update/website_update/web2.oxt b/desktop/test/deployment/update/website_update/web2.oxt Binary files differnew file mode 100644 index 000000000000..705e70a7533f --- /dev/null +++ b/desktop/test/deployment/update/website_update/web2.oxt diff --git a/desktop/test/deployment/update/website_update/web3.oxt b/desktop/test/deployment/update/website_update/web3.oxt Binary files differnew file mode 100644 index 000000000000..4e63a75f0cbf --- /dev/null +++ b/desktop/test/deployment/update/website_update/web3.oxt diff --git a/desktop/test/deployment/update/website_update/web4.oxt b/desktop/test/deployment/update/website_update/web4.oxt Binary files differnew file mode 100644 index 000000000000..e66513e68384 --- /dev/null +++ b/desktop/test/deployment/update/website_update/web4.oxt diff --git a/desktop/test/deployment/update/website_update/web5.oxt b/desktop/test/deployment/update/website_update/web5.oxt Binary files differnew file mode 100644 index 000000000000..65b02db9347d --- /dev/null +++ b/desktop/test/deployment/update/website_update/web5.oxt diff --git a/desktop/test/deployment/update/website_update/web6.oxt b/desktop/test/deployment/update/website_update/web6.oxt Binary files differnew file mode 100644 index 000000000000..98416edfa583 --- /dev/null +++ b/desktop/test/deployment/update/website_update/web6.oxt diff --git a/desktop/test/deployment/update/website_update/web7.oxt b/desktop/test/deployment/update/website_update/web7.oxt Binary files differnew file mode 100644 index 000000000000..31ba45f032d5 --- /dev/null +++ b/desktop/test/deployment/update/website_update/web7.oxt diff --git a/desktop/test/deployment/update/wrong_url/readme.txt b/desktop/test/deployment/update/wrong_url/readme.txt new file mode 100755 index 000000000000..cc2459763ca9 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/readme.txt @@ -0,0 +1,18 @@ +The extensions use either multiple urls to the update information file, or the update information file contains multiple urls. Some of those URLs point to locations which do not exist. + +url1.oxt: The corresponding url1.update.xml contains two download urls. The first Url points to a location that is not available. The second points to the new version. + +url2.oxt: Contains to URLs to update information files. The first URL in url2.oxt is wrong and the second is +correct. + +url3.oxt: contains to URLs to update information files which point to locations which do not exist. + +wrongdownload1.oxt: The corresponding wrongdownload1.update.xml contains two download URLs which point to locations which are not available. + +wrongdownload2.oxt: same as wrongdownload1.oxt + +wrongdownload3.oxt: same as wrongdownload1.oxt + + +Use the wrongdownload extensions to check the automatic scolling of the text area that contains the results. + diff --git a/desktop/test/deployment/update/wrong_url/update/url1.oxt b/desktop/test/deployment/update/wrong_url/update/url1.oxt Binary files differnew file mode 100644 index 000000000000..479b546c84dd --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/url1.oxt diff --git a/desktop/test/deployment/update/wrong_url/update/url1.update.xml b/desktop/test/deployment/update/wrong_url/update/url1.update.xml new file mode 100755 index 000000000000..5ff3bce7bb2f --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/url1.update.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.url1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/notavailable/url1.oxt" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/update/url1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/wrong_url/update/url2.oxt b/desktop/test/deployment/update/wrong_url/update/url2.oxt Binary files differnew file mode 100644 index 000000000000..ec2c5c6528cd --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/url2.oxt diff --git a/desktop/test/deployment/update/wrong_url/update/url2.update.xml b/desktop/test/deployment/update/wrong_url/update/url2.update.xml new file mode 100755 index 000000000000..4bf79eb39425 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/url2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.url2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/update/url2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/wrong_url/update/wrongdownload1.update.xml b/desktop/test/deployment/update/wrong_url/update/wrongdownload1.update.xml new file mode 100755 index 000000000000..0fd5bee55346 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/wrongdownload1.update.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.wrongdownload1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/notavailable/wrongdownload1.oxt" /> + <src xlink:href="http://extensions.openoffice.org/notavailable/" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/wrong_url/update/wrongdownload2.update.xml b/desktop/test/deployment/update/wrong_url/update/wrongdownload2.update.xml new file mode 100755 index 000000000000..124331215215 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/wrongdownload2.update.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.wrongdownload2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/notavailable/wrongdownload2.oxt" /> + <src xlink:href="http://extensions.openoffice.org/notavailable/" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/wrong_url/update/wrongdownload3.update.xml b/desktop/test/deployment/update/wrong_url/update/wrongdownload3.update.xml new file mode 100755 index 000000000000..051d33ec4ba4 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/wrongdownload3.update.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.wrongdownload3.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/notavailable/wrongdownload3.oxt" /> + <src xlink:href="http://extensions.openoffice.org/notavailable/" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/wrong_url/url1.oxt b/desktop/test/deployment/update/wrong_url/url1.oxt Binary files differnew file mode 100644 index 000000000000..41d8522fbbce --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/url1.oxt diff --git a/desktop/test/deployment/update/wrong_url/url2.oxt b/desktop/test/deployment/update/wrong_url/url2.oxt Binary files differnew file mode 100644 index 000000000000..d68e45e5e55f --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/url2.oxt diff --git a/desktop/test/deployment/update/wrong_url/url3.oxt b/desktop/test/deployment/update/wrong_url/url3.oxt Binary files differnew file mode 100644 index 000000000000..80f93b74d11f --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/url3.oxt diff --git a/desktop/test/deployment/update/wrong_url/wrongdownload1.oxt b/desktop/test/deployment/update/wrong_url/wrongdownload1.oxt Binary files differnew file mode 100644 index 000000000000..535ae331a9af --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/wrongdownload1.oxt diff --git a/desktop/test/deployment/update/wrong_url/wrongdownload2.oxt b/desktop/test/deployment/update/wrong_url/wrongdownload2.oxt Binary files differnew file mode 100644 index 000000000000..aafe2c24672b --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/wrongdownload2.oxt diff --git a/desktop/test/deployment/update/wrong_url/wrongdownload3.oxt b/desktop/test/deployment/update/wrong_url/wrongdownload3.oxt Binary files differnew file mode 100644 index 000000000000..fbdac925a257 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/wrongdownload3.oxt diff --git a/desktop/test/deployment/version/readme.txt b/desktop/test/deployment/version/readme.txt new file mode 100755 index 000000000000..c2ba28afd916 --- /dev/null +++ b/desktop/test/deployment/version/readme.txt @@ -0,0 +1,85 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +There are three extensions in various versions: + +1 version_XXX/plain.oxt has no dependencies and no license. +2a version_XXX/dependency.oxt has an unsatisfied dependency and no license. +2b version_nodependencies_XXX/dependency.oxt is identical to 2a but without the + dependency. +3 version_XXX/license.oxt has no dependencies and a license. + +The different versions are: + +A version_none contains no version element (treated as version "0"). +B version_badelement contains a bad <version val="1"/> (not allowed by the + specification, but treated by the current implementation as version "0"). +C version_badvalue contains a bad <version value="1.a"/> (not allowed by the + specification, but treated by the current implementation as version "1"). +D version_0.0 contains <version value="0.0"/> (same as version "0"). +E version_1.2.3 contains <version value="1.2.3"/>. +F version_1.2.4.7 contains <version value="1.2.4.7"/>. +G version_1.02.4.7.0 contains <version value="1.02.4.7.0"/> (same as version + "1.2.4.7"). +H version_1.2.15.3 contains <version value="1.2.15.3"/>. + +The total order among the various versions is thus + + A = B = D < C < E < F = G < H. + +Things to watch for: + +- If version y of extension e is to be installed and version x < y of + extension e is already installed, then + unopkg add e + will replace x with y. + +- If version y of extension e is to be installed and version x >= y of + extension e is already installed, then + unopkg add e + will fail with an error message. + +- If version y of extension e is to be installed and any version x of + extension e is already installed, then + unopkg add -f e + will replace x with y. + +- If version y of extension e is to be installed and any version x of + extension e is already installed, then + unopkg gui "Add..." + and + soffice "Tools - Package Manager... - Add..." + will query with a dialog whether to replace x with y. The dialog will have + "OK" (replace) preselected if x < y, and "Cancel" otherwise. + +- If replacing an installed version x of an extension e with a version y fails + because y has unsatisfied dependencies, or because y has a license to wich the + user does not agree, version x is left installed afterwards. + +- Checking for already installed versions of an extension is only done within a + single layer (unopkg versus unopkg --shared; "My Packages" versus + "OpenOffice Packages" in unopkg gui/soffice), not across layers. diff --git a/desktop/test/deployment/version/version_0.0/dependency.oxt b/desktop/test/deployment/version/version_0.0/dependency.oxt Binary files differnew file mode 100644 index 000000000000..30c8432251a5 --- /dev/null +++ b/desktop/test/deployment/version/version_0.0/dependency.oxt diff --git a/desktop/test/deployment/version/version_0.0/license.oxt b/desktop/test/deployment/version/version_0.0/license.oxt Binary files differnew file mode 100644 index 000000000000..b994ff71b732 --- /dev/null +++ b/desktop/test/deployment/version/version_0.0/license.oxt diff --git a/desktop/test/deployment/version/version_0.0/plain.oxt b/desktop/test/deployment/version/version_0.0/plain.oxt Binary files differnew file mode 100644 index 000000000000..f156014eb8c3 --- /dev/null +++ b/desktop/test/deployment/version/version_0.0/plain.oxt diff --git a/desktop/test/deployment/version/version_1.02.4.7.0/dependency.oxt b/desktop/test/deployment/version/version_1.02.4.7.0/dependency.oxt Binary files differnew file mode 100644 index 000000000000..4d75f7076234 --- /dev/null +++ b/desktop/test/deployment/version/version_1.02.4.7.0/dependency.oxt diff --git a/desktop/test/deployment/version/version_1.02.4.7.0/license.oxt b/desktop/test/deployment/version/version_1.02.4.7.0/license.oxt Binary files differnew file mode 100644 index 000000000000..40938b7543db --- /dev/null +++ b/desktop/test/deployment/version/version_1.02.4.7.0/license.oxt diff --git a/desktop/test/deployment/version/version_1.02.4.7.0/plain.oxt b/desktop/test/deployment/version/version_1.02.4.7.0/plain.oxt Binary files differnew file mode 100644 index 000000000000..521a2b6c77a8 --- /dev/null +++ b/desktop/test/deployment/version/version_1.02.4.7.0/plain.oxt diff --git a/desktop/test/deployment/version/version_1.2.15.3/dependency.oxt b/desktop/test/deployment/version/version_1.2.15.3/dependency.oxt Binary files differnew file mode 100644 index 000000000000..6f2a301f3bb3 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.15.3/dependency.oxt diff --git a/desktop/test/deployment/version/version_1.2.15.3/license.oxt b/desktop/test/deployment/version/version_1.2.15.3/license.oxt Binary files differnew file mode 100644 index 000000000000..2e2a87575047 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.15.3/license.oxt diff --git a/desktop/test/deployment/version/version_1.2.15.3/plain.oxt b/desktop/test/deployment/version/version_1.2.15.3/plain.oxt Binary files differnew file mode 100644 index 000000000000..000f3a144fbd --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.15.3/plain.oxt diff --git a/desktop/test/deployment/version/version_1.2.3/dependency.oxt b/desktop/test/deployment/version/version_1.2.3/dependency.oxt Binary files differnew file mode 100644 index 000000000000..c2966345872d --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.3/dependency.oxt diff --git a/desktop/test/deployment/version/version_1.2.3/license.oxt b/desktop/test/deployment/version/version_1.2.3/license.oxt Binary files differnew file mode 100644 index 000000000000..9cd80e9911b4 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.3/license.oxt diff --git a/desktop/test/deployment/version/version_1.2.3/plain.oxt b/desktop/test/deployment/version/version_1.2.3/plain.oxt Binary files differnew file mode 100644 index 000000000000..e34264591c58 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.3/plain.oxt diff --git a/desktop/test/deployment/version/version_1.2.4.7/dependency.oxt b/desktop/test/deployment/version/version_1.2.4.7/dependency.oxt Binary files differnew file mode 100644 index 000000000000..53089e76b07e --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.4.7/dependency.oxt diff --git a/desktop/test/deployment/version/version_1.2.4.7/license.oxt b/desktop/test/deployment/version/version_1.2.4.7/license.oxt Binary files differnew file mode 100644 index 000000000000..e283508d3492 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.4.7/license.oxt diff --git a/desktop/test/deployment/version/version_1.2.4.7/plain.oxt b/desktop/test/deployment/version/version_1.2.4.7/plain.oxt Binary files differnew file mode 100644 index 000000000000..d63c79a734b6 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.4.7/plain.oxt diff --git a/desktop/test/deployment/version/version_badelement/dependency.oxt b/desktop/test/deployment/version/version_badelement/dependency.oxt Binary files differnew file mode 100644 index 000000000000..3cb8faa2e7b6 --- /dev/null +++ b/desktop/test/deployment/version/version_badelement/dependency.oxt diff --git a/desktop/test/deployment/version/version_badelement/license.oxt b/desktop/test/deployment/version/version_badelement/license.oxt Binary files differnew file mode 100644 index 000000000000..7b2b7730eced --- /dev/null +++ b/desktop/test/deployment/version/version_badelement/license.oxt diff --git a/desktop/test/deployment/version/version_badelement/plain.oxt b/desktop/test/deployment/version/version_badelement/plain.oxt Binary files differnew file mode 100644 index 000000000000..62267c212fdc --- /dev/null +++ b/desktop/test/deployment/version/version_badelement/plain.oxt diff --git a/desktop/test/deployment/version/version_badvalue/dependency.oxt b/desktop/test/deployment/version/version_badvalue/dependency.oxt Binary files differnew file mode 100644 index 000000000000..7d8103365452 --- /dev/null +++ b/desktop/test/deployment/version/version_badvalue/dependency.oxt diff --git a/desktop/test/deployment/version/version_badvalue/license.oxt b/desktop/test/deployment/version/version_badvalue/license.oxt Binary files differnew file mode 100644 index 000000000000..b97723ebb0bc --- /dev/null +++ b/desktop/test/deployment/version/version_badvalue/license.oxt diff --git a/desktop/test/deployment/version/version_badvalue/plain.oxt b/desktop/test/deployment/version/version_badvalue/plain.oxt Binary files differnew file mode 100644 index 000000000000..f9964ed8f070 --- /dev/null +++ b/desktop/test/deployment/version/version_badvalue/plain.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_0.0/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_0.0/dependency.oxt Binary files differnew file mode 100644 index 000000000000..f156014eb8c3 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_0.0/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_1.02.4.7.0/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_1.02.4.7.0/dependency.oxt Binary files differnew file mode 100644 index 000000000000..521a2b6c77a8 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_1.02.4.7.0/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_1.2.15.3/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_1.2.15.3/dependency.oxt Binary files differnew file mode 100644 index 000000000000..000f3a144fbd --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_1.2.15.3/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_1.2.3/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_1.2.3/dependency.oxt Binary files differnew file mode 100644 index 000000000000..e34264591c58 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_1.2.3/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_1.2.4.7/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_1.2.4.7/dependency.oxt Binary files differnew file mode 100644 index 000000000000..d63c79a734b6 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_1.2.4.7/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_badelement/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_badelement/dependency.oxt Binary files differnew file mode 100644 index 000000000000..62267c212fdc --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_badelement/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_badvalue/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_badvalue/dependency.oxt Binary files differnew file mode 100644 index 000000000000..f9964ed8f070 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_badvalue/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_none/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_none/dependency.oxt Binary files differnew file mode 100644 index 000000000000..fc227b099ec8 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_none/dependency.oxt diff --git a/desktop/test/deployment/version/version_none/dependency.oxt b/desktop/test/deployment/version/version_none/dependency.oxt Binary files differnew file mode 100644 index 000000000000..36a1854bf59b --- /dev/null +++ b/desktop/test/deployment/version/version_none/dependency.oxt diff --git a/desktop/test/deployment/version/version_none/license.oxt b/desktop/test/deployment/version/version_none/license.oxt Binary files differnew file mode 100644 index 000000000000..1564c089b0a7 --- /dev/null +++ b/desktop/test/deployment/version/version_none/license.oxt diff --git a/desktop/test/deployment/version/version_none/plain.oxt b/desktop/test/deployment/version/version_none/plain.oxt Binary files differnew file mode 100644 index 000000000000..fc227b099ec8 --- /dev/null +++ b/desktop/test/deployment/version/version_none/plain.oxt diff --git a/desktop/unx/source/args.c b/desktop/unx/source/args.c new file mode 100644 index 000000000000..d69fe62e2466 --- /dev/null +++ b/desktop/unx/source/args.c @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Novell, Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Major Contributor(s): + * Michael Meeks <michael.meeks@novell.com> + * Portions created by the Ted are Copyright (C) 2010 Ted. All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#include <stdlib.h> +#include <string.h> +#include <osl/process.h> + +#include "args.h" + +/* do we start -env: */ +static int +is_env_arg (rtl_uString *str) +{ + return !rtl_ustr_ascii_compare_WithLength (str->buffer, 5, "-env:"); +} + +static struct { + const char *name; + unsigned int bTwoArgs : 1; + unsigned int bInhibitSplash : 1; + unsigned int bInhibitPagein : 1; + unsigned int bInhibitJavaLdx : 1; + const char *pPageinType; +} pArgDescr[] = { + /* have a trailing argument */ + { "pt", 1, 0, 0, 0, NULL }, + { "display", 1, 0, 0, 0, NULL }, + + /* no splash */ + { "nologo", 0, 1, 0, 0, NULL }, + { "headless", 0, 1, 0, 0, NULL }, + { "invisible", 0, 1, 0, 0, NULL }, + { "minimized", 0, 1, 0, 0, NULL }, + + /* pagein bits */ + { "writer", 0, 0, 0, 0, "pagein-writer" }, + { "calc", 0, 0, 0, 0, "pagein-calc" }, + { "draw", 0, 0, 0, 0, "pagein-draw" }, + { "impress", 0, 0, 0, 0, "pagein-impress" }, + + /* nothing much */ + { "version", 0, 1, 1, 1, NULL }, + { "help", 0, 1, 1, 1, NULL }, + { "h", 0, 1, 1, 1, NULL }, + { "?", 0, 1, 1, 1, NULL }, +}; + +Args *args_parse (void) +{ + Args *args; + sal_uInt32 nArgs, i, j; + + nArgs = osl_getCommandArgCount(); + i = sizeof (Args) + sizeof (rtl_uString *) * nArgs; + args = malloc (i); + memset (args, 0, i); + args->nArgsTotal = nArgs; + + j = 0; + + /* sort the -env: args to the front */ + for ( i = 0; i < nArgs; ++i ) + { + rtl_uString *pTmp = NULL; + osl_getCommandArg( i, &pTmp ); + if (is_env_arg (pTmp)) + args->ppArgs[j++] = pTmp; + else + rtl_uString_release (pTmp); + } + args->nArgsEnv = j; + + /* Then the other args */ + for ( i = 0; i < nArgs; ++i ) + { + rtl_uString *pTmp = NULL; + + osl_getCommandArg( i, &pTmp ); + if (!is_env_arg (pTmp)) + args->ppArgs[j++] = pTmp; + else + rtl_uString_release (pTmp); + } + + for ( i = args->nArgsEnv; i < args->nArgsTotal; i++ ) + { + sal_uInt32 j; + const sal_Unicode *arg = args->ppArgs[i]->buffer; + sal_Int32 length = args->ppArgs[i]->length; + + /* grok only parameters */ + if (arg[0] != '-') + continue; + + while (length > 2 && arg[0] == '-') { + arg++; + length--; + } + + for ( j = 0; j < SAL_N_ELEMENTS (pArgDescr); ++j ) { + if (!rtl_ustr_indexOfAscii_WithLength + (arg, length, pArgDescr[j].name, strlen (pArgDescr[j].name))) { + + args->bInhibitSplash |= pArgDescr[j].bInhibitSplash; + args->bInhibitPagein |= pArgDescr[j].bInhibitPagein; + args->bInhibitJavaLdx |= pArgDescr[j].bInhibitJavaLdx; + if (pArgDescr[j].pPageinType) + args->pPageinType = pArgDescr[j].pPageinType; + } + } + } + + return args; +} + +void +args_free (Args *args) +{ + /* FIXME: free ppArgs */ + rtl_uString_release( args->pAppPath ); + free (args); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/args.h b/desktop/unx/source/args.h new file mode 100644 index 000000000000..4a0cb55ffcde --- /dev/null +++ b/desktop/unx/source/args.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Novell, Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Major Contributor(s): + * Michael Meeks <michael.meeks@novell.com> + * Portions created by the Ted are Copyright (C) 2010 Ted. All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#include <sal/types.h> +#include <rtl/ustring.h> + +typedef struct { + rtl_uString *pAppPath; + const char *pPageinType; // @pagein-writer for - writer etc. else NULL + sal_Bool bInhibitSplash; // should we show a splash screen + sal_Bool bInhibitPagein; // should we run pagein ? + sal_Bool bInhibitJavaLdx; // should we run javaldx ? + + sal_uInt32 nArgsEnv; // number of -env: style args + sal_uInt32 nArgsTotal; // number of -env: as well as -writer style args + rtl_uString *ppArgs[1]; // sorted argument array +} Args; + +Args *args_parse (void); +void args_free (Args *args); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/file_image.h b/desktop/unx/source/file_image.h new file mode 100755 index 000000000000..4d081713a736 --- /dev/null +++ b/desktop/unx/source/file_image.h @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_FILE_IMAGE_H +#define INCLUDED_FILE_IMAGE_H + +#ifndef INCLUDED_STDDEF_H +#include <stddef.h> +#define INCLUDED_STDDEF_H +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** file_image. + */ +struct file_image_st +{ + void * m_base; + size_t m_size; +}; + +typedef struct file_image_st file_image; + +#define FILE_IMAGE_INITIALIZER { 0, 0 } + + +/** file_image_open. + */ +int file_image_open ( + file_image * image, + const char * filename); + + +/** file_image_pagein. + */ +int file_image_pagein ( + file_image * image); + + +/** file_image_close. + */ +int file_image_close ( + file_image * image); + + +/** Epilog. + */ +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDED_ODEP_IMAGE_H */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/file_image_unx.c b/desktop/unx/source/file_image_unx.c new file mode 100755 index 000000000000..fa1af9248d60 --- /dev/null +++ b/desktop/unx/source/file_image_unx.c @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "file_image.h" + +#include <unistd.h> + +#include <errno.h> +#include <fcntl.h> + +#if defined(LINUX) +# ifndef __USE_BSD +# define __USE_BSD /* madvise, MADV_WILLNEED */ +# endif +#endif /* Linux */ + +#include <sys/mman.h> +#include <sys/stat.h> + +#include <string.h> + +/* + * file_image_open + */ +int file_image_open (file_image * image, const char * filename) +{ + int result = 0; + int fd; + struct stat st; + void * p; + + if (image == 0) + return (EINVAL); + + image->m_base = MAP_FAILED, image->m_size = 0; + + if ((fd = open (filename, O_RDONLY)) == -1) + return (errno); + + if (fstat (fd, &st) == -1) + { + result = errno; + goto cleanup_and_leave; + } + + p = mmap (0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (p == MAP_FAILED) + { + result = errno; + goto cleanup_and_leave; + } + + image->m_base = p, image->m_size = st.st_size; + +cleanup_and_leave: + close (fd); + return (result); +} + +/* + * file_image_pagein. + */ +int file_image_pagein (file_image * image) +{ + file_image w; + long s; + size_t k; + volatile char c = 0; + + if (image == 0) + return (EINVAL); + + if ((w.m_base = image->m_base) == 0) + return (EINVAL); + if ((w.m_size = image->m_size) == 0) + return (0); + + if (madvise (w.m_base, w.m_size, MADV_WILLNEED) == -1) + { +#ifndef MACOSX + return (errno); +#else + /* madvise MADV_WILLNEED need not succeed here */ + /* but that is fine */ +#endif + } + + +#ifndef MACOSX + if ((s = sysconf (_SC_PAGESIZE)) == -1) + s = 0x1000; +#else + s = getpagesize(); +#endif + + k = (size_t)(s); + while (w.m_size > k) + { + c ^= ((char*)(w.m_base))[0]; + w.m_base = (char*)(w.m_base) + k; + w.m_size -= k; + } + if (w.m_size > 0) + { + c ^= ((char*)(w.m_base))[0]; + w.m_base = (char*)(w.m_base) + w.m_size; + w.m_size -= w.m_size; + } + + return (0); +} + +/* + * file_image_close + */ +int file_image_close (file_image * image) +{ + if (image == 0) + return (EINVAL); + + if (munmap (image->m_base, image->m_size) == -1) + return (errno); + + image->m_base = 0, image->m_size = 0; + return (0); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/makefile.mk b/desktop/unx/source/makefile.mk new file mode 100755 index 000000000000..7864dd8ad58b --- /dev/null +++ b/desktop/unx/source/makefile.mk @@ -0,0 +1,78 @@ +# +# Version: MPL 1.1 / GPLv3+ / LGPLv3+ +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (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.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Initial Developer of the Original Code is +# Novell, Inc. +# Portions created by the Initial Developer are Copyright (C) 2010 the +# Initial Developer. All Rights Reserved. +# +# Contributor(s): Jan Holesovsky <kendy@novell.com> +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 3 or later (the "GPLv3+"), or +# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +# instead of those above. +# +PRJ=..$/.. +PRJNAME=desktop +TARGET=oosplash + +NO_DEFAULT_STL=TRUE + +.INCLUDE : settings.mk + +.IF "$(OS)"=="MACOSX" +dummy: + @echo "Not building oosplash.bin for Mac." + +.ELSE + +.IF "$(ENABLE_QUICKSTART_LIBPNG)"=="TRUE" +CFLAGS+=-DENABLE_QUICKSTART_LIBPNG +CFLAGS+=$(LIBPNG_CFLAGS) +.ENDIF +.IF "$(USE_XINERAMA)"=="YES" +CFLAGS+=-DUSE_XINERAMA +.ENDIF + +STDLIB= + +OBJFILES= \ + $(OBJ)$/splashx.obj \ + $(OBJ)$/start.obj \ + $(OBJ)$/args.obj \ + $(OBJ)$/pagein.obj \ + $(OBJ)$/file_image_unx.obj + +APP1TARGET = $(TARGET) +APP1RPATH = BRAND +APP1OBJS = $(OBJFILES) $(PAGEIN_OBJS) +APP1LIBSALCPPRT= +APP1CODETYPE = C +APP1STDLIBS = $(PTHREAD_LIBS) $(X11LINK_DYNAMIC) $(SALLIB) +.IF "$(ENABLE_QUICKSTART_LIBPNG)"=="TRUE" +APP1STDLIBS += $(LIBPNG_LIBS) +.ENDIF +.IF "$(USE_XINERAMA)"=="YES" +APP1STDLIBS += -lXinerama +.ENDIF +.IF "$(OS)"=="SOLARIS" +APP1STDLIBS+= -lsocket +.ENDIF + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/unx/source/officeloader/makefile.mk b/desktop/unx/source/officeloader/makefile.mk new file mode 100755 index 000000000000..050da981e88d --- /dev/null +++ b/desktop/unx/source/officeloader/makefile.mk @@ -0,0 +1,47 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=officeloader +LIBTARGET=NO + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +OBJFILES = \ + $(OBJ)$/officeloader.obj + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/unx/source/officeloader/officeloader.cxx b/desktop/unx/source/officeloader/officeloader.cxx new file mode 100644 index 000000000000..3927d8e14714 --- /dev/null +++ b/desktop/unx/source/officeloader/officeloader.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <sal/main.h> +#include <osl/process.h> +#include <rtl/ustring.hxx> + +#include "../../../source/inc/exithelper.hxx" + +using namespace desktop; +using ::rtl::OUString; + +SAL_IMPLEMENT_MAIN() +{ + oslProcess process; + oslProcessError error; + + OUString sExecutableFile; + rtl_uString **pCommandArgs; + sal_uInt32 nCommandArgs; + + osl_getExecutableFile( &sExecutableFile.pData ); + + sExecutableFile += OUString( RTL_CONSTASCII_USTRINGPARAM(".bin") ); + + nCommandArgs = osl_getCommandArgCount(); + pCommandArgs = new rtl_uString *[nCommandArgs]; + + for ( sal_uInt32 i = 0; i < nCommandArgs; i++ ) + { + pCommandArgs[i] = NULL; + osl_getCommandArg( i, &pCommandArgs[i] ); + } + + bool bRestart = false; + bool bFirstRun = true; + oslProcessExitCode exitcode = 255; + + do { + error = osl_executeProcess( + sExecutableFile.pData, + bFirstRun ? pCommandArgs : NULL, + bFirstRun ? nCommandArgs : 0, + 0, + NULL, + NULL, + NULL, + 0, + &process + ); + + if ( osl_Process_E_None == error ) + { + oslProcessInfo info; + + info.Size = sizeof(info); + + error = osl_joinProcess( process ); + if ( osl_Process_E_None != error ) + break; + + error = osl_getProcessInfo( process, osl_Process_EXITCODE, &info ); + if ( osl_Process_E_None != error ) + break; + + if ( info.Fields & osl_Process_EXITCODE ) + { + exitcode = info.Code; + bRestart = (ExitHelper::E_CRASH_WITH_RESTART == exitcode || ExitHelper::E_NORMAL_RESTART == exitcode); + } + else + break; + + osl_freeProcessHandle( process ); + + } + + bFirstRun = false; + + } while ( bRestart ); + + return exitcode; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/pagein.c b/desktop/unx/source/pagein.c new file mode 100755 index 000000000000..90392b790881 --- /dev/null +++ b/desktop/unx/source/pagein.c @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "file_image.h" + +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +/* do_pagein */ +static int do_pagein (const char * filename, size_t * size) +{ + int result; + file_image image = FILE_IMAGE_INITIALIZER; + + if ((result = file_image_open (&image, filename)) != 0) + return (result); + + if ((result = file_image_pagein (&image)) != 0) + { + fprintf (stderr, "file_image_pagein %s: %s\n", filename, strerror(result)); + goto cleanup_and_leave; + } + + if (size) + { + *size = image.m_size; + } + +cleanup_and_leave: + file_image_close (&image); + return (result); +} + +extern int pagein_execute (int argc, char **argv); + +/* main */ +int pagein_execute (int argc, char **argv) +{ + int i, v = 0; + size_t nfiles = 0, nbytes = 0; + + if (argc < 2) + { + fprintf ( + stderr, + "%s: Usage: pagein [-v[v]] [-L<path>] [@]<filename> ...\n", + argv[0]); + return (1); + } + + for (i = 1; i < argc; i++) + { + FILE * fp = 0; + size_t k = 0; + + if (argv[i][0] == '-') + { + /* option */ + int j = 1; + switch (argv[i][j]) + { + case 'v': + /* verbosity level */ + for (v += 1, j += 1; argv[i][j]; j++) + v += (argv[i][j] == 'v'); + break; + case 'L': + /* search path */ + if (chdir (&(argv[i][2])) == -1) + fprintf (stderr, "chdir %s: %s\n", &(argv[i][2]), strerror(errno)); + break; + default: + /* ignored */ + break; + } + + /* next argv */ + continue; + } + + if ((argv[i][0] == '@') && ((fp = fopen (argv[i], "r")) == 0)) + { + char fullpath[4096]; + memset(fullpath, 0, sizeof(fullpath)); + char *path; + strncpy (fullpath, argv[i] + 1, 3000); + if (!(path = strrchr (fullpath, '/'))) + path = fullpath; + else + path++; + + if ((fp = fopen (&(argv[i][1]), "r")) == 0) + { + fprintf (stderr, "fopen %s: %s\n", &(argv[i][1]), strerror(errno)); + continue; + } + while (fgets (path, 1024, fp) != 0) + { + path[strlen(path) - 1] = '\0', k = 0; + + /* paths relative to the location of the pagein file */ + if (do_pagein (fullpath, &k) == 0) + { + /* accumulate total size */ + nbytes += k; + } + + if (v >= 2) + fprintf (stderr, "pagein(\"%s\") = %d bytes\n", path, (int) k); + nfiles += 1; + } + fclose (fp); + } + else + { + if (fp != 0) + fclose (fp); + + if (do_pagein (argv[i], &k) == 0) + { + /* accumulate total size */ + nbytes += k; + } + + if (v >= 2) + fprintf (stderr, "pagein(\"%s\") = %d bytes\n", argv[i], (int) k); + nfiles += 1; + } + } + + if (v >= 1) + fprintf (stderr, "Total: %d files (%d bytes)\n", (int) nfiles, (int) nbytes); + return (0); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/splashx.c b/desktop/unx/source/splashx.c new file mode 100755 index 000000000000..76ef3eb1f138 --- /dev/null +++ b/desktop/unx/source/splashx.c @@ -0,0 +1,673 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Novell, Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifdef ENABLE_QUICKSTART_LIBPNG + +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/Xutil.h> + +#ifdef USE_XINERAMA +#include <X11/extensions/Xinerama.h> +#endif + +#define USE_LIBPNG + +#include "osl/endian.h" +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef USE_LIBPNG +# include <png.h> +#endif + +#include "splashx.h" + +typedef struct { + unsigned char b, g, r; +} color_t; + +#define WINDOW_WIDTH 440 +#define WINDOW_HEIGHT 299 + +#define PROGRESS_XOFFSET 12 +#define PROGRESS_YOFFSET 18 +#define PROGRESS_BARSPACE 2 + +static Display *display = NULL; +static int screen; +static int depth; +static Visual *visual = NULL; + +static int width = WINDOW_WIDTH; +static int height = WINDOW_HEIGHT; + +static Colormap color_map; +static Window win; +static GC gc; + +// Progress bar values +// taken from desktop/source/splash/splash.cxx +static int tlx = 212; +static int tly = 216; +static int barwidth = 263; +static int barheight = 8; +static int barspace = PROGRESS_BARSPACE; +static color_t barcol = { 18, 202, 157 }; +static color_t framecol = { 0xD3, 0xD3, 0xD3 }; + +static XColor barcolor; +static XColor framecolor; + +static unsigned char **bitmap_rows = NULL; + +#define BMP_HEADER_LEN 14 +#define WIN_INFO_LEN 40 + +#define UINT8( x ) ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + +#define UINT16( x ) ( ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[1] ) ) << 8 ) ) + +#define UINT32( x ) ( ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[1] ) ) << 8 ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[2] ) ) << 16 ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[3] ) ) << 24 ) ) + +#define MAX( x, y ) ( ( (x) > (y) )? (x): (y) ) + +#define LOAD_FAILURE( msg ) \ + { \ + fprintf( stderr, "%s: " msg, filename ); \ + close( fd ); \ + return 0; \ + } + +#ifdef USE_LIBPNG + +/* libpng-1.2.41 */ +#ifndef PNG_TRANSFORM_GRAY_TO_RGB +# define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 +#endif + +png_structp png_ptr = NULL; +png_infop info_ptr = NULL; + +int splash_load_bmp( const char *filename ) +{ + FILE *file; + + if ( !(file = fopen( filename, "r" ) ) ) + return 0; + + png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); + info_ptr = png_create_info_struct(png_ptr); + png_init_io( png_ptr, file ); + + if( setjmp( png_jmpbuf( png_ptr ) ) ) + { + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + fclose( file ); + return 0; + } + + png_read_png( png_ptr, info_ptr, + PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_ALPHA | + PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_BGR, NULL); + + bitmap_rows = png_get_rows( png_ptr, info_ptr ); + width = png_get_image_width( png_ptr, info_ptr ); + height = png_get_image_height( png_ptr, info_ptr ); + + fclose( file ); + return 1; +} +#else + +/* Load the specified Windows 24bit BMP to 'bitmap' + * Return: 1 - success, 0 - failure */ +int splash_load_bmp( const char *filename ) +{ + int fd = open( filename, O_RDONLY ); + if ( fd < 0 ) + return 0; + + char file_header[ BMP_HEADER_LEN ]; + + if ( read( fd, file_header, BMP_HEADER_LEN ) != BMP_HEADER_LEN || file_header[0] != 'B' || file_header[1] != 'M' ) + LOAD_FAILURE( "Not a bitmap.\n" ); + + char info_header[ WIN_INFO_LEN ]; + if ( read( fd, info_header, 4 ) != 4 ) + LOAD_FAILURE( "Unable to read the header.\n" ); + + int header_size = UINT32( info_header ); + if ( header_size != WIN_INFO_LEN ) + LOAD_FAILURE( "Not a Windows bitmap.\n" ); + + if ( read( fd, info_header + 4, WIN_INFO_LEN - 4 ) != WIN_INFO_LEN - 4 ) + LOAD_FAILURE( "The header ended too early.\n" ); + + width = UINT32( info_header + 4 ); + height = UINT32( info_header + 8 ); + + int bits = UINT16( info_header + 14 ); + int compression = UINT16( info_header + 16 ); + + if ( bits != 24 ) + LOAD_FAILURE( "Just 24 bpp bitmaps are supported.\n" ); + + if ( compression != 0 ) + LOAD_FAILURE( "Just uncompressed bitmaps are supported.\n" ); + + size_t bitmap_size = width * height * 3; + unsigned char *bitmap = malloc( bitmap_size ); + if ( bitmap == NULL ) + LOAD_FAILURE( "Cannot allocate memory for the data.\n" ); + + if ( read( fd, bitmap, bitmap_size ) != bitmap_size ) + LOAD_FAILURE( "Cannot read the bitmap data.\n" ); + + bitmap_rows = malloc (sizeof (unsigned char*) * height); + int i; + for (i = 0; i < height; i++) + bitmap_rows[i] = bitmap + (width * height * 3) - width * 3 * (i + 1); + + close( fd ); + return 1; +} +#endif + +static void setup_color( int val[3], color_t *col ) +{ + if ( val[0] < 0 || val[1] < 0 || val[2] < 0 ) + return; + +#define CONVERT_COLOR( from,to ) if ( from < 0 ) to = 0; else if ( from > 255 ) to = 255; else to = from; + CONVERT_COLOR( val[0], col->r ); + CONVERT_COLOR( val[1], col->g ); + CONVERT_COLOR( val[2], col->b ); +#undef CONVERT_COLOR +} + +// setup +void splash_setup( int barc[3], int framec[3], int posx, int posy, int w, int h ) +{ + if ( width <= 500 ) + { + barwidth = width - ( 2 * PROGRESS_XOFFSET ); + barheight = 6; + tlx = PROGRESS_XOFFSET; + tly = height - PROGRESS_YOFFSET; + + barcol.r = 0; + barcol.g = 0; + barcol.b = 128; + } + + if ( posx >= 0 ) + tlx = posx; + if ( posy >= 0 ) + tly = posy; + if ( w >= 0 ) + barwidth = w; + if ( h >= 0 ) + barheight = h; + + setup_color( barc, &barcol ); + setup_color( framec, &framecol ); +} + +// Universal shift: bits >= 0 - left, otherwise right +#define SHIFT( x, bits ) ( ( (bits) >= 0 )? ( (x) << (bits) ): ( (x) >> -(bits) ) ) + +// Position of the highest bit (more or less integer log2) +inline int HIGHEST_BIT( unsigned long x ) +{ + int i = 0; + for ( ; x; ++i ) + x >>= 1; + + return i; +} + +// Number of bits set to 1 +inline int BITS( unsigned long x ) +{ + int i = 0; + for ( ; x; x >>= 1 ) + if ( x & 1UL ) + ++i; + + return i; +} + +// Set 'bitmap' as the background of our 'win' window +static void create_pixmap() +{ + if ( !bitmap_rows ) + return; + + Pixmap pixmap = XCreatePixmap( display, win, width, height, depth ); + + unsigned long value_mask = 0; + XGCValues values; + GC pixmap_gc = XCreateGC( display, pixmap, value_mask, &values ); + + if ( visual->class == TrueColor ) + { + unsigned long red_mask = visual->red_mask; + unsigned long green_mask = visual->green_mask; + unsigned long blue_mask = visual->blue_mask; + + unsigned long red_delta_mask = ( 1UL << ( 8 - BITS( red_mask ) ) ) - 1; + unsigned long green_delta_mask = ( 1UL << ( 8 - BITS( green_mask ) ) ) - 1; + unsigned long blue_delta_mask = ( 1UL << ( 8 - BITS( blue_mask ) ) ) - 1; + + int red_shift = HIGHEST_BIT( red_mask ) - 8; + int green_shift = HIGHEST_BIT( green_mask ) - 8; + int blue_shift = HIGHEST_BIT( blue_mask ) - 8; + + XImage *image = XCreateImage( display, visual, depth, ZPixmap, + 0, NULL, width, height, 32, 0 ); + + int bytes_per_line = image->bytes_per_line; + int bpp = image->bits_per_pixel; + int byte_order = image->byte_order; +#if defined( _LITTLE_ENDIAN ) + int machine_byte_order = LSBFirst; +#elif defined( _BIG_ENDIAN ) + int machine_byte_order = MSBFirst; +#else + { + fprintf( stderr, "Unsupported machine endianity.\n" ); + XFreeGC( display, pixmap_gc ); + XFreePixmap( display, pixmap ); + XDestroyImage( image ); + return; + } +#endif + + char *data = malloc( height * bytes_per_line ); + image->data = data; + + // The following dithers & converts the color_t color to one + // acceptable for the visual +#define COPY_IN_OUT( pix_size, code ) \ + { \ + int x, y; \ + for ( y = 0; y < height; ++y ) \ + { \ + out = data + y * bytes_per_line; \ + unsigned long red_delta = 0, green_delta = 0, blue_delta = 0; \ + color_t *in = (color_t *)bitmap_rows[y]; \ + for ( x = 0; x < width; ++x, ++in ) \ + { \ + unsigned long red = in->r + red_delta; \ + unsigned long green = in->g + green_delta; \ + unsigned long blue = in->b + blue_delta; \ + red_delta = red & red_delta_mask; \ + green_delta = green & green_delta_mask; \ + blue_delta = blue & blue_delta_mask; \ + if ( red > 255 ) \ + red = 255; \ + if ( green > 255 ) \ + green = 255; \ + if ( blue > 255 ) \ + blue = 255; \ + unsigned long pixel = \ + ( SHIFT( red, red_shift ) & red_mask ) | \ + ( SHIFT( green, green_shift ) & green_mask ) | \ + ( SHIFT( blue, blue_shift ) & blue_mask ); \ + code \ + } \ + } \ + } + + char *out = data; + + if ( bpp == 32 ) + { + if ( machine_byte_order == byte_order ) + COPY_IN_OUT( 4, *( (uint32_t *)out ) = (uint32_t)pixel; out += 4; ) + else + COPY_IN_OUT( 4, uint32_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 3 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); + *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 1 ); + *( (uint8_t *)out + 3 ) = *( (uint8_t *)(&tmp) ); + out += 4; ) + } + else if ( bpp == 24 ) + { + if ( machine_byte_order == byte_order && byte_order == LSBFirst ) + COPY_IN_OUT( 3, *( (color_t *)out ) = *( (color_t *)( &pixel ) ); out += 3; ) + else if ( machine_byte_order == byte_order && byte_order == MSBFirst ) + COPY_IN_OUT( 3, uint32_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 1 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); + *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 3 ); + out += 3; ) + else + COPY_IN_OUT( 3, uint32_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 3 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); + *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 1 ); + out += 3; ) + } + else if ( bpp == 16 ) + { + if ( machine_byte_order == byte_order ) + COPY_IN_OUT( 2, *( (uint16_t *)out ) = (uint16_t)pixel; out += 2; ) + else + COPY_IN_OUT( 2, uint16_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 1 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) ); + out += 2; ); + } + else if ( bpp == 8 ) + { + COPY_IN_OUT( 1, *( (uint8_t *)out ) = (uint8_t)pixel; ++out; ) + } + else + { + fprintf( stderr, "Unsupported depth: %d bits per pixel.\n", bpp ); + XFreeGC( display, pixmap_gc ); + XFreePixmap( display, pixmap ); + XDestroyImage( image ); + return; + } + +#undef COPY_IN_OUT + + XPutImage( display, pixmap, pixmap_gc, image, 0, 0, 0, 0, width, height ); + XDestroyImage( image ); + } + else //if ( depth == 1 || visual->class == DirectColor ) + { + // FIXME Something like the following, but faster ;-) - XDrawPoint is not + // a good idea... + int x, y; + for ( y = 0; y < height; ++y ) + { + color_t *color = (color_t *)&bitmap_rows[y]; + + int delta = 0; + for ( x = 0; x < width; ++x, ++color ) + { + int rnd = (int)( ( (long)( random() - RAND_MAX/2 ) * 32000 )/RAND_MAX ); + int luminance = delta + rnd + 299 * (int)color->r + 587 * (int)color->g + 114 * (int)color->b; + + if ( luminance < 128000 ) + { + XSetForeground( display, pixmap_gc, BlackPixel( display, screen ) ); + delta = luminance; + } + else + { + XSetForeground( display, pixmap_gc, WhitePixel( display, screen ) ); + delta = luminance - 255000; + } + + XDrawPoint( display, pixmap, pixmap_gc, x, y ); + } + } + } + + XSetWindowBackgroundPixmap( display, win, pixmap ); + + XFreeGC( display, pixmap_gc ); + XFreePixmap( display, pixmap ); +} + +// The old method of hiding the window decorations +static void suppress_decorations_motif() +{ + struct { + unsigned long flags, functions, decorations; + long input_mode; + } mwmhints; + + Atom a = XInternAtom( display, "_MOTIF_WM_HINTS", False ); + + mwmhints.flags = 15; // functions, decorations, input_mode, status + mwmhints.functions = 2; // ? + mwmhints.decorations = 0; + mwmhints.input_mode = 0; + + XChangeProperty( display, win, a, a, 32, + PropModeReplace, (unsigned char*)&mwmhints, 5 ); +} + +// This is a splash, set it as such. +// If it fails, just hide the decorations... +static void suppress_decorations() +{ + Atom atom_type = XInternAtom( display, "_NET_WM_WINDOW_TYPE", True ); + Atom atom_splash = XInternAtom( display, "_NET_WM_WINDOW_TYPE_SPLASH", True ); + + if ( atom_type != None && atom_splash != None ) + XChangeProperty( display, win, atom_type, XA_ATOM, 32, + PropModeReplace, (unsigned char*)&atom_splash, 1 ); + //else + suppress_decorations_motif(); // FIXME: Unconditional until Metacity/compiz's SPLASH handling is fixed +} + +// Create the window +// Return: 1 - success, 0 - failure +int splash_create_window( int argc, char** argv ) +{ + char *display_name = NULL; + int i; + for ( i = 0; i < argc; i++ ) + { + if ( !strcmp( argv[i], "-display" ) || !strcmp( argv[i], "--display" ) ) + display_name = ( i + 1 < argc )? argv[i+1]: NULL; + } + + if ( !display_name ) + display_name = getenv( "DISPLAY" ); + + // init display + display = XOpenDisplay( display_name ); + if ( !display ) + { + fprintf( stderr, "Failed to open display\n" ); + return 0; + } + + // create the window + screen = DefaultScreen( display ); + depth = DefaultDepth( display, screen ); + color_map = DefaultColormap( display, screen ); + visual = DefaultVisual( display, screen ); + + Window root_win = RootWindow( display, screen ); + int display_width = DisplayWidth( display, screen ); + int display_height = DisplayHeight( display, screen ); + +#ifdef USE_XINERAMA + int n_xinerama_screens = 1; + XineramaScreenInfo* p_screens = XineramaQueryScreens( display, &n_xinerama_screens ); + if( p_screens ) + { + int i = 0; + for( ; i < n_xinerama_screens; i++ ) + { + if ( p_screens[i].screen_number == screen ) + { + display_width = p_screens[i].width; + display_height = p_screens[i].height; + break; + } + } + XFree( p_screens ); + } +#endif + + win = XCreateSimpleWindow( display, root_win, + ( display_width - width ) / 2, ( display_height - height ) / 2, + width, height, 0, + BlackPixel( display, screen ), BlackPixel( display, screen ) ); + + XSetWindowColormap( display, win, color_map ); + + // setup colors +#define FILL_COLOR( xcol,col ) xcol.red = 256*col.r; xcol.green = 256*col.g; xcol.blue = 256*col.b; + FILL_COLOR( barcolor, barcol ); + FILL_COLOR( framecolor, framecol ); +#undef FILL_COLOR + + XAllocColor( display, color_map, &barcolor ); + XAllocColor( display, color_map, &framecolor ); + + // not resizable, no decorations, etc. + unsigned long value_mask = 0; + XGCValues values; + gc = XCreateGC( display, win, value_mask, &values ); + + XSizeHints size_hints; + size_hints.flags = PPosition | PSize | PMinSize | PMaxSize; + size_hints.min_width = width; + size_hints.max_width = width; + size_hints.min_height = height; + size_hints.max_height = height; + + char *name = "LibreOffice"; + char *icon = "icon"; // FIXME + + XSetStandardProperties( display, win, name, icon, None, + 0, 0, &size_hints ); + + // the actual work + suppress_decorations(); + create_pixmap(); + + // show it + XSelectInput( display, win, 0 ); + XMapWindow( display, win ); + + return 1; +} + +// Re-draw & process the events +// Just throwing them away - we do not need anything more... +static void process_events() +{ + XEvent xev; + int num_events; + + XFlush( display ); + num_events = XPending( display ); + while ( num_events > 0 ) + { + num_events--; + XNextEvent( display, &xev ); + } +} + +// Draw the progress +void splash_draw_progress( int progress ) +{ + if (!display) + return; + + // sanity + if ( progress < 0 ) + progress = 0; + if ( progress > 100 ) + progress = 100; + + // draw progress... + int length = ( progress * barwidth / 100 ) - ( 2 * barspace ); + if ( length < 0 ) + length = 0; + + // border + XSetForeground( display, gc, framecolor.pixel ); + XDrawRectangle( display, win, gc, + tlx, tly, + barwidth, barheight ); + + // progress bar + XSetForeground( display, gc, barcolor.pixel ); + XFillRectangle( display, win, gc, + tlx + barspace, tly + barspace, + length + 1, barheight - 2*barspace + 1 ); + + // pending events + process_events(); +} + +// Close the window & cleanup +void splash_close_window() +{ + if (display) + XCloseDisplay( display ); + display = NULL; +#ifdef USE_LIBPNG + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); +#else + free( bitmap_rows ); +#endif + bitmap_rows = NULL; +} + +#else /* not ENABLE_QUICKSTART_LIBPNG */ + +/* Stubs that will never be called in this case */ + +int splash_load_bmp( const char *filename ) +{ + (void)filename; + return 1; +} +void splash_setup( int barc[3], int framec[3], int posx, int posy, int w, int h ) +{ + (void)barc; (void)framec; (void)posx; (void)posy; (void)w; (void)h; +} +int splash_create_window( int argc, char** argv ) +{ + (void)argc; (void)argv; + return 1; +} +void splash_close_window() +{ +} +void splash_draw_progress( int progress ) +{ + (void)progress; +} + +#endif // ENABLE_QUICKSTART_LIBPNG + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/splashx.h b/desktop/unx/source/splashx.h new file mode 100755 index 000000000000..537034c6efc8 --- /dev/null +++ b/desktop/unx/source/splashx.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Novell, Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#ifndef _SPLASHX_H +#define _SPLASHX_H + +#ifdef __cplusplus +extern "C" { +#endif + +// Load the specified bitmap so we can have as a background of the +// splash. +// +// Note: Must be called before the create_window(), otherwise there will be no +// image in the splash, just black rectangle. +// +// Return: 1 - success, 0 - failure (non-existing, etc.) +int splash_load_bmp( const char *filename ); + +// Init some of the values +// If not called, the defaults are used +// barc, framec - colors, posx, posy - position, w, h - size +void splash_setup( int barc[3], int framec[3], int posx, int posy, int w, int h ); + +// Create the splash window +// Return: 1 - success, 0 - failure +int splash_create_window( int argc, char** argv ); + +// Destroy the splash window +void splash_close_window(); + +// Update the progress bar +void splash_draw_progress( int progress ); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _SPLASHX_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/start.c b/desktop/unx/source/start.c new file mode 100755 index 000000000000..85e2e2822c64 --- /dev/null +++ b/desktop/unx/source/start.c @@ -0,0 +1,1049 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Novell, Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#include <signal.h> +#include <unistd.h> +#include <limits.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sys/un.h> +#include <sys/poll.h> +#include <fcntl.h> +#include <stdio.h> +#include <libgen.h> +#include <string.h> +#include <errno.h> + +#include <osl/nlsupport.h> +#include <osl/process.h> +#include <osl/thread.h> +#include <rtl/bootstrap.h> +#include <rtl/digest.h> +#include <rtl/ustrbuf.h> +#include <sal/main.h> + +#include "args.h" +#include "splashx.h" + +#define IMG_SUFFIX ".png" +#define PIPEDEFAULTPATH "/tmp" +#define PIPEALTERNATEPATH "/var/tmp" + +/* Easier conversions: rtl_uString to rtl_String */ +static rtl_String * +ustr_to_str( rtl_uString *pStr ) +{ + rtl_String *pOut = NULL; + + rtl_uString2String( &pOut, rtl_uString_getStr( pStr ), + rtl_uString_getLength( pStr ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + + return pOut; +} + +/* Easier conversions: char * to rtl_uString */ +static rtl_uString * +charp_to_ustr( const char *pStr ) +{ + rtl_uString *pOut = NULL; + + rtl_string2UString( &pOut, pStr, strlen( pStr ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); + + return pOut; +} + +/* Easier debugging of rtl_uString values. */ +#if OSL_DEBUG_LEVEL > 1 +static void +ustr_debug( const char *pMessage, rtl_uString *pStr ) +{ + rtl_String *pOut = ustr_to_str( pStr ); + + fprintf( stderr, "%s: %s\n", pMessage, rtl_string_getStr( pOut ) ); + + rtl_string_release( pOut ); + return; +} +#else +#define ustr_debug( a, b ) {} +#endif + +typedef struct { + int status_fd; + oslProcess child; +} ChildInfo; + +static int +child_info_get_status_fd (ChildInfo *info) +{ + return info->status_fd; +} + +static void +child_info_destroy (ChildInfo *info) +{ + close (info->status_fd); + osl_freeProcessHandle (info->child); + free (info); +} + +static ChildInfo * +child_spawn ( Args *args, sal_Bool bAllArgs, sal_Bool bWithStatus ) +{ + rtl_uString *pApp = NULL, *pTmp = NULL; + rtl_uString **ppArgs; + sal_uInt32 nArgs, i; + char buffer[64]; + ChildInfo *info; + int status_pipe[2]; + oslProcessError nError; + + info = calloc (1, sizeof (ChildInfo)); + + /* create pipe */ + if ( pipe( status_pipe ) < 0 ) + { + fprintf( stderr, "ERROR: no file handles\n"); + exit( 1 ); + } + info->status_fd = status_pipe[0]; + + /* application name */ + rtl_uString_newFromAscii( &pApp, "file://" ); + rtl_uString_newConcat( &pApp, pApp, args->pAppPath ); + rtl_uString_newFromAscii( &pTmp, "/soffice.bin" ); + rtl_uString_newConcat( &pApp, pApp, pTmp ); + rtl_uString_release( pTmp ); + pTmp = NULL; + + /* copy args */ + nArgs = bAllArgs ? args->nArgsTotal : args->nArgsEnv; + ppArgs = (rtl_uString **)calloc( nArgs + 1, sizeof( rtl_uString* ) ); + for ( i = 0; i < nArgs; ++i ) + ppArgs[i] = args->ppArgs[i]; + + if( bWithStatus ) + { + /* add the pipe arg */ + snprintf (buffer, 63, "--splash-pipe=%d", status_pipe[1]); + rtl_uString_newFromAscii( &pTmp, buffer ); + ppArgs[nArgs] = pTmp; + ++nArgs; + } + + /* start the main process */ + nError = osl_executeProcess( pApp, ppArgs, nArgs, + osl_Process_NORMAL, + NULL, + NULL, + NULL, 0, + &info->child ); + + if (pTmp) + rtl_uString_release( pTmp ); + free (ppArgs); + + if ( nError != osl_Process_E_None ) + { + fprintf( stderr, "ERROR %d forking process", nError ); + ustr_debug( "", pApp ); + rtl_uString_release( pApp ); + _exit (1); + } + + rtl_uString_release( pApp ); + close( status_pipe[1] ); + + return info; +} + +static sal_Bool +child_exited_wait (ChildInfo *info, sal_Bool bShortWait) +{ + TimeValue t = { 0, 250 /* ms */ * 1000 * 1000 }; + if (!bShortWait) + t.Seconds = 1024; + return osl_joinProcessWithTimeout (info->child, &t) != osl_Process_E_TimedOut; +} + +static int +child_get_exit_code (ChildInfo *info) +{ + oslProcessInfo inf; + + inf.Code = -1; + inf.Size = sizeof (inf); + if (osl_getProcessInfo (info->child, osl_Process_EXITCODE, &inf) != osl_Process_E_None) + { + fprintf (stderr, "Warning: failed to fetch libreoffice exit status\n"); + return -1; + } + return inf.Code; +} + +typedef enum { ProgressContinue, ProgressRestart, ProgressExit } ProgressStatus; + +/* Path of the application. */ +static rtl_uString * +get_app_path( const char *pAppExec ) +{ + char pRealPath[PATH_MAX]; + rtl_uString *pResult; + + char *pOrigPath = strdup( pAppExec ); + char *pPath = dirname( pOrigPath ); + + realpath( pPath, pRealPath ); + pResult = charp_to_ustr( pRealPath ); + free( pOrigPath ); + + return pResult; +} + +/* Compute the OOo md5 hash from 'pText' */ +static rtl_uString * +get_md5hash( rtl_uString *pText ) +{ + rtl_uString *pResult = NULL; + sal_Int32 nCapacity = 100; + + if ( !pText ) + return NULL; + +#if OSL_DEBUG_LEVEL > 1 + rtl_String *pOut = ustr_to_str( pText ); + fprintf (stderr, "Generate pipe md5 for '%s'\n", pOut->buffer); + rtl_string_release( pOut ); +#endif + + unsigned char *pData = (unsigned char *)rtl_uString_getStr( pText ); + sal_uInt32 nSize = rtl_uString_getLength( pText ) * sizeof( sal_Unicode ); + if ( !pData ) + return NULL; + + rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 ); + if ( digest == 0 ) + return NULL; + + sal_uInt32 md5_key_len = rtl_digest_queryLength( digest ); + sal_uInt8 *md5_buf = (sal_uInt8 *)calloc( md5_key_len, sizeof( sal_uInt8 ) ); + + rtl_digest_init( digest, pData , nSize ); + rtl_digest_update( digest, pData, nSize ); + rtl_digest_get( digest, md5_buf, md5_key_len ); + rtl_digest_destroy( digest ); + + /* create hex-value string from the MD5 value to keep + the string size minimal */ + rtl_uString_new_WithLength( &pResult, nCapacity ); + sal_uInt32 i = 0; + for ( ; i < md5_key_len; ++i ) + { + char val[3]; + snprintf( val, 3, "%x", md5_buf[i] ); /* sic! we ignore some of the 0's */ + + rtl_uStringbuffer_insert_ascii( &pResult, &nCapacity, rtl_uString_getLength( pResult ), + val, strlen( val ) ); + } + + /* cleanup */ + free( md5_buf ); + + return pResult; +} + +/* Construct the pipe name */ +static rtl_uString * +get_pipe_path( rtl_uString *pAppPath ) +{ + rtl_uString *pPath = NULL, *pTmp = NULL, *pUserInstallation = NULL; + rtl_uString *pResult = NULL, *pBasePath = NULL, *pAbsUserInstallation = NULL; + + /* setup bootstrap filename */ + rtl_uString_newFromAscii( &pPath, "file://" ); + rtl_uString_newConcat( &pPath, pPath, pAppPath ); + rtl_uString_newFromAscii( &pTmp, "/" ); + rtl_uString_newConcat( &pPath, pPath, pTmp ); + rtl_uString_newFromAscii( &pTmp, SAL_CONFIGFILE( "bootstrap" ) ); + rtl_uString_newConcat( &pPath, pPath, pTmp ); + + ustr_debug( "bootstap", pPath ); + + /* read userinstallation value */ + rtlBootstrapHandle handle = rtl_bootstrap_args_open( pPath ); + + rtl_uString_newFromAscii( &pTmp, "UserInstallation" ); + rtl_bootstrap_get_from_handle( handle, pTmp, &pUserInstallation, NULL ); + + rtl_bootstrap_args_close( handle ); + + /* turn it into an absolute path - unwinding symlinks etc. */ + if ( osl_getProcessWorkingDir (&pBasePath) || + osl_getAbsoluteFileURL( pBasePath, pUserInstallation, &pAbsUserInstallation ) ) + rtl_uString_newFromString (&pAbsUserInstallation, pUserInstallation); + + /* create the pipe name */ + ustr_debug( "user installation", pAbsUserInstallation ); + rtl_uString *pMd5hash = get_md5hash( pAbsUserInstallation ); + if ( !pMd5hash ) + rtl_uString_new( &pMd5hash ); + + if ( access( PIPEDEFAULTPATH, R_OK|W_OK ) == 0 ) + rtl_uString_newFromAscii( &pResult, PIPEDEFAULTPATH ); + else + rtl_uString_newFromAscii( &pResult, PIPEALTERNATEPATH ); + + rtl_uString_newFromAscii( &pTmp, "/OSL_PIPE_" ); + rtl_uString_newConcat( &pResult, pResult, pTmp ); + + sal_Unicode pUnicode[RTL_USTR_MAX_VALUEOFINT32]; + rtl_ustr_valueOfInt32( pUnicode, (int)getuid(), 10 ); + rtl_uString_newFromStr( &pTmp, pUnicode ); + rtl_uString_newConcat( &pResult, pResult, pTmp ); + + rtl_uString_newFromAscii( &pTmp, "_SingleOfficeIPC_" ); + rtl_uString_newConcat( &pResult, pResult, pTmp ); + + rtl_uString_newConcat( &pResult, pResult, pMd5hash ); + + ustr_debug( "result", pResult ); + + /* cleanup */ + rtl_uString_release( pMd5hash ); + rtl_uString_release( pPath ); + rtl_uString_release( pTmp ); + rtl_uString_release( pBasePath ); + rtl_uString_release( pUserInstallation ); + rtl_uString_release( pAbsUserInstallation ); + + return pResult; +} + +/* Get fd of the pipe of the already running OOo. */ +static int +connect_pipe( rtl_uString *pPipePath ) +{ + int fd; + size_t len; + struct sockaddr_un addr; + + rtl_String *pPipeStr = ustr_to_str( pPipePath ); + + memset( &addr, 0, sizeof( addr ) ); + + if ( ( fd = socket( AF_UNIX, SOCK_STREAM, 0 ) ) < 0 ) + return fd; + + fcntl( fd, F_SETFD, FD_CLOEXEC ); + + addr.sun_family = AF_UNIX; + strncpy( addr.sun_path, rtl_string_getStr( pPipeStr ), sizeof( addr.sun_path ) ); + rtl_string_release( pPipeStr ); + +/* cut / paste from osl's pipe.c */ +#if defined(FREEBSD) + len = SUN_LEN( &addr ); +#else + len = sizeof( addr ); +#endif + + if ( connect( fd, (struct sockaddr *)&addr, len ) < 0 ) + return -1; + + return fd; +} + +/* Escape: "," -> "\\,", "\0" -> "\\0", "\\" -> "\\\\" */ +static rtl_uString * +escape_path( rtl_uString *pToEscape ) +{ + rtl_uString *pBuffer = NULL; + sal_Int32 nCapacity = 1000; + + rtl_uString_new_WithLength( &pBuffer, nCapacity ); + + sal_Int32 i = 0; + sal_Int32 nEscapeLength = rtl_uString_getLength( pToEscape ); + for ( ; i < nEscapeLength; ++i ) + { + sal_Unicode c = pToEscape->buffer[i]; + switch ( c ) + { + case (sal_Unicode)'\0': + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "\\0" ) ); + break; + case (sal_Unicode)',': + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "\\," ) ); + break; + case (sal_Unicode)'\\': + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "\\\\" ) ); + break; + default: + rtl_uStringbuffer_insert( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + &c, 1 ); + } + } + + return pBuffer; +} + +/* Send args to the OOo instance (using the 'fd' file descriptor) */ +static sal_Bool +send_args( int fd, rtl_uString *pCwdPath ) +{ + rtl_uString *pBuffer = NULL, *pTmp = NULL; + sal_Int32 nCapacity = 1000; + rtl_String *pOut = NULL; + sal_Bool bResult; + size_t nLen; + rtl_uString *pEscapedCwdPath = escape_path( pCwdPath ); + + rtl_uString_new_WithLength( &pBuffer, nCapacity ); + rtl_uString_new( &pTmp ); + + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "InternalIPC::Arguments" ) ); + + if ( rtl_uString_getLength( pEscapedCwdPath ) ) + { + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "1" ) ); + rtl_uStringbuffer_insert( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + rtl_uString_getStr( pEscapedCwdPath ), + rtl_uString_getLength( pEscapedCwdPath ) ); + } + else + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "0" ) ); + + sal_Bool bDontConvertNext = sal_False; + sal_uInt32 nArg; + sal_uInt32 nArgCount = osl_getCommandArgCount(); + for ( nArg = 0; nArg < nArgCount; ++nArg ) + { + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + ",", 1 ); + + osl_getCommandArg( nArg, &pTmp ); + + // this is not a param, we have to prepend filenames with file:// + // FIXME: improve the check + if ( ( pTmp->buffer[0] != (sal_Unicode)'-' ) ) + { + sal_Int32 nFirstColon = rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, ':' ); + sal_Int32 nFirstSlash = rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, '/' ); + + // check that pTmp is not an URI yet + // note ".uno" ".slot" & "vnd.sun.star.script" are special urls that + // don't expect a following '/' + + const char* schemes[] = { "slot:", ".uno:", "vnd.sun.star.script:" }; + sal_Bool bIsSpecialURL = sal_False; + int index = 0; + int len = SAL_N_ELEMENTS(schemes); + for ( ; index < len; ++index ) + { + if ( rtl_ustr_indexOfAscii_WithLength( pTmp->buffer + , pTmp->length , schemes[ index ], strlen(schemes[ index ] )) == 0 ) + { + bIsSpecialURL = sal_True; + break; + } + } + + if ( !bIsSpecialURL && ( nFirstColon < 1 || ( nFirstSlash != nFirstColon + 1 ) ) ) + { + // some of the switches (currently just -pt) don't want to + // have the filenames as URIs + if ( !bDontConvertNext ) + osl_getAbsoluteFileURL( pCwdPath, pTmp, &pTmp ); + } + } + + // don't convert filenames with some of the switches + // (currently just -pt) + bDontConvertNext = !rtl_ustr_ascii_compareIgnoreAsciiCase( pTmp->buffer, "-pt" ); + + rtl_uString *pEscapedTmp = escape_path( pTmp ); + + rtl_uStringbuffer_insert( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + rtl_uString_getStr( pEscapedTmp ), + rtl_uString_getLength( pEscapedTmp ) ); + + rtl_uString_release( pEscapedTmp ); + } + + ustr_debug( "Pass args", pBuffer ); + + pOut = ustr_to_str( pBuffer ); + + nLen = rtl_string_getLength( pOut ) + 1; + bResult = ( write( fd, rtl_string_getStr( pOut ), nLen ) == (ssize_t) nLen ); + + /* cleanup */ + rtl_uString_release( pEscapedCwdPath ); + rtl_uString_release( pBuffer ); + rtl_uString_release( pTmp ); + rtl_string_release( pOut ); + + return bResult; +} + +static void +load_splash_image( rtl_uString *pUAppPath ) +{ + char *pBuffer, *pSuffix, *pLocale; + int nLocSize; + rtl_Locale *pLoc = NULL; + rtl_String *pLang, *pCountry, *pAppPath; + + osl_getProcessLocale (&pLoc); + pLang = ustr_to_str (pLoc->Language); + pCountry = ustr_to_str (pLoc->Country); + + nLocSize = strlen (pLang->buffer) + strlen (pCountry->buffer) + 8; + pLocale = malloc (nLocSize); + pLocale[0] = '-'; + strcpy (pLocale + 1, pLang->buffer); + strcat (pLocale, "_"); + strcat (pLocale, pCountry->buffer); + + rtl_string_release( pCountry ); + rtl_string_release( pLang ); + + pAppPath = ustr_to_str (pUAppPath); + pBuffer = malloc (pAppPath->length + nLocSize + 256); + strcpy (pBuffer, pAppPath->buffer); + pSuffix = pBuffer + pAppPath->length; + rtl_string_release( pAppPath ); + + strcpy (pSuffix, "/edition/intro"); + strcat (pSuffix, pLocale); + strcat (pSuffix, IMG_SUFFIX); + if ( splash_load_bmp( pBuffer ) ) + goto cleanup; + + strcpy (pSuffix, "/edition/intro" IMG_SUFFIX); + if ( splash_load_bmp( pBuffer ) ) + goto cleanup; + + strcpy (pSuffix, "/intro"); + strcat (pSuffix, pLocale); + strcat (pSuffix, IMG_SUFFIX); + if ( splash_load_bmp( pBuffer ) ) + goto cleanup; + + strcpy (pSuffix, "/intro" IMG_SUFFIX); + if ( splash_load_bmp( pBuffer ) ) + goto cleanup; + + fprintf (stderr, "Failed to find intro image\n"); + + cleanup: + free (pLocale); + free (pBuffer); +} + +/* Fill 'array' with values of the key 'name'. + Its value is a comma delimited list of integers */ +static void +get_bootstrap_value( int *array, int size, rtlBootstrapHandle handle, const char *name ) +{ + rtl_uString *pKey = NULL, *pValue = NULL; + + /* get the value from the ini file */ + rtl_uString_newFromAscii( &pKey, name ); + rtl_bootstrap_get_from_handle( handle, pKey, &pValue, NULL ); + + /* the value is several numbers delimited by ',' - parse it */ + if ( rtl_uString_getLength( pValue ) > 0 ) + { + rtl_uString *pToken = NULL; + int i = 0; + sal_Int32 nIndex = 0; + for ( ; ( nIndex >= 0 ) && ( i < size ); ++i ) + { + nIndex = rtl_uString_getToken( &pToken, pValue, 0, ',', nIndex ); + array[i] = rtl_ustr_toInt32( rtl_uString_getStr( pToken ), 10 ); + } + + rtl_uString_release( pToken ); + } + + /* cleanup */ + rtl_uString_release( pKey ); + rtl_uString_release( pValue ); +} + +/* Load the colors and size of the splash. */ +static void +load_splash_defaults( rtl_uString *pAppPath, sal_Bool *bNoDefaults ) +{ + rtl_uString *pSettings = NULL, *pTmp = NULL; + rtlBootstrapHandle handle; + + /* costruct the sofficerc file location */ + rtl_uString_newFromAscii( &pSettings, "file://" ); + rtl_uString_newConcat( &pSettings, pSettings, pAppPath ); + rtl_uString_newFromAscii( &pTmp, "/" ); + rtl_uString_newConcat( &pSettings, pSettings, pTmp ); + rtl_uString_newFromAscii( &pTmp, SAL_CONFIGFILE( "soffice" ) ); + rtl_uString_newConcat( &pSettings, pSettings, pTmp ); + + /* use it as the bootstrap file */ + handle = rtl_bootstrap_args_open( pSettings ); + + int logo[1] = { -1 }, + bar[3] = { -1, -1, -1 }, + frame[3] = { -1, -1, -1 }, + pos[2] = { -1, -1 }, + size[2] = { -1, -1 }; + + /* get the values */ + get_bootstrap_value( logo, 1, handle, "Logo" ); + get_bootstrap_value( bar, 3, handle, "ProgressBarColor" ); + get_bootstrap_value( frame, 3, handle, "ProgressFrameColor" ); + get_bootstrap_value( pos, 2, handle, "ProgressPosition" ); + get_bootstrap_value( size, 2, handle, "ProgressSize" ); + + if ( logo[0] == 0 ) + *bNoDefaults = sal_True; + + splash_setup( bar, frame, pos[0], pos[1], size[0], size[1] ); + + /* cleanup */ + rtl_bootstrap_args_close( handle ); + rtl_uString_release( pSettings ); + rtl_uString_release( pTmp ); +} + +#define BUFFER_LEN 255 + +/* Read the percent to show in splash. */ +static ProgressStatus +read_percent( ChildInfo *info, int *pPercent ) +{ + static char pBuffer[BUFFER_LEN + 1]; + static char *pNext = pBuffer; + static ssize_t nRead = 0; + + char *pBegin; + char *pIter; + + /* from the last call */ + int nNotProcessed = nRead - ( pNext - pBuffer ); + if ( nNotProcessed >= BUFFER_LEN ) + return sal_False; + + memmove( pBuffer, pNext, nNotProcessed ); + + /* read data */ + nRead = read( child_info_get_status_fd (info), + pBuffer + nNotProcessed, BUFFER_LEN - nNotProcessed ); + if ( nRead < 0 ) { + if (errno == EINTR) + return ProgressContinue; + return ProgressExit; + } + + nRead += nNotProcessed; + pBuffer[nRead] = '\0'; + + /* skip old data */ + pBegin = pBuffer; + pNext = pBuffer; + for ( pIter = pBuffer; *pIter; ++pIter ) + { + if ( *pIter == '\n' ) + { + pBegin = pNext; + pNext = pIter + 1; + } + } + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "Got status: %s\n", pBegin ); +#endif + if ( !strncasecmp( pBegin, "end", 3 ) ) + return ProgressExit; + else if ( !strncasecmp( pBegin, "restart", 7 ) ) + return ProgressRestart; + else if ( sscanf( pBegin, "%d%%", pPercent ) ) + return ProgressContinue; + + /* unexpected - let's exit the splash to be safe */ + return ProgressExit; +} + +/* Simple system check. */ +static void +system_checks( void ) +{ +#ifdef LINUX + struct stat buf; + + /* check proc is mounted - lots of things fail otherwise */ + if ( stat( "/proc/version", &buf ) != 0 ) + { + fprintf( stderr, "ERROR: /proc not mounted - LibreOffice is unlikely to work well if at all" ); + exit( 1 ); + } +#endif +} + +/* re-use the pagein code */ +extern int pagein_execute (int argc, char **argv); + +#ifndef MACOSX +#define REL_PATH "/../basis-link/program/" +static char *build_pagein_path (Args *args, const char *pagein_name) +{ + char *path; + rtl_String *app_path; + + app_path = ustr_to_str (args->pAppPath); + path = malloc (app_path->length + strlen (pagein_name) + sizeof (REL_PATH) + 1); + strcpy (path, "@"); + strcpy (path + 1, rtl_string_getStr (app_path)); + strcat (path, REL_PATH); + strcat (path, pagein_name); + + rtl_string_release( app_path ); + + return path; +} +#endif + +void +exec_pagein (Args *args) +{ +// no pagein for the while on OSX +#ifdef MACOSX + (void)args; +#else + char *argv[3]; + + /* don't use -L - since that does a chdir that breaks relative paths */ + argv[0] = "dummy-pagein"; + argv[1] = build_pagein_path (args, "pagein-common"); + if (args->pPageinType) { + argv[2] = build_pagein_path (args, args->pPageinType); + } else + argv[2] = NULL; + + pagein_execute (args->pPageinType ? 3 : 2, argv); + + if (argv[2]) + free (argv[2]); + free (argv[1]); +#endif +} + +static void extend_library_path (const char *new_element) +{ + rtl_uString *pEnvName=NULL, *pOrigEnvVar=NULL, *pNewEnvVar=NULL; + const char *pathname; +#ifdef AIX + pathname = "LIBPATH"; +#else + pathname = "LD_LIBRARY_PATH"; +#endif + + rtl_uString_newFromAscii( &pEnvName, pathname ); + rtl_uString_newFromAscii( &pNewEnvVar, new_element ); + + osl_getEnvironment( pEnvName, &pOrigEnvVar ); + if (pOrigEnvVar && pOrigEnvVar->length) + { + rtl_uString *pDelim = NULL; + rtl_uString_newFromAscii( &pDelim, ":" ); + rtl_uString_newConcat( &pNewEnvVar, pNewEnvVar, pDelim ); + rtl_uString_newConcat( &pNewEnvVar, pNewEnvVar, pOrigEnvVar ); + rtl_uString_release( pDelim ); + } + + osl_setEnvironment( pEnvName, pNewEnvVar ); + + if (pOrigEnvVar) + rtl_uString_release( pOrigEnvVar ); + rtl_uString_release( pNewEnvVar ); + rtl_uString_release( pEnvName ); +} + +static void +exec_javaldx (Args *args) +{ + char newpath[4096]; + sal_uInt32 nArgs; + rtl_uString *pApp; + rtl_uString **ppArgs; + rtl_uString *pTmp, *pTmp2; + rtl_uString *pEnvironment[1] = { NULL }; + + ppArgs = (rtl_uString **)calloc( args->nArgsEnv + 2, sizeof( rtl_uString* ) ); + + for ( nArgs = 0; nArgs < args->nArgsEnv; ++nArgs ) + ppArgs[nArgs] = args->ppArgs[nArgs]; + + /* Use absolute path to redirectrc */ + pTmp = NULL; + rtl_uString_newFromAscii( &pTmp, "-env:INIFILENAME=vnd.sun.star.pathname:" ); + rtl_uString_newConcat( &pTmp, pTmp, args->pAppPath ); + pTmp2 = NULL; + rtl_uString_newFromAscii( &pTmp2, "/redirectrc" ); + rtl_uString_newConcat( &pTmp, pTmp, pTmp2 ); + ppArgs[nArgs] = pTmp; + rtl_uString_release (pTmp2); + nArgs++; + + oslProcess javaldx = NULL; + oslFileHandle fileOut= 0; + oslProcessError err; + + /* And also to javaldx */ + pApp = NULL; + rtl_uString_newFromAscii( &pApp, "file://" ); + rtl_uString_newConcat( &pApp, pApp, args->pAppPath ); + pTmp = NULL; + rtl_uString_newFromAscii( &pTmp, "/../ure/bin/javaldx" ); + rtl_uString_newConcat( &pApp, pApp, pTmp ); + rtl_uString_release( pTmp ); + + /* unset to avoid bogus console output */ + rtl_uString_newFromAscii( &pEnvironment[0], "G_SLICE" ); + + err = osl_executeProcess_WithRedirectedIO( pApp, ppArgs, nArgs, + osl_Process_NORMAL, + NULL, // security + NULL, // work dir + pEnvironment, 1, + &javaldx, // process handle + NULL, + &fileOut, + NULL); + + rtl_uString_release( pEnvironment[0] ); + rtl_uString_release( ppArgs[nArgs-1] ); + rtl_uString_release( pApp ); + free( ppArgs ); + + if( err != osl_Process_E_None) + { + fprintf (stderr, "Warning: failed to launch javaldx - java may not fuction correctly\n"); + if (javaldx) + osl_freeProcessHandle(javaldx); + if (fileOut) + osl_closeFile(fileOut); + return; + } else { + char *chomp; + sal_uInt64 bytes_read; + + /* Magically osl_readLine doesn't work with pipes with E_SPIPE - so be this lame instead: */ + while (osl_readFile (fileOut, newpath, SAL_N_ELEMENTS (newpath), &bytes_read) == osl_File_E_INTR); + + if (bytes_read <= 0) { + fprintf (stderr, "Warning: failed to read path from javaldx\n"); + if (javaldx) + osl_freeProcessHandle(javaldx); + if (fileOut) + osl_closeFile(fileOut); + return; + } + newpath[bytes_read] = '\0'; + + if ((chomp = strstr (newpath, "\n"))) + *chomp = '\0'; + } + +#if OSL_DEBUG_LEVEL > 1 + fprintf (stderr, "Adding javaldx path of '%s'\n", newpath); +#endif + extend_library_path (newpath); + + if (javaldx) + osl_freeProcessHandle(javaldx); + if (fileOut) + osl_closeFile(fileOut); +} + +SAL_IMPLEMENT_MAIN_WITH_ARGS( argc, argv ) +{ + int fd = 0; + sal_Bool bSentArgs = sal_False; + const char* pUsePlugin; + rtl_uString *pPipePath = NULL; + Args *args; + + /* turn SIGPIPE into an error */ + signal( SIGPIPE, SIG_IGN ); + + args = args_parse (); + args->pAppPath = get_app_path( argv[0] ); + if ( !args->pAppPath ) + { + fprintf( stderr, "ERROR: Can't read app link\n" ); + exit( 1 ); + } + ustr_debug( "App path", args->pAppPath ); + +#ifndef ENABLE_QUICKSTART_LIBPNG + /* we can't load and render it anyway */ + args->bInhibitSplash = sal_True; +#endif + + pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" ); + if ( pUsePlugin && !strcmp(pUsePlugin, "svp") ) + args->bInhibitSplash = sal_True; + + pPipePath = get_pipe_path( args->pAppPath ); + + if ( ( fd = connect_pipe( pPipePath ) ) >= 0 ) + { + rtl_uString *pCwdPath = NULL; + osl_getProcessWorkingDir( &pCwdPath ); + + bSentArgs = send_args( fd, pCwdPath ); + + close( fd ); + } +#if OSL_DEBUG_LEVEL > 1 + else + ustr_debug( "Failed to connect to pipe", pPipePath ); +#endif + + if ( !bSentArgs ) + { + /* we have to prepare for, and exec the binary */ + int nPercent = 0; + ChildInfo *info; + sal_Bool bAllArgs = sal_True; + sal_Bool bHaveWindow = sal_False; + sal_Bool bShortWait, bRestart; + + /* sanity check pieces */ + system_checks(); + + /* load splash image and create window */ + if ( !args->bInhibitSplash ) + { + sal_Bool bNoDefaults = sal_False; + load_splash_image( args->pAppPath ); + load_splash_defaults( args->pAppPath, &bNoDefaults ); + + if (!bNoDefaults && + ( bHaveWindow = splash_create_window( argc, argv ) ) ) + splash_draw_progress( 0 ); + } + + /* pagein */ + if (!args->bInhibitJavaLdx) + exec_pagein (args); + + /* javaldx */ + if (!args->bInhibitJavaLdx) + exec_javaldx (args); + + do { + bRestart = sal_False; + + /* fast updates if we have somewhere to update it to */ + bShortWait = bHaveWindow; + + /* Periodically update the splash & the percent according + to what status_fd says, poll quickly only while starting */ + info = child_spawn (args, bAllArgs, bShortWait); + while (!child_exited_wait (info, bShortWait)) + { + ProgressStatus eResult; + + splash_draw_progress( nPercent ); + eResult = read_percent( info, &nPercent ); + if (eResult != ProgressContinue) + { + splash_close_window (); + bShortWait = sal_False; + } + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "Polling, result is %s\n", + ( eResult == ProgressContinue )? "continue" : + ( ( eResult == ProgressRestart )? "restart" : "exit" ) ); +#endif + } + +#if OSL_DEBUG_LEVEL > 0 + fprintf (stderr, "Exited with code '%d'\n", child_get_exit_code (info)); +#endif + + switch (child_get_exit_code (info)) { + case 79: // re-start with just -env: parameters +#if OSL_DEBUG_LEVEL > 0 + fprintf (stderr, "oosplash: re-start with just -env: params !\n"); +#endif + bRestart = sal_True; + bAllArgs = sal_False; + break; + case 81: // re-start with all arguments +#if OSL_DEBUG_LEVEL > 0 + fprintf (stderr, "oosplash: re-start with all params !\n"); +#endif + bRestart = sal_True; + bAllArgs = sal_True; + break; + default: + break; + } + + child_info_destroy (info); + } while (bRestart); + } + + /* cleanup */ + rtl_uString_release( pPipePath ); + args_free (args); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/splash/exports.map b/desktop/unx/splash/exports.map new file mode 100755 index 000000000000..c4de86635ae8 --- /dev/null +++ b/desktop/unx/splash/exports.map @@ -0,0 +1,8 @@ +UDK_3_0_0 { + global: + GetVersionInfo; + component_getFactory; + + local: + *; +}; diff --git a/desktop/unx/splash/makefile.mk b/desktop/unx/splash/makefile.mk new file mode 100755 index 000000000000..e338cfe36b83 --- /dev/null +++ b/desktop/unx/splash/makefile.mk @@ -0,0 +1,76 @@ +# +# Version: MPL 1.1 / GPLv3+ / LGPLv3+ +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (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.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Initial Developer of the Original Code is +# Novell, Inc. +# Portions created by the Initial Developer are Copyright (C) 2010 the +# Initial Developer. All Rights Reserved. +# +# Contributor(s): Jan Holesovsky <kendy@novell.com> +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 3 or later (the "GPLv3+"), or +# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +# instead of those above. +# +PRJ=..$/.. + +PRJNAME=desktop +TARGET=spl_unx +LIBTARGET=NO + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +.IF "$(OS)"=="MACOSX" +dummy: + @echo "Unix quickstarter disabled for mac" +.ELSE + +# --- Files -------------------------------------------------------- + +SLOFILES = $(SLO)$/unxsplash.obj + +SHL1DEPN= makefile.mk +SHL1OBJS= $(SLOFILES) + + +SHL1TARGET=$(TARGET)$(DLLPOSTFIX) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=exports.map +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +SHL1STDLIBS= \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/splash.component + +$(MISC)/splash.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + splash.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt splash.component + +.ENDIF
\ No newline at end of file diff --git a/desktop/unx/splash/splash.component b/desktop/unx/splash/splash.component new file mode 100755 index 000000000000..cd7792744ea0 --- /dev/null +++ b/desktop/unx/splash/splash.component @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.office.comp.PipeSplashScreen"> + <service name="com.sun.star.office.PipeSplashScreen"/> + </implementation> +</component> diff --git a/desktop/unx/splash/unxsplash.cxx b/desktop/unx/splash/unxsplash.cxx new file mode 100644 index 000000000000..88d6906bfdea --- /dev/null +++ b/desktop/unx/splash/unxsplash.cxx @@ -0,0 +1,194 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright 2010, Novell Inc. + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + ************************************************************************/ +#include "unxsplash.hxx" +#include <stdio.h> +#include <unotools/bootstrap.hxx> +#include <osl/process.h> +#include <tools/urlobj.hxx> +#include <tools/stream.hxx> +#include <sfx2/sfx.hrc> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <cppuhelper/implementationentry.hxx> +#include <rtl/logfile.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/math.hxx> + +#define PIPE_ARG "--splash-pipe=" + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::registry; + +namespace desktop +{ + UnxSplashScreen::UnxSplashScreen( const Reference< uno::XComponentContext >& xCtx ) + : m_xCtx( xCtx ), + m_pOutFd( NULL ) +{ +} + +UnxSplashScreen::~UnxSplashScreen() +{ +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "UnxSplashScreen::~UnxSplashScreen()\n" ); +#endif + + if ( m_pOutFd ) + { + fclose( m_pOutFd ); + m_pOutFd = NULL; + } +} + +void SAL_CALL UnxSplashScreen::start( const OUString& /*aText*/, sal_Int32 /*nRange*/ ) + throw ( RuntimeException ) +{ +} + +void SAL_CALL UnxSplashScreen::end() + throw ( RuntimeException ) +{ +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "UnxSplashScreen::end()\n" ); +#endif + if( !m_pOutFd ) + return; + + fprintf( m_pOutFd, "end\n" ); + fflush( m_pOutFd ); +} + +void SAL_CALL UnxSplashScreen::reset() + throw ( RuntimeException ) +{ +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "UnxSplashScreen::reset()\n" ); +#endif + if( !m_pOutFd ) + return; + + fprintf( m_pOutFd, "restart\n" ); + fflush( m_pOutFd ); +} + +void SAL_CALL UnxSplashScreen::setText( const OUString& /*aText*/ ) + throw ( RuntimeException ) +{ + // TODO? +} + +void SAL_CALL UnxSplashScreen::setValue( sal_Int32 nValue ) + throw ( RuntimeException ) +{ + if ( m_pOutFd ) + { + fprintf( m_pOutFd, "%"SAL_PRIdINT32"%%\n", nValue ); + fflush( m_pOutFd ); + } +} + +// XInitialize +void SAL_CALL +UnxSplashScreen::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& ) + throw ( RuntimeException ) +{ + for ( sal_uInt32 i = 0; i < osl_getCommandArgCount(); i++ ) + { + rtl::OUString aArg; + if ( osl_getCommandArg( i, &aArg.pData ) ) + break; + if ( aArg.matchIgnoreAsciiCaseAsciiL( PIPE_ARG, sizeof( PIPE_ARG ) - 1, 0 ) ) + { + OUString aNum = aArg.copy( sizeof( PIPE_ARG ) - 1 ); + int fd = aNum.toInt32(); + m_pOutFd = fdopen( fd, "w" ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "Got argument '--splash-pipe=%d ('%s') (%p)\n", + fd, (const sal_Char *)rtl::OUStringToOString( aNum, RTL_TEXTENCODING_UTF8 ), + m_pOutFd ); +#endif + } + } +} +} + +using namespace desktop; + +// get service instance... +static uno::Reference< uno::XInterface > m_xINSTANCE; + +uno::Reference< uno::XInterface > SAL_CALL UnxSplash_createInstance(const uno::Reference< uno::XComponentContext > & xCtx ) throw( uno::Exception ) +{ + static osl::Mutex m_aMutex; + if ( !m_xINSTANCE.is() ) + { + osl::MutexGuard guard( m_aMutex ); + if ( !m_xINSTANCE.is() ) + m_xINSTANCE = (cppu::OWeakObject*) new UnxSplashScreen( xCtx ); + } + + return m_xINSTANCE; +} + +OUString UnxSplash_getImplementationName() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.office.comp.PipeSplashScreen" ) ); +} + +uno::Sequence< OUString > SAL_CALL UnxSplash_getSupportedServiceNames() throw() +{ + const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.office.PipeSplashScreen" ) ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +::cppu::ImplementationEntry aEntries[] = +{ + { + UnxSplash_createInstance, UnxSplash_getImplementationName, + UnxSplash_getSupportedServiceNames, + ::cppu::createSingleComponentFactory, + 0, 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +extern "C" +{ + +SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( const sal_Char* pImplName, void* pServiceManager, void* pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( pImplName, pServiceManager, + pRegistryKey, aEntries ); +} + +} // extern "C" + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/splash/unxsplash.hxx b/desktop/unx/splash/unxsplash.hxx new file mode 100644 index 000000000000..b25e858d9bac --- /dev/null +++ b/desktop/unx/splash/unxsplash.hxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Novell, Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#include <stdio.h> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <osl/mutex.hxx> +#include <rtl/bootstrap.hxx> + +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::task; + +namespace desktop { + +class UnxSplashScreen : public ::cppu::WeakImplHelper2< XStatusIndicator, XInitialization > +{ +private: + // don't allow anybody but ourselves to create instances of this class + UnxSplashScreen( const UnxSplashScreen& ); + UnxSplashScreen( void ); + UnxSplashScreen operator =( const UnxSplashScreen& ); + + virtual ~UnxSplashScreen(); + + static UnxSplashScreen *m_pINSTANCE; + + static osl::Mutex m_aMutex; + Reference< XComponentContext > m_xCtx; + + FILE *m_pOutFd; + +public: + UnxSplashScreen( const Reference< XComponentContext >& xCtx ); + + // XStatusIndicator + virtual void SAL_CALL start( const OUString& aText, sal_Int32 nRange ) throw ( RuntimeException ); + virtual void SAL_CALL end() throw ( RuntimeException ); + virtual void SAL_CALL reset() throw ( RuntimeException ); + virtual void SAL_CALL setText( const OUString& aText ) throw ( RuntimeException ); + virtual void SAL_CALL setValue( sal_Int32 nValue ) throw ( RuntimeException ); + + // XInitialize + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments ) throw ( RuntimeException ); +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/util/hidother.src b/desktop/util/hidother.src new file mode 100644 index 000000000000..a7ca7c09874e --- /dev/null +++ b/desktop/util/hidother.src @@ -0,0 +1,54 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "../source/inc/helpid.hrc" + +hidspecial HID_PACKAGE_MANAGER { HelpID = HID_PACKAGE_MANAGER; }; +hidspecial HID_PACKAGE_MANAGER_MENU_ITEM { HelpID = HID_PACKAGE_MANAGER_MENU_ITEM; }; +hidspecial HID_PACKAGE_MANAGER_TREELISTBOX { HelpID = HID_PACKAGE_MANAGER_TREELISTBOX; }; +hidspecial HID_PACKAGE_MANAGER_PROGRESS { HelpID = HID_PACKAGE_MANAGER_PROGRESS; }; +hidspecial HID_PACKAGE_MANAGER_PROGRESS_CANCEL { HelpID = HID_PACKAGE_MANAGER_PROGRESS_CANCEL; }; + +hidspecial HID_PACKAGE_MANAGER_UPD_REQ { HelpID = HID_PACKAGE_MANAGER_UPD_REQ; }; + +hidspecial HID_FIRSTSTART_PREV { HelpId = HID_FIRSTSTART_PREV;}; +hidspecial HID_FIRSTSTART_NEXT { HelpId = HID_FIRSTSTART_NEXT;}; +hidspecial HID_FIRSTSTART_CANCEL { HelpId = HID_FIRSTSTART_CANCEL;}; +hidspecial HID_FIRSTSTART_FINISH { HelpId = HID_FIRSTSTART_FINISH;}; +hidspecial UID_FIRSTSTART_HELP { HelpId = UID_FIRSTSTART_HELP;}; + +hidspecial UID_BTN_LICENSE_ACCEPT { HelpId = UID_BTN_LICENSE_ACCEPT;}; + +hidspecial HID_DEPLOYMENT_GUI_UPDATE { HelpId = HID_DEPLOYMENT_GUI_UPDATE;}; +hidspecial HID_DEPLOYMENT_GUI_UPDATEINSTALL { HelpId = HID_DEPLOYMENT_GUI_UPDATEINSTALL;}; + +hidspecial HID_EXTENSION_MANAGER_LISTBOX { HelpId = HID_EXTENSION_MANAGER_LISTBOX; }; +hidspecial HID_EXTENSION_MANAGER_LISTBOX_OPTIONS { HelpId = HID_EXTENSION_MANAGER_LISTBOX_OPTIONS; }; +hidspecial HID_EXTENSION_MANAGER_LISTBOX_ENABLE { HelpId = HID_EXTENSION_MANAGER_LISTBOX_ENABLE; }; +hidspecial HID_EXTENSION_MANAGER_LISTBOX_DISABLE { HelpId = HID_EXTENSION_MANAGER_LISTBOX_DISABLE; }; +hidspecial HID_EXTENSION_MANAGER_LISTBOX_REMOVE { HelpId = HID_EXTENSION_MANAGER_LISTBOX_REMOVE; }; + diff --git a/desktop/util/makefile.mk b/desktop/util/makefile.mk new file mode 100755 index 000000000000..1c6fb2e0e46b --- /dev/null +++ b/desktop/util/makefile.mk @@ -0,0 +1,233 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=soffice +TARGETTYPE=GUI +LIBTARGET=NO +GEN_HID=TRUE +GEN_HID_OTHER=TRUE + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + +UWINAPILIB = + +VERINFONAME=verinfo + +# --- Resourcen ---------------------------------------------------- + +.IF "$(GUI)" == "WNT" +RCFILES=verinfo.rc +.ENDIF + +# --- Linken der Applikation --------------------------------------- + +.IF "$(OS)" == "MACOSX" +LINKFLAGSAPPGUI!:= $(LINKFLAGSAPPGUI:s/-bind_at_load//) +.ENDIF # MACOSX + +RESLIB1NAME= dkt +RESLIB1IMAGES= $(PRJ)$/res +RESLIB1SRSFILES= $(SRS)$/desktop.srs + +.IF "$(L10N_framework)"=="" +.IF "$(LINK_SO)"=="TRUE" +APP1TARGET=so$/$(TARGET) +APP1NOSAL=TRUE +APP1RPATH=BRAND +APP1OBJS=$(OBJ)$/copyright_ascii_sun.obj $(OBJ)$/main.obj +APP1STDLIBS = $(SALLIB) $(SOFFICELIB) +APP1DEPN= $(APP1RES) verinfo.rc + +.IF "$(GUI)" == "WNT" +APP1RES= $(RES)$/desktop.res +APP1ICON=$(SOLARRESDIR)$/icons/so9_main_app.ico +APP1VERINFO=verinfo.rc +APP1LINKRES=$(MISC)$/$(TARGET)1.res +APP1STACK=10000000 + +.ENDIF # WNT + +.ENDIF # "$(LINK_SO)"=="TRUE" + +APP5TARGET=soffice +APP5NOSAL=TRUE +APP5RPATH=BRAND +APP5OBJS=$(OBJ)$/copyright_ascii_ooo.obj $(OBJ)$/main.obj +APP5STDLIBS = $(SALLIB) $(SOFFICELIB) +.IF "$(OS)" == "LINUX" +APP5STDLIBS+= -lXext -lX11 +.ENDIF # LINUX + +APP5DEPN= $(APP1TARGETN) $(APP5RES) ooverinfo.rc +APP5DEF= $(MISCX)$/$(TARGET).def + +.IF "$(GUI)" == "WNT" +APP5RES= $(RES)$/oodesktop.res +APP5ICON=$(SOLARRESDIR)$/icons/ooo3_main_app.ico +APP5VERINFO=ooverinfo.rc +APP5LINKRES=$(MISC)$/ooffice5.res +APP5STACK=10000000 +.ENDIF # WNT + +.IF "$(GUI)" == "WNT" +.IF "$(LINK_SO)"=="TRUE" +APP6TARGET=so$/officeloader +APP6RES=$(RES)$/soloader.res +APP6NOSAL=TRUE +APP6DEPN= $(APP1TARGETN) $(APP6RES) verinfo.rc +APP6VERINFO=verinfo.rc +APP6LINKRES=$(MISC)$/soffice6.res +APP6ICON=$(SOLARRESDIR)$/icons/so9_main_app.ico +APP6OBJS = \ + $(OBJ)$/extendloaderenvironment.obj \ + $(OBJ)$/officeloader.obj \ + $(SOLARLIBDIR)$/pathutils-obj.obj +STDLIB6=$(ADVAPI32LIB) $(SHELL32LIB) $(SHLWAPILIB) +.ENDIF # "$(LINK_SO)"=="TRUE" + +APP7TARGET=officeloader +APP7RES=$(RES)$/ooloader.res +APP7NOSAL=TRUE +APP7DEPN= $(APP1TARGETN) $(APP7RES) ooverinfo.rc +APP7VERINFO=ooverinfo.rc +APP7LINKRES=$(MISC)$/ooffice7.res +APP7ICON=$(SOLARRESDIR)$/icons/ooo3_main_app.ico +APP7OBJS = \ + $(OBJ)$/extendloaderenvironment.obj \ + $(OBJ)$/officeloader.obj \ + $(SOLARLIBDIR)$/pathutils-obj.obj +STDLIB7=$(ADVAPI32LIB) $(SHELL32LIB) $(SHLWAPILIB) +.ELIF "$(OS)" == "MACOSX" +APP6TARGET=officeloader +APP6NOSAL=TRUE +APP6RPATH=BRAND +APP6OBJS=$(OBJ)$/copyright_ascii_ooo.obj $(OBJ)$/officeloader.obj +APP6STDLIBS = $(SALLIB) +APP5DEPN= $(APP1TARGETN) $(APP5RES) ooverinfo.rc +APP5DEF= $(MISCX)$/$(TARGET).def +.ENDIF # WNT + +.ENDIF + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk + +.IF "$(L10N_framework)"=="" + +.IF "$(APP1TARGETN)"!="" +$(APP1TARGETN) : $(MISC)$/binso_created.flg +.ENDIF # "$(APP1TARGETN)"!="" + +.IF "$(APP5TARGETN)"!="" +$(APP5TARGETN) : $(MISC)$/binso_created.flg +.ENDIF # "$(APP6TARGETN)"!="" + +.IF "$(APP6TARGETN)"!="" +$(APP6TARGETN) : $(MISC)$/binso_created.flg +.ENDIF # "$(APP6TARGETN)"!="" + +.IF "$(GUI)" == "WNT" +ALLTAR: $(MISC)$/$(TARGET).exe.manifest +ALLTAR: $(MISC)$/$(TARGET).bin.manifest +ALLTAR: $(BIN)$/$(TARGET).bin +.IF "$(LINK_SO)"=="TRUE" +ALLTAR: $(BIN)$/so$/$(TARGET).bin +.ENDIF # "$(LINK_SO)"=="TRUE" +.ENDIF # WNT + +$(BIN)$/soffice_oo$(EXECPOST) : $(APP5TARGETN) + $(COPY) $< $@ + +.IF "$(LINK_SO)"=="TRUE" +$(BIN)$/so$/soffice_so$(EXECPOST) : $(APP1TARGETN) + $(COPY) $< $@ + +ALLTAR : $(BIN)$/so$/soffice_so$(EXECPOST) +.ENDIF # "$(LINK_SO)"=="TRUE" +ALLTAR : $(BIN)$/soffice_oo$(EXECPOST) + +.IF "$(OS)" == "MACOSX" +.IF "$(LINK_SO)"=="TRUE" +$(BIN)$/so$/soffice_mac$(EXECPOST) : $(APP1TARGETN) + $(COPY) $< $@ + +ALLTAR : $(BIN)$/so$/soffice_mac$(EXECPOST) +.ENDIF # "$(LINK_SO)"=="TRUE" + +$(BIN)$/soffice_mac$(EXECPOST) : $(APP5TARGETN) + $(COPY) $< $@ + +ALLTAR : $(BIN)$/soffice_mac$(EXECPOST) + +.ENDIF # "$(OS)" == "MACOSX" + +.IF "$(GUI)" == "WNT" + +# create a manifest file with the same name as the +# office executable file soffice.exe.manifest +.IF "$(CCNUMVER)" <= "001399999999" +$(MISC)$/$(TARGET).exe.manifest: template.manifest + $(COPY) $< $@ +.ELSE +$(MISC)$/$(TARGET).exe.template.manifest: template.manifest + $(COPY) $< $@ + +$(MISC)$/$(TARGET).exe.linker.manifest: $(BIN)$/$(TARGET)$(EXECPOST) + mt.exe -inputresource:$(BIN)$/$(TARGET)$(EXECPOST) -out:$@ + +$(MISC)$/$(TARGET).exe.manifest: $(MISC)$/$(TARGET).exe.template.manifest $(MISC)$/$(TARGET).exe.linker.manifest + mt.exe -manifest $(MISC)$/$(TARGET).exe.linker.manifest $(MISC)$/$(TARGET).exe.template.manifest -out:$@ +.ENDIF + +# create a manifest file with the same name as the +# office executable file soffice.bin.manifest +.IF "$(CCNUMVER)" <= "001399999999" +$(MISC)$/$(TARGET).bin.manifest: template.manifest + $(COPY) $< $@ +.ELSE +$(MISC)$/$(TARGET).bin.manifest: $(MISC)$/$(TARGET).exe.manifest + $(COPY) $(MISC)$/$(TARGET).exe.manifest $@ +.ENDIF + +$(BIN)$/$(TARGET).bin: $(BIN)$/$(TARGET)$(EXECPOST) + $(COPY) $< $@ + +$(BIN)$/so$/$(TARGET).bin: $(BIN)$/so$/$(TARGET)$(EXECPOST) + $(COPY) $< $@ + +.ENDIF # WNT + +$(MISC)$/binso_created.flg : + @@-$(MKDIRHIER) $(BIN)$/so && $(TOUCH) $@ + +.ENDIF diff --git a/desktop/util/ooverinfo.rc b/desktop/util/ooverinfo.rc new file mode 100644 index 000000000000..53b20852c40d --- /dev/null +++ b/desktop/util/ooverinfo.rc @@ -0,0 +1,112 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + *************************************************************************/ + +#define VER_FIRSTYEAR 2000 + +#include <windows.h> +#include "version.hrc" + +// ----------------------------------------------------------------------- +// version information +// ----------------------------------------------------------------------- + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION, SUBVERSION, VERVARIANT, VER_COUNT + PRODUCTVERSION VERSION, SUBVERSION, VERVARIANT, VER_COUNT + FILEFLAGSMASK 0x3F + FILEFLAGS +#if defined(DEBUG) + VS_FF_DEBUG | +#endif +#ifdef VER_PREL + VS_FF_PRERELEASE | +#endif + 0 + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_APP + { + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + // International StringTable + VALUE "CompanyName", "The Document Foundation\0" + VALUE "FileDescription", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\0" + VALUE "FileVersion", PPS(VER_LEVEL) "\0" + VALUE "ProductVersion", PPS(VER_LEVEL) "\0" + VALUE "OriginalFilename", "SOFFICE.EXE\0" + VALUE "InternalName", "SOFFICE\0" + VALUE "LegalCopyright", S_CRIGHT " Oracle, Inc.\0" + } + } + + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x0409, 1252 + } + } + +2 ICON "icons/oasis-text.ico" +3 ICON "icons/oasis-text-template.ico" +4 ICON "icons/oasis-spreadsheet.ico" +5 ICON "icons/oasis-spreadsheet-template.ico" +6 ICON "icons/oasis-drawing.ico" +7 ICON "icons/oasis-drawing-template.ico" +8 ICON "icons/oasis-presentation.ico" +9 ICON "icons/oasis-presentation-template.ico" +10 ICON "icons/oasis-presentation-template.ico" +11 ICON "icons/oasis-master-document.ico" +12 ICON "icons/oasis-web-template.ico" +13 ICON "icons/oasis-empty-document.ico" +14 ICON "icons/oasis-database.ico" +15 ICON "icons/oasis-formula.ico" +16 ICON "icons/oasis-web-template.ico" +17 ICON "icons/empty-document.ico" +18 ICON "icons/empty-document.ico" +19 ICON "icons/ooo3_open.ico" +20 ICON "icons/empty-document.ico" +21 ICON "icons/ooo3_writer_app.ico" +22 ICON "icons/ooo3_calc_app.ico" +23 ICON "icons/ooo3_draw_app.ico" +24 ICON "icons/ooo3_impress_app.ico" +25 ICON "icons/ooo3_math_app.ico" +26 ICON "icons/ooo3_base_app.ico" +27 ICON "icons/oasis-empty-document.ico" +28 ICON "icons/text.ico" +29 ICON "icons/text-template.ico" +30 ICON "icons/spreadsheet.ico" +31 ICON "icons/spreadsheet-template.ico" +32 ICON "icons/drawing.ico" +33 ICON "icons/drawing-template.ico" +34 ICON "icons/presentation.ico" +35 ICON "icons/presentation-template.ico" +36 ICON "icons/master-document.ico" +37 ICON "icons/empty-document.ico" +38 ICON "icons/database.ico" +39 ICON "icons/formula.ico" +40 ICON "icons/oxt-extension.ico" + diff --git a/desktop/util/ooverinfo2.rc b/desktop/util/ooverinfo2.rc new file mode 100755 index 000000000000..caacb294122d --- /dev/null +++ b/desktop/util/ooverinfo2.rc @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "version.hrc" + +// ----------------------------------------------------------------------- + +// ----------------------------------------------------------------------- +// language/character set specification table +// ----------------------------------------------------------------------- + + +ICON 2 "icons/oasis-text.ico" +ICON 3 "icons/oasis-text-template.ico" +ICON 4 "icons/oasis-spreadsheet.ico" +ICON 5 "icons/oasis-spreadsheet-template.ico" +ICON 6 "icons/oasis-drawing.ico" +ICON 7 "icons/oasis-drawing-template.ico" +ICON 8 "icons/oasis-presentation.ico" +ICON 9 "icons/oasis-presentation-template.ico" +ICON 10 "icons/oasis-presentation-template.ico" +// ICON 11 "icons/oasis-master-document.ico" +// ICON 12 "icons/oasis-web-template.ico" +ICON 13 "icons/oasis-empty-document.ico" +ICON 14 "icons/oasis-database.ico" +ICON 15 "icons/oasis-formula.ico" +ICON 16 "icons/oasis-web-template.ico" +ICON 17 "icons/empty-document.ico" +ICON 18 "icons/empty-document.ico" +ICON 19 "icons/ooo-open.ico" +ICON 20 "icons/empty-document.ico" +ICON 21 "icons/ooo-writer-app.ico" +ICON 22 "icons/ooo-calc-app.ico" +ICON 23 "icons/ooo-draw-app.ico" +ICON 24 "icons/ooo-impress-app.ico" +ICON 25 "icons/ooo-math-app.ico" +ICON 26 "icons/ooo-base-app.ico" +ICON 27 "icons/oasis-empty-document.ico" +ICON 28 "icons/text.ico" +ICON 29 "icons/text-template.ico" +ICON 30 "icons/spreadsheet.ico" +ICON 31 "icons/spreadsheet-template.ico" +ICON 32 "icons/drawing.ico" +ICON 33 "icons/drawing-template.ico" +ICON 34 "icons/presentation.ico" +ICON 35 "icons/presentation-template.ico" +ICON 36 "icons/master-document.ico" +ICON 37 "icons/empty-document.ico" +ICON 38 "icons/database.ico" +ICON 39 "icons/formula.ico" +ICON 40 "icons/oxt-extension.ico" + diff --git a/desktop/util/soffice.ico b/desktop/util/soffice.ico Binary files differnew file mode 100644 index 000000000000..88ccf5e5a6a0 --- /dev/null +++ b/desktop/util/soffice.ico diff --git a/desktop/util/template.manifest b/desktop/util/template.manifest new file mode 100755 index 000000000000..d3bd0c101f2f --- /dev/null +++ b/desktop/util/template.manifest @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity version="1.0.0.0" processorArchitecture="x86" name="LibreOffice" type="win32" /> +<description>http://www.documentfoundation.org</description> +<dependency> +<dependentAssembly> +<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="x86"/> +</dependentAssembly> +</dependency> +</assembly> diff --git a/desktop/util/verinfo.rc b/desktop/util/verinfo.rc new file mode 100644 index 000000000000..4c01f6b6b237 --- /dev/null +++ b/desktop/util/verinfo.rc @@ -0,0 +1,116 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + *************************************************************************/ + +#define VER_FIRSTYEAR 2007 + +#include <windows.h> +#include "version_so.hrc" + +// ----------------------------------------------------------------------- +// version information +// ----------------------------------------------------------------------- + +VS_VERSION_INFO versioninfo +#ifndef SUBVERSION + FILEVERSION VERSION, 0, VERVARIANT, VER_COUNT + PRODUCTVERSION VERSION, 0, VERVARIANT, VER_COUNT +#else + FILEVERSION VERSION, SUBVERSION, VERVARIANT, VER_COUNT + PRODUCTVERSION VERSION, SUBVERSION, VERVARIANT, VER_COUNT +#endif + FILEFLAGSMASK 0x3F + FILEFLAGS +#if defined(DEBUG) + VS_FF_DEBUG | +#endif +#ifdef VER_PREL + VS_FF_PRERELEASE | +#endif + 0 + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_APP + { + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + // International StringTable + VALUE "CompanyName", "The Document Foundation\0" + VALUE "FileDescription", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\0" + VALUE "FileVersion", PPS(VER_LEVEL) "\0" + VALUE "ProductVersion", PPS(VER_LEVEL) "\0" + VALUE "OriginalFilename", "SOFFICE.EXE\0" + VALUE "InternalName", "SOFFICE\0" + VALUE "LegalCopyright", S_CRIGHT " Oracle and/or its affiliates. All rights reserved.\0" + } + } + + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x0409, 1252 + } + } + +2 ICON "icons/oasis-text.ico" +3 ICON "icons/oasis-text-template.ico" +4 ICON "icons/oasis-spreadsheet.ico" +5 ICON "icons/oasis-spreadsheet-template.ico" +6 ICON "icons/oasis-drawing.ico" +7 ICON "icons/oasis-drawing-template.ico" +8 ICON "icons/oasis-presentation.ico" +9 ICON "icons/oasis-presentation-template.ico" +10 ICON "icons/oasis-presentation-template.ico" +11 ICON "icons/oasis-master-document.ico" +12 ICON "icons/oasis-web-template.ico" +13 ICON "icons/oasis-empty-document.ico" +14 ICON "icons/oasis-database.ico" +15 ICON "icons/oasis-formula.ico" +16 ICON "icons/oasis-web-template.ico" +17 ICON "icons/empty-document.ico" +18 ICON "icons/empty-document.ico" +19 ICON "icons/so9_main_app.ico" +20 ICON "icons/empty-document.ico" +21 ICON "icons/so9_writer_app.ico" +22 ICON "icons/so9_calc_app.ico" +23 ICON "icons/so9_draw_app.ico" +24 ICON "icons/so9_impress_app.ico" +25 ICON "icons/so9_math_app.ico" +26 ICON "icons/so9_base_app.ico" +27 ICON "icons/oasis-empty-document.ico" +28 ICON "icons/text.ico" +29 ICON "icons/text-template.ico" +30 ICON "icons/spreadsheet.ico" +31 ICON "icons/spreadsheet-template.ico" +32 ICON "icons/drawing.ico" +33 ICON "icons/drawing-template.ico" +34 ICON "icons/presentation.ico" +35 ICON "icons/presentation-template.ico" +36 ICON "icons/master-document.ico" +37 ICON "icons/empty-document.ico" +38 ICON "icons/database.ico" +39 ICON "icons/formula.ico" +40 ICON "icons/oxt-extension.ico" diff --git a/desktop/win32/source/QuickStart/OOQuickStart.rc b/desktop/win32/source/QuickStart/OOQuickStart.rc new file mode 100755 index 000000000000..9baf7e864f5f --- /dev/null +++ b/desktop/win32/source/QuickStart/OOQuickStart.rc @@ -0,0 +1,130 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +ICON_ACTIVE ICON DISCARDABLE "icons/ooo3_main_app.ico" +IDI_QUICKSTART ICON DISCARDABLE "icons/ooo3_main_app.ico" +IDI_SMALL ICON DISCARDABLE "icons/ooo3_main_app.ico" +ICON_INACTIVE ICON DISCARDABLE "icons/ooo3_main_app.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_QUICKSTART ACCELERATORS MOVEABLE PURE +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 230, 75 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "System" +BEGIN + ICON IDI_QUICKSTART,IDC_MYICON,14,9,16,16 + LTEXT "QuickStart Version 1.0",IDC_STATIC,49,10,119,8, + SS_NOPREFIX + LTEXT "Copyright (C) 2001",IDC_STATIC,49,20,119,8 + DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""resource.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_TITLE "SoQuickStart" + IDC_QUICKSTART "QUICKSTART" + IDS_TOOLTIP "StarOffice 6.0 QuickStart" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_EXIT "Exit" +END + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/desktop/win32/source/QuickStart/QuickStart.cpp b/desktop/win32/source/QuickStart/QuickStart.cpp new file mode 100755 index 000000000000..3531c29ea317 --- /dev/null +++ b/desktop/win32/source/QuickStart/QuickStart.cpp @@ -0,0 +1,426 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +// QuickStart.cpp : Defines the entry point for the application. +// + +#include "StdAfx.h" +#include "resource.h" +#include <systools/win32/uwinapi.h> +#include <stdio.h> + +#define MY_TASKBAR_NOTIFICATION WM_USER+1 + +#define MAX_LOADSTRING 100 + +// message used to communicate with soffice +#define TERMINATIONVETO_MESSAGE "SO TerminationVeto" +#define TERMINATE_MESSAGE "SO Terminate" +#define LISTENER_WINDOWCLASS "SO Listener Class" +#define KILLTRAY_MESSAGE "SO KillTray" + +static UINT aTerminationVetoMessage = 0x7FFF; +static UINT aTerminateMessage = 0x7FFF; +static HMENU popupMenu = NULL; +static bool bTerminateVeto = true; + +#define UPDATE_TIMER 1 + +// Global Variables: +HINSTANCE hInst; // current instance +TCHAR szTitle[MAX_LOADSTRING]; // The title bar text +TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text + +TCHAR szExitString[MAX_LOADSTRING]; +TCHAR szTooltipString[MAX_LOADSTRING]; + +// Foward declarations of functions included in this code module: +ATOM MyRegisterClass(HINSTANCE hInstance); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); + +bool SofficeRuns() +{ + // check for soffice by searching the communication window + return ( FindWindowEx( NULL, NULL, LISTENER_WINDOWCLASS, NULL ) == NULL ) ? false : true; +} + +bool launchSoffice( ) +{ + if ( !SofficeRuns() ) + { + // UINT ret = WinExec( "h:\\office60.630b\\program\\swriter.exe -bean", SW_SHOW ); + char filename[_MAX_PATH + 1]; + + filename[_MAX_PATH] = 0; + GetModuleFileName( NULL, filename, _MAX_PATH ); // soffice resides in the same dir + char *p = strrchr( filename, '\\' ); + if ( !p ) + return false; + + strncpy( p+1, "soffice.exe", _MAX_PATH - (p+1 - filename) ); + + char imagename[_MAX_PATH + 1]; + + imagename[_MAX_PATH] = 0; + _snprintf(imagename, _MAX_PATH, "\"%s\" -quickstart", filename ); + + UINT ret = WinExec( imagename, SW_SHOW ); + if ( ret < 32 ) + return false; +/* + // wait until we can communicate + int retry = 30; + while (retry-- && !SofficeRuns() ) + Sleep(1000); + + return SofficeRuns(); + */ + return true; + } + else + return true; +} + +void NotifyListener( HWND hWnd ) +{ + static HICON hIconActive=NULL; + //static HICON hIconInActive=NULL; + + if( !hIconActive ) + { + hIconActive = (HICON)LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_ACTIVE ), + IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), + LR_DEFAULTCOLOR | LR_SHARED ); + +/* hIconInActive = (HICON)LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_INACTIVE ), + IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), + LR_DEFAULTCOLOR | LR_SHARED ); + */ + } + + NOTIFYICONDATA nid; + nid.cbSize = sizeof(NOTIFYICONDATA); + nid.hWnd = hWnd; + nid.uID = IDM_QUICKSTART; + nid.szTip[SAL_N_ELEMENTS(nid.szTip) - 1] = 0; +// nid.hIcon = bTerminateVeto ? hIconActive : hIconInActive; +// strncpy(nid.szTip, bTerminateVeto ? STRING_QUICKSTARTACTIVE : STRING_QUICKSTARTINACTIVE, SAL_N_ELEMENTS(nid.szTip) - 1 ); + nid.hIcon = hIconActive; + strncpy(nid.szTip, szTooltipString, SAL_N_ELEMENTS(nid.szTip) - 1); + nid.uFlags = NIF_TIP|NIF_ICON; + + // update systray + Shell_NotifyIcon( NIM_MODIFY, &nid ); + //CheckMenuItem( popupMenu, IDM_QUICKSTART, bTerminateVeto ? MF_CHECKED : MF_UNCHECKED ); + + // notify listener + SendMessage( HWND_BROADCAST, aTerminationVetoMessage, (WORD) bTerminateVeto, 0L ); +} + + + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE /*hPrevInstance*/, + LPSTR /*lpCmdLine*/, + int nCmdShow) +{ + // Look for -killtray argument + + for ( int i = 1; i < __argc; i++ ) + { + if ( 0 == strcmp( __argv[i], "-killtray" ) ) + { + HWND hwndTray = FindWindow( LISTENER_WINDOWCLASS, NULL ); + + if ( hwndTray ) + { + UINT uMsgKillTray = RegisterWindowMessage( KILLTRAY_MESSAGE ); + SendMessage( hwndTray, uMsgKillTray, 0, 0 ); + } + + return 0; + } + } + + launchSoffice(); + return 0; + + // TODO: Place code here. + MSG msg; + HACCEL hAccelTable; + aTerminationVetoMessage = RegisterWindowMessage( TERMINATIONVETO_MESSAGE ); + aTerminateMessage = RegisterWindowMessage( TERMINATE_MESSAGE ); + + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadString(hInstance, IDC_QUICKSTART, szWindowClass, MAX_LOADSTRING); + + LoadString(hInstance, IDS_EXIT, szExitString, MAX_LOADSTRING); + LoadString(hInstance, IDS_TOOLTIP, szTooltipString, MAX_LOADSTRING); + + MyRegisterClass(hInstance); + + // Perform application initialization: + if (!InitInstance (hInstance, nCmdShow)) + { + return FALSE; + } + + hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_QUICKSTART); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) + { + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return msg.wParam; +} + + + +// +// FUNCTION: MyRegisterClass() +// +// PURPOSE: Registers the window class. +// +// COMMENTS: +// +// This function and its usage is only necessary if you want this code +// to be compatible with Win32 systems prior to the 'RegisterClassEx' +// function that was added to Windows 95. It is important to call this function +// so that the application will get 'well formed' small icons associated +// with it. +// +ATOM MyRegisterClass(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_QUICKSTART); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = NULL; + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); + + return RegisterClassEx(&wcex); +} + +// +// FUNCTION: InitInstance(HANDLE, int) +// +// PURPOSE: Saves instance handle and creates main window +// +// COMMENTS: +// +// In this function, we save the instance handle in a global variable and +// create and display the main program window. +// +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + HWND hWnd; + + hInst = hInstance; // Store instance handle in our global variable + + hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); + + if (!hWnd) + { + return FALSE; + } + + nCmdShow = SW_HIDE; // hide main window, we only need the taskbar icon + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + return TRUE; +} + +// +// FUNCTION: WndProc(HWND, unsigned, WORD, LONG) +// +// PURPOSE: Processes messages for the main window. +// +// WM_COMMAND - process the application menu +// WM_PAINT - Paint the main window +// WM_DESTROY - post a quit message and return +// +// +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_CREATE: + { + // make sure soffice runs + if( !launchSoffice() ) + return -1; + + // create popup menu + popupMenu = CreatePopupMenu(); + static int count=0; + + // Add my items + MENUITEMINFO mi; + mi.cbSize = sizeof(MENUITEMINFO); + mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; + mi.fType=MFT_STRING; + mi.fState=MFS_ENABLED|MFS_DEFAULT; + mi.wID = IDM_QUICKSTART; + mi.hSubMenu=NULL; + mi.hbmpChecked=NULL; + mi.hbmpUnchecked=NULL; + mi.dwItemData=NULL; + mi.dwTypeData = "QuickStart"; + mi.cch = strlen(mi.dwTypeData); +// InsertMenuItem(popupMenu, count++, TRUE, &mi); + + mi.cbSize = sizeof(MENUITEMINFO); + mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; + mi.fType=MFT_STRING; + mi.fState=MFS_ENABLED; + mi.wID = IDM_ABOUT; + mi.hSubMenu=NULL; + mi.hbmpChecked=NULL; + mi.hbmpUnchecked=NULL; + mi.dwItemData=NULL; + mi.dwTypeData = "Info..."; + mi.cch = strlen(mi.dwTypeData); +// InsertMenuItem(popupMenu, count++, TRUE, &mi); + + mi.cbSize = sizeof(MENUITEMINFO); + mi.fMask=MIIM_TYPE; + mi.fType=MFT_SEPARATOR; + mi.hSubMenu=NULL; + mi.hbmpChecked=NULL; + mi.hbmpUnchecked=NULL; + mi.dwItemData=NULL; +// InsertMenuItem(popupMenu, count++, TRUE, &mi); + + mi.cbSize = sizeof(MENUITEMINFO); + mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; + mi.fType=MFT_STRING; + mi.fState=MFS_ENABLED; + mi.wID = IDM_EXIT; + mi.hSubMenu=NULL; + mi.hbmpChecked=NULL; + mi.hbmpUnchecked=NULL; + mi.dwItemData=NULL; + mi.dwTypeData = szExitString; + mi.cch = strlen(mi.dwTypeData); + InsertMenuItem(popupMenu, count++, TRUE, &mi); + + // add taskbar icon + NOTIFYICONDATA nid; + nid.cbSize = sizeof(NOTIFYICONDATA); + nid.hWnd = hWnd; + nid.uID = IDM_QUICKSTART; + nid.uFlags = NIF_MESSAGE; + nid.uCallbackMessage=MY_TASKBAR_NOTIFICATION; + Shell_NotifyIcon(NIM_ADD, &nid); + + // and update state + NotifyListener( hWnd ); + + // check for soffice + SetTimer(hWnd, UPDATE_TIMER, 3000, NULL); + } + break; + + case MY_TASKBAR_NOTIFICATION: // message from taskbar + switch(lParam) + { +/* + case WM_LBUTTONDBLCLK: + bTerminateVeto = bTerminateVeto ? false : true; + NotifyListener( hWnd ); + break; + */ + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + { + POINT pt; + GetCursorPos(&pt); + SetForegroundWindow( hWnd ); + int m = TrackPopupMenuEx(popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON, + pt.x, pt.y, hWnd, NULL); + // BUGFIX: See Q135788 (PRB: Menus for Notification Icons Don't Work Correctly) + PostMessage(hWnd, NULL, 0, 0); + switch(m) + { + case IDM_QUICKSTART: + bTerminateVeto = bTerminateVeto ? false : true; + NotifyListener( hWnd ); + break; + case IDM_ABOUT: + DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); + break; + case IDM_EXIT: + DestroyWindow(hWnd); + break; + } + } + break; + } + break; + + case WM_TIMER: + if( wParam == UPDATE_TIMER ) + { + // update state + NotifyListener( hWnd ); + } + break; + + case WM_DESTROY: + // try to terminate office + SendMessage( HWND_BROADCAST, aTerminateMessage, 0, 0L ); + + // delete taskbar icon + NOTIFYICONDATA nid; + nid.cbSize=sizeof(NOTIFYICONDATA); + nid.hWnd = hWnd; + nid.uID = IDM_QUICKSTART; + Shell_NotifyIcon(NIM_DELETE, &nid); + + PostQuitMessage(0); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +// Mesage handler for about box. +LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM) +{ + switch (message) + { + case WM_INITDIALOG: + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) + { + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + break; + } + return FALSE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/QuickStart/QuickStart.h b/desktop/win32/source/QuickStart/QuickStart.h new file mode 100755 index 000000000000..b61a04075e08 --- /dev/null +++ b/desktop/win32/source/QuickStart/QuickStart.h @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#if !defined(AFX_QUICKSTART_H__7D38EE02_7699_4CF0_AFF9_FD92E05CC009__INCLUDED_) +#define AFX_QUICKSTART_H__7D38EE02_7699_4CF0_AFF9_FD92E05CC009__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_QUICKSTART_H__7D38EE02_7699_4CF0_AFF9_FD92E05CC009__INCLUDED_) + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/QuickStart/StdAfx.h b/desktop/win32/source/QuickStart/StdAfx.h new file mode 100755 index 000000000000..f5277a01332c --- /dev/null +++ b/desktop/win32/source/QuickStart/StdAfx.h @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) +#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + + +// Windows Header Files: +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#include <shellapi.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +// C RunTime Header Files +#include <stdlib.h> +#include <malloc.h> +#include <memory.h> +#include <tchar.h> + +// Local Header Files + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/QuickStart/makefile.mk b/desktop/win32/source/QuickStart/makefile.mk new file mode 100644 index 000000000000..41242d849dfb --- /dev/null +++ b/desktop/win32/source/QuickStart/makefile.mk @@ -0,0 +1,74 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=sysui +TARGET=quickstart +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +TARGETTYPE=GUI + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +UWINAPILIB = + +# --- Resources ---------------------------------------------------- + +RCFILES=OOQuickStart.rc + +# --- Files -------------------------------------------------------- + +OBJFILES=$(OBJ)$/QuickStart.obj + +APP1OBJS=$(OBJFILES) +APP1NOSAL=TRUE +APP1TARGET=$(TARGET) +APP1RPATH=BRAND +.IF "$(COM)"=="GCC" +APP1STDLIBS=-luuid +.ELSE +APP1STDLIBS=comsupp.lib +.ENDIF + +APP1STDLIBS+=$(SHELL32LIB)\ + $(OLE32LIB)\ + $(GDI32LIB)\ + $(OLEAUT32LIB)\ + $(COMDLG32LIB)\ + $(KERNEL32LIB)\ + $(OLEAUT32LIB) + +APP1NOSVRES=$(RES)$/$(TARGET).res + + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/win32/source/QuickStart/resource.h b/desktop/win32/source/QuickStart/resource.h new file mode 100755 index 000000000000..dc4a70ab5193 --- /dev/null +++ b/desktop/win32/source/QuickStart/resource.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by QUICKSTART.RC +// +#define IDR_MAINFRAME 128 +#define IDD_QUICKSTART_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDS_APP_TITLE 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDS_HELLO 106 +#define IDI_QUICKSTART 107 +#define IDI_SMALL 108 +#define IDC_QUICKSTART 109 +#define IDM_QUICKSTART 110 +#define IDS_TOOLTIP 111 +#define IDS_EXIT 112 +#define ICON_ACTIVE 1 +#define ICON_INACTIVE 2 +#define IDC_MYICON 3 +#define IDC_STATIC -1 +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 113 +#endif +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/QuickStart/so/QuickStart.rc b/desktop/win32/source/QuickStart/so/QuickStart.rc new file mode 100755 index 000000000000..732904dc745a --- /dev/null +++ b/desktop/win32/source/QuickStart/so/QuickStart.rc @@ -0,0 +1,130 @@ +//Microsoft Developer Studio generated resource script. +// +#include "../resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +ICON_ACTIVE ICON DISCARDABLE "icons/so9_main_app.ico" +IDI_QUICKSTART ICON DISCARDABLE "icons/so9_main_app.ico" +IDI_SMALL ICON DISCARDABLE "icons/so9_main_app.ico" +ICON_INACTIVE ICON DISCARDABLE "icons/so9_main_app.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_QUICKSTART ACCELERATORS MOVEABLE PURE +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 230, 75 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "System" +BEGIN + ICON IDI_QUICKSTART,IDC_MYICON,14,9,16,16 + LTEXT "QuickStart Version 1.0",IDC_STATIC,49,10,119,8, + SS_NOPREFIX + LTEXT "Copyright (C) 2001",IDC_STATIC,49,20,119,8 + DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""resource.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_TITLE "SoQuickStart" + IDC_QUICKSTART "QUICKSTART" + IDS_TOOLTIP "Oracle Open Office 3.2 QuickStart" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_EXIT "Exit" +END + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/desktop/win32/source/QuickStart/so/makefile.mk b/desktop/win32/source/QuickStart/so/makefile.mk new file mode 100755 index 000000000000..50154c7d50b2 --- /dev/null +++ b/desktop/win32/source/QuickStart/so/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=sysui +TARGET=soquickstart +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +TARGETTYPE=GUI + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +UWINAPILIB = + +# --- Resources ---------------------------------------------------- + +.IF "$(LINK_SO)"=="TRUE" + +RCFILES=QuickStart.rc +INCPRE=.. + +# --- Files -------------------------------------------------------- + +OBJFILES=$(OBJ)$/QuickStart.obj + +APP1OBJS=$(OBJFILES) +APP1NOSAL=TRUE +APP1TARGET=$(TARGET) +APP1RPATH=BRAND +.IF "$(COM)"=="GCC" +APP1STDLIBS=-luuid +.ELSE +APP1STDLIBS=comsupp.lib +.ENDIF + +APP1STDLIBS+=$(SHELL32LIB)\ + $(OLE32LIB)\ + $(GDI32LIB)\ + $(OLEAUT32LIB)\ + $(COMDLG32LIB)\ + $(KERNEL32LIB)\ + $(OLEAUT32LIB) + +APP1NOSVRES=$(RES)$/$(TARGET).res + +.ENDIF # "$(LINK_SO)"=="TRUE" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/win32/source/applauncher/launcher.cxx b/desktop/win32/source/applauncher/launcher.cxx new file mode 100644 index 000000000000..a7a17b59a215 --- /dev/null +++ b/desktop/win32/source/applauncher/launcher.cxx @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "launcher.hxx" + + +#ifndef _WINDOWS_ +# define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +# include <windows.h> +# include <shellapi.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#endif + + +#include <stdlib.h> +#include <malloc.h> + + +#ifdef __MINGW32__ +extern "C" int APIENTRY WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) +#else +extern "C" int APIENTRY _tWinMain( HINSTANCE, HINSTANCE, LPTSTR, int ) +#endif +{ + // Retreive startup info + + STARTUPINFO aStartupInfo; + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof( aStartupInfo ); + GetStartupInfo( &aStartupInfo ); + + // Retrieve command line + + LPTSTR lpCommandLine = GetCommandLine(); + + LPTSTR *ppArguments = NULL; + int nArguments = 0; + + ppArguments = GetArgv( &nArguments ); + + { + lpCommandLine = (LPTSTR)_alloca( sizeof(_TCHAR) * (_tcslen(lpCommandLine) + _tcslen(APPLICATION_SWITCH) + 2) ); + + _tcscpy( lpCommandLine, GetCommandLine() ); + _tcscat( lpCommandLine, _T(" ") ); + _tcscat( lpCommandLine, APPLICATION_SWITCH ); + } + + + // Calculate application name + + TCHAR szApplicationName[MAX_PATH]; + TCHAR szDrive[MAX_PATH]; + TCHAR szDir[MAX_PATH]; + TCHAR szFileName[MAX_PATH]; + TCHAR szExt[MAX_PATH]; + + GetModuleFileName( NULL, szApplicationName, MAX_PATH ); + _tsplitpath( szApplicationName, szDrive, szDir, szFileName, szExt ); + _tmakepath( szApplicationName, szDrive, szDir, OFFICE_IMAGE_NAME, _T(".exe") ); + + PROCESS_INFORMATION aProcessInfo; + + BOOL fSuccess = CreateProcess( + szApplicationName, + lpCommandLine, + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &aStartupInfo, + &aProcessInfo ); + + if ( fSuccess ) + { + // Wait for soffice process to be terminated to allow other applications + // to wait for termination of started process + + WaitForSingleObject( aProcessInfo.hProcess, INFINITE ); + + CloseHandle( aProcessInfo.hProcess ); + CloseHandle( aProcessInfo.hThread ); + + return 0; + } + + DWORD dwError = GetLastError(); + + LPVOID lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&lpMsgBuf, + 0, + NULL + ); + + // Display the string. + MessageBox( NULL, (LPCTSTR)lpMsgBuf, NULL, MB_OK | MB_ICONERROR ); + + // Free the buffer. + LocalFree( lpMsgBuf ); + + return GetLastError(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/launcher.hxx b/desktop/win32/source/applauncher/launcher.hxx new file mode 100644 index 000000000000..46829d67037c --- /dev/null +++ b/desktop/win32/source/applauncher/launcher.hxx @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#pragma once +#ifndef __cplusplus +#error Need C++ to compile +#endif + +#ifndef _INC_TCHAR +# ifdef UNICODE +# define _UNICODE +# endif +# include <tchar.h> +#endif + +#ifdef UNICODE +# define GetArgv( pArgc ) CommandLineToArgvW( GetCommandLine(), pArgc ) +#else +# define GetArgv( pArgc ) (*pArgc = __argc, __argv) +#endif + +#define OFFICE_IMAGE_NAME _T("soffice") + +extern _TCHAR APPLICATION_SWITCH[]; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/makefile.mk b/desktop/win32/source/applauncher/makefile.mk new file mode 100755 index 000000000000..d08309bbed24 --- /dev/null +++ b/desktop/win32/source/applauncher/makefile.mk @@ -0,0 +1,150 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=applauncher +LIBTARGET=NO +TARGETTYPE=GUI +UWINAPILIB= + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +CDEFS+=-DUNICODE + + +OBJFILES= \ + $(OBJ)$/launcher.obj \ + $(OBJ)$/swriter.obj \ + $(OBJ)$/scalc.obj \ + $(OBJ)$/sdraw.obj \ + $(OBJ)$/simpress.obj \ + $(OBJ)$/sbase.obj \ + $(OBJ)$/smath.obj \ + $(OBJ)$/sweb.obj + +# SO launcher +.IF "$(LINK_SO)"=="TRUE" +.IF "$(BUILD_SPECIAL)"!="" +APP1DEPN= $(APP1RES) verinfo.rc +APP1TARGET=so$/swriter +APP1NOSAL=TRUE +APP1LINKRES=$(MISC)$/$(TARGET)1.res +APP1ICON=$(SOLARRESDIR)$/icons/so9_writer_app.ico +APP1OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/swriter.obj +APP1STDLIBS = $(SHELL32LIB) +APP1VERINFO=verinfo.rc +APP1PRODUCTDEF+=-DRES_APP_NAME=swriter + +APP2TARGET=so$/scalc +APP2NOSAL=TRUE +APP2LINKRES=$(MISC)$/$(TARGET)2.res +APP2ICON=$(SOLARRESDIR)$/icons/so9_calc_app.ico +APP2OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/scalc.obj +APP2STDLIBS = $(SHELL32LIB) +APP2DEPN=verinfo.rc +APP2VERINFO=verinfo.rc +APP2PRODUCTDEF+=-DRES_APP_NAME=scalc + +APP3TARGET=so$/sdraw +APP3NOSAL=TRUE +APP3LINKRES=$(MISC)$/$(TARGET)3.res +APP3ICON=$(SOLARRESDIR)$/icons/so9_draw_app.ico +APP3OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sdraw.obj +APP3STDLIBS = $(SHELL32LIB) +APP3DEPN=verinfo.rc +APP3VERINFO=verinfo.rc +APP3PRODUCTDEF+=-DRES_APP_NAME=sdraw + +APP4TARGET=so$/simpress +APP4NOSAL=TRUE +APP4LINKRES=$(MISC)$/$(TARGET)4.res +APP4ICON=$(SOLARRESDIR)$/icons/so9_impress_app.ico +APP4OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/simpress.obj +APP4STDLIBS = $(SHELL32LIB) +APP4DEPN=verinfo.rc +APP4VERINFO=verinfo.rc +APP4PRODUCTDEF+=-DRES_APP_NAME=simpress + +APP5TARGET=so$/sbase +APP5NOSAL=TRUE +APP5LINKRES=$(MISC)$/$(TARGET)5.res +APP5ICON=$(SOLARRESDIR)$/icons/so9_base_app.ico +APP5OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sbase.obj +APP5STDLIBS = $(SHELL32LIB) +APP5DEPN=verinfo.rc +APP5VERINFO=verinfo.rc +APP5PRODUCTDEF+=-DRES_APP_NAME=sbase + +APP6TARGET=so$/smath +APP6NOSAL=TRUE +APP6LINKRES=$(MISC)$/$(TARGET)6.res +APP6ICON=$(SOLARRESDIR)$/icons/so9_math_app.ico +APP6OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/smath.obj +APP6STDLIBS = $(SHELL32LIB) +APP6DEPN=verinfo.rc +APP6VERINFO=verinfo.rc +APP6PRODUCTDEF+=-DRES_APP_NAME=smath + +APP7TARGET=so$/sweb +APP7NOSAL=TRUE +APP7LINKRES=$(MISC)$/$(TARGET)7.res +APP7ICON=$(SOLARRESDIR)$/icons/so9_writer_app.ico +APP7OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sweb.obj +APP7STDLIBS = $(SHELL32LIB) +APP7DEPN=verinfo.rc +APP7VERINFO=verinfo.rc +APP7PRODUCTDEF+=-DRES_APP_NAME=sweb + + +.ENDIF # "$(BUILD_SPECIAL)"!="" +.ENDIF # "$(LINK_SO)"=="TRUE" + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/win32/source/applauncher/ooo/makefile.mk b/desktop/win32/source/applauncher/ooo/makefile.mk new file mode 100755 index 000000000000..02f240cce9e0 --- /dev/null +++ b/desktop/win32/source/applauncher/ooo/makefile.mk @@ -0,0 +1,130 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=applauncher +LIBTARGET=NO +TARGETTYPE=GUI +UWINAPILIB= + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +APP1TARGET=swriter +APP1DEPN=verinfo.rc +APP1VERINFO=verinfo.rc +APP1NOSAL=TRUE +APP1LINKRES=$(MISC)$/$(TARGET)1.res +APP1ICON=$(SOLARRESDIR)$/icons/ooo3_writer_app.ico +APP1OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/swriter.obj +APP1STDLIBS = $(SHELL32LIB) +APP1PRODUCTDEF+=-DRES_APP_NAME=$(APP1TARGET) + +APP2TARGET=scalc +APP2DEPN=verinfo.rc +APP2VERINFO=verinfo.rc +APP2NOSAL=TRUE +APP2LINKRES=$(MISC)$/$(TARGET)2.res +APP2ICON=$(SOLARRESDIR)$/icons/ooo3_calc_app.ico +APP2OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/scalc.obj +APP2STDLIBS = $(SHELL32LIB) +APP2PRODUCTDEF+=-DRES_APP_NAME=$(APP2TARGET) + +APP3TARGET=sdraw +APP3DEPN=verinfo.rc +APP3VERINFO=verinfo.rc +APP3NOSAL=TRUE +APP3LINKRES=$(MISC)$/$(TARGET)3.res +APP3ICON=$(SOLARRESDIR)$/icons/ooo3_draw_app.ico +APP3OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sdraw.obj +APP3STDLIBS = $(SHELL32LIB) +APP3PRODUCTDEF+=-DRES_APP_NAME=$(APP3TARGET) + +APP4TARGET=simpress +APP4DEPN=verinfo.rc +APP4VERINFO=verinfo.rc +APP4NOSAL=TRUE +APP4LINKRES=$(MISC)$/$(TARGET)4.res +APP4ICON=$(SOLARRESDIR)$/icons/ooo3_impress_app.ico +APP4OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/simpress.obj +APP4STDLIBS = $(SHELL32LIB) +APP4PRODUCTDEF+=-DRES_APP_NAME=$(APP4TARGET) + +APP5TARGET=smath +APP5DEPN=verinfo.rc +APP5VERINFO=verinfo.rc +APP5NOSAL=TRUE +APP5LINKRES=$(MISC)$/$(TARGET)5.res +APP5ICON=$(SOLARRESDIR)$/icons/ooo3_math_app.ico +APP5OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/smath.obj +APP5STDLIBS = $(SHELL32LIB) +APP5PRODUCTDEF+=-DRES_APP_NAME=$(APP5TARGET) + +APP6TARGET=sbase +APP6DEPN=verinfo.rc +APP6VERINFO=verinfo.rc +APP6NOSAL=TRUE +APP6LINKRES=$(MISC)$/$(TARGET)6.res +APP6ICON=$(SOLARRESDIR)$/icons/ooo3_base_app.ico +APP6OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sbase.obj +APP6STDLIBS = $(SHELL32LIB) +APP6PRODUCTDEF+=-DRES_APP_NAME=$(APP6TARGET) + +APP7TARGET=sweb +APP7DEPN=verinfo.rc +APP7VERINFO=verinfo.rc +APP7NOSAL=TRUE +APP7LINKRES=$(MISC)$/$(TARGET)7.res +APP7ICON=$(SOLARRESDIR)$/icons/ooo3_writer_app.ico +APP7OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sweb.obj +APP7STDLIBS = $(SHELL32LIB) +APP7PRODUCTDEF+=-DRES_APP_NAME=$(APP7TARGET) + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/win32/source/applauncher/ooo/verinfo.rc b/desktop/win32/source/applauncher/ooo/verinfo.rc new file mode 100755 index 000000000000..c5fcc811d0e2 --- /dev/null +++ b/desktop/win32/source/applauncher/ooo/verinfo.rc @@ -0,0 +1,71 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + *************************************************************************/ + +#define VER_FIRSTYEAR 2009 + +#include <windows.h> +#include "version.hrc" + +// ----------------------------------------------------------------------- +// version information +// ----------------------------------------------------------------------- + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION, SUBVERSION, VERVARIANT, VER_COUNT + PRODUCTVERSION VERSION, SUBVERSION, VERVARIANT, VER_COUNT + FILEFLAGSMASK 0x3F + FILEFLAGS +#if defined(DEBUG) + VS_FF_DEBUG | +#endif +#ifdef VER_PREL + VS_FF_PRERELEASE | +#endif + 0 + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_APP + { + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + // International StringTable + VALUE "CompanyName", "The Document Foundation\0" + VALUE "FileDescription", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\0" + VALUE "FileVersion", PPS(VER_LEVEL) "\0" + VALUE "ProductVersion", PPS(VER_LEVEL) "\0" + VALUE "OriginalFilename", PPS(RES_APP_NAME) ".exe\0" + VALUE "InternalName", PPS(RES_APP_NAME) "\0" + VALUE "LegalCopyright", S_CRIGHT " Oracle and/or its affiliates. All rights reserved.\0" + } + } + + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x0409, 1252 + } + } diff --git a/desktop/win32/source/applauncher/sbase.cxx b/desktop/win32/source/applauncher/sbase.cxx new file mode 100644 index 000000000000..9a1f31d3dce0 --- /dev/null +++ b/desktop/win32/source/applauncher/sbase.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-base" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/scalc.cxx b/desktop/win32/source/applauncher/scalc.cxx new file mode 100644 index 000000000000..ceca63e14450 --- /dev/null +++ b/desktop/win32/source/applauncher/scalc.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-calc" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/sdraw.cxx b/desktop/win32/source/applauncher/sdraw.cxx new file mode 100644 index 000000000000..034a7c4f949c --- /dev/null +++ b/desktop/win32/source/applauncher/sdraw.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-draw" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/simpress.cxx b/desktop/win32/source/applauncher/simpress.cxx new file mode 100644 index 000000000000..cd01d01b346d --- /dev/null +++ b/desktop/win32/source/applauncher/simpress.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-impress" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/smath.cxx b/desktop/win32/source/applauncher/smath.cxx new file mode 100644 index 000000000000..3e670cd8e692 --- /dev/null +++ b/desktop/win32/source/applauncher/smath.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-math" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/sweb.cxx b/desktop/win32/source/applauncher/sweb.cxx new file mode 100644 index 000000000000..1c2fd8eabd6c --- /dev/null +++ b/desktop/win32/source/applauncher/sweb.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-web" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/swriter.cxx b/desktop/win32/source/applauncher/swriter.cxx new file mode 100644 index 000000000000..1909cb97cded --- /dev/null +++ b/desktop/win32/source/applauncher/swriter.cxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-writer" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/verinfo.rc b/desktop/win32/source/applauncher/verinfo.rc new file mode 100755 index 000000000000..afb58f3a377c --- /dev/null +++ b/desktop/win32/source/applauncher/verinfo.rc @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + *************************************************************************/ + +#define VER_FIRSTYEAR 2009 + +#include <windows.h> +#include "version_so.hrc" + +// ----------------------------------------------------------------------- +// version information +// ----------------------------------------------------------------------- + +VS_VERSION_INFO versioninfo +#ifndef SUBVERSION + fileversion VERSION, 0, VERVARIANT, VER_COUNT + productversion VERSION, 0, VERVARIANT, VER_COUNT +#else + fileversion VERSION, SUBVERSION, VERVARIANT, VER_COUNT + productversion VERSION, SUBVERSION, VERVARIANT, VER_COUNT +#endif + fileflagsmask 0x3F + fileflags +#if defined(DEBUG) + VS_FF_DEBUG | +#endif +#ifdef VER_PREL + VS_FF_PRERELEASE | +#endif + 0 + fileos VOS_NT_WINDOWS32 + filetype VFT_APP + { + block "StringFileInfo" + { + block "040904E4" + { + // International StringTable + value "CompanyName", "The Document Foundation\0" + value "FileDescription", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\0" + value "FileVersion", PPS(VER_LEVEL) "\0" + value "ProductVersion", PPS(VER_LEVEL) "\0" + value "OriginalFilename", PPS(RES_APP_NAME) ".exe\0" + value "InternalName", PPS(RES_APP_NAME) "\0" + value "LegalCopyright", S_CRIGHT " Oracle and/or its affiliates. All rights reserved.\0" + } + } + + block "VarFileInfo" + { + value "Translation", 0x0409, 1252 + } + } diff --git a/desktop/win32/source/extendloaderenvironment.cxx b/desktop/win32/source/extendloaderenvironment.cxx new file mode 100644 index 000000000000..ee9de7f6099f --- /dev/null +++ b/desktop/win32/source/extendloaderenvironment.cxx @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "precompiled_desktop.hxx" +#include "sal/config.h" + +#include <cstddef> + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#include <shlwapi.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include "tools/pathutils.hxx" + +#include "extendloaderenvironment.hxx" + +namespace { + +void fail() { + LPWSTR buf = NULL; + FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, + GetLastError(), 0, reinterpret_cast< LPWSTR >(&buf), 0, NULL); + MessageBoxW(NULL, buf, NULL, MB_OK | MB_ICONERROR); + LocalFree(buf); + TerminateProcess(GetCurrentProcess(), 255); +} + +bool contains(WCHAR const * paths, WCHAR const * path, WCHAR const * pathEnd) { + WCHAR const * q = path; + for (WCHAR const * p = paths;; ++p) { + WCHAR c = *p; + switch (c) { + case L'\0': + return q == pathEnd; + case L';': + if (q == pathEnd) { + return true; + } + q = path; + break; + default: + if (q != NULL) { + if (q != pathEnd && *q == c) { + ++q; + } else { + q = NULL; + } + } + break; + } + } +} + +} + +namespace desktop_win32 { + +void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory) { + if (!GetModuleFileNameW(NULL, iniDirectory, MAX_PATH)) { + fail(); + } + WCHAR * iniDirEnd = tools::filename(iniDirectory); + WCHAR name[MAX_PATH + MY_LENGTH(L".bin")]; + // hopefully std::size_t is large enough to not overflow + WCHAR * nameEnd = name; + for (WCHAR * p = iniDirEnd; *p != L'\0'; ++p) { + *nameEnd++ = *p; + } + if (!(nameEnd - name >= 4 && nameEnd[-4] == L'.' && + (nameEnd[-3] == L'E' || nameEnd[-3] == L'e') && + (nameEnd[-2] == L'X' || nameEnd[-2] == L'x') && + (nameEnd[-1] == L'E' || nameEnd[-1] == L'e'))) + { + *nameEnd = L'.'; + nameEnd += 4; + } + nameEnd[-3] = 'b'; + nameEnd[-2] = 'i'; + nameEnd[-1] = 'n'; + tools::buildPath(binPath, iniDirectory, iniDirEnd, name, nameEnd - name); + *iniDirEnd = L'\0'; + WCHAR path[MAX_PATH]; + WCHAR * pathEnd = tools::buildPath( + path, iniDirectory, iniDirEnd, MY_STRING(L"..\\basis-link")); + if (pathEnd == NULL) { + fail(); + } + std::size_t const maxEnv = 32767; + WCHAR pad[2 * MAX_PATH + maxEnv]; + // hopefully std::size_t is large enough to not overflow + WCHAR * padEnd = NULL; + WCHAR env[maxEnv]; + DWORD n = GetEnvironmentVariableW(L"PATH", env, maxEnv); + if (n >= maxEnv || n == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND) { + fail(); + } + env[n] = L'\0'; + bool exclude1; + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + fail(); + } + // This path is only taken by testtool.exe in basis program directory; + // its PATH needs to include the brand program directory: + pathEnd = tools::buildPath( + path, iniDirectory, iniDirEnd, MY_STRING(L"..")); + if (pathEnd == NULL) { + fail(); + } + padEnd = tools::buildPath( + pad, path, pathEnd, MY_STRING(L"\\..\\program")); + if (padEnd == NULL) { + fail(); + } + exclude1 = contains(env, pad, padEnd); + } else { + exclude1 = true; + } + WCHAR * pad2 = exclude1 ? pad : padEnd + 1; + pathEnd = tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")); + if (pathEnd == NULL) { + fail(); + } + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL) { + fail(); + } + padEnd = tools::buildPath(pad2, path, pathEnd, MY_STRING(L"\\bin")); + if (padEnd == NULL) { + fail(); + } + bool exclude2 = contains(env, pad2, padEnd); + if (!(exclude1 && exclude2)) { + if (!(exclude1 || exclude2)) { + pad2[-1] = L';'; + } + WCHAR * p = exclude2 ? pad2 - 1 : padEnd; + if (n != 0) { + *p++ = L';'; + } + for (DWORD i = 0; i <= n; ++i) { + *p++ = env[i]; + } + if (!SetEnvironmentVariableW(L"PATH", pad)) { + fail(); + } + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/extendloaderenvironment.hxx b/desktop/win32/source/extendloaderenvironment.hxx new file mode 100644 index 000000000000..ace91b1a913d --- /dev/null +++ b/desktop/win32/source/extendloaderenvironment.hxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_WIN32_SOURCE_EXTENDLOADERENVIRONMENT_HXX +#define INCLUDED_DESKTOP_WIN32_SOURCE_EXTENDLOADERENVIRONMENT_HXX + +#include "sal/config.h" + +#include <cstddef> + +#include <tchar.h> + +#define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1) +#define MY_STRING(s) (s), MY_LENGTH(s) + +namespace desktop_win32 { + +inline WCHAR * commandLineAppend( + WCHAR * buffer, WCHAR const * text, std::size_t length) +{ + wcsncpy(buffer, text, length + 1); // trailing null + return buffer + length; +} + +inline WCHAR * commandLineAppend(WCHAR * buffer, WCHAR const * text) { + return commandLineAppend(buffer, text, wcslen(text)); +} + +inline WCHAR * commandLineAppendEncoded(WCHAR * buffer, WCHAR const * text) { + std::size_t n = 0; + for (;;) { + WCHAR c = *text++; + if (c == L'\0') { + break; + } else if (c == L'$') { + buffer = commandLineAppend(buffer, MY_STRING(L"\\$")); + n = 0; + } else if (c == L'\\') { + buffer = commandLineAppend(buffer, MY_STRING(L"\\\\")); + n += 2; + } else { + *buffer++ = c; + n = 0; + } + } + // The command line will continue with a double quote, so double any + // preceding backslashes as required by Windows: + for (std::size_t i = 0; i < n; ++i) { + *buffer++ = L'\\'; + } + *buffer = L'\0'; + return buffer; +} + +// Set the PATH environment variable in the current (loader) process, so that a +// following CreateProcess has the necessary environment: +// @param binPath +// Must point to an array of size at least MAX_PATH. Is filled with the null +// terminated full path to the "bin" file corresponding to the current +// executable. +// @param iniDirectory +// Must point to an array of size at least MAX_PATH. Is filled with the null +// terminated full directory path (ending in "\") to the "ini" file +// corresponding to the current executable. +void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/guiloader/genericloader.cxx b/desktop/win32/source/guiloader/genericloader.cxx new file mode 100644 index 000000000000..1d2075a65bc8 --- /dev/null +++ b/desktop/win32/source/guiloader/genericloader.cxx @@ -0,0 +1,178 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" +#define UNICODE +#define _UNICODE + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#include <shellapi.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include <tchar.h> + +#include <malloc.h> +#include <string.h> +#include <stdlib.h> +#include <systools/win32/uwinapi.h> + +#include "tools/pathutils.hxx" +#include "../extendloaderenvironment.hxx" + +//--------------------------------------------------------------------------- + +static int GenericMain() +{ + TCHAR szTargetFileName[MAX_PATH]; + TCHAR szIniDirectory[MAX_PATH]; + STARTUPINFO aStartupInfo; + + desktop_win32::extendLoaderEnvironment(szTargetFileName, szIniDirectory); + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof(aStartupInfo); + + GetStartupInfo( &aStartupInfo ); + + DWORD dwExitCode = (DWORD)-1; + + PROCESS_INFORMATION aProcessInfo; + + size_t iniDirLen = wcslen(szIniDirectory); + WCHAR cwd[MAX_PATH]; + DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd); + if (cwdLen >= MAX_PATH) { + cwdLen = 0; + } + WCHAR redirect[MAX_PATH]; + DWORD dummy; + bool hasRedirect = + tools::buildPath( + redirect, szIniDirectory, szIniDirectory + iniDirLen, + MY_STRING(L"redirect.ini")) != NULL && + (GetBinaryType(redirect, &dummy) || // cheaper check for file existence? + GetLastError() != ERROR_FILE_NOT_FOUND); + LPTSTR cl1 = GetCommandLine(); + WCHAR * cl2 = new WCHAR[ + wcslen(cl1) + + (hasRedirect + ? (MY_LENGTH(L" \"-env:INIFILENAME=vnd.sun.star.pathname:") + + iniDirLen + MY_LENGTH(L"redirect.ini\"")) + : 0) + + MY_LENGTH(L" \"-env:OOO_CWD=2") + 4 * cwdLen + MY_LENGTH(L"\"") + 1]; + // 4 * cwdLen: each char preceded by backslash, each trailing backslash + // doubled + WCHAR * p = desktop_win32::commandLineAppend(cl2, cl1); + if (hasRedirect) { + p = desktop_win32::commandLineAppend( + p, MY_STRING(L" \"-env:INIFILENAME=vnd.sun.star.pathname:")); + p = desktop_win32::commandLineAppend(p, szIniDirectory); + p = desktop_win32::commandLineAppend(p, MY_STRING(L"redirect.ini\"")); + } + p = desktop_win32::commandLineAppend(p, MY_STRING(L" \"-env:OOO_CWD=")); + if (cwdLen == 0) { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"0")); + } else { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"2")); + p = desktop_win32::commandLineAppendEncoded(p, cwd); + } + desktop_win32::commandLineAppend(p, MY_STRING(L"\"")); + + BOOL fSuccess = CreateProcess( + szTargetFileName, + cl2, + NULL, + NULL, + TRUE, + 0, + NULL, + szIniDirectory, + &aStartupInfo, + &aProcessInfo ); + + delete[] cl2; + + if ( fSuccess ) + { + DWORD dwWaitResult; + + do + { + // On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWidth" so we have to do so + // as if we where processing any messages + + dwWaitResult = MsgWaitForMultipleObjects( 1, &aProcessInfo.hProcess, FALSE, INFINITE, QS_ALLEVENTS ); + + if ( WAIT_OBJECT_0 + 1 == dwWaitResult ) + { + MSG msg; + + PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); + } + } while ( WAIT_OBJECT_0 + 1 == dwWaitResult ); + + dwExitCode = 0; + GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode ); + + CloseHandle( aProcessInfo.hProcess ); + CloseHandle( aProcessInfo.hThread ); + } + + return dwExitCode; +} + +//--------------------------------------------------------------------------- + +#ifdef __MINGW32__ +int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) +#else +int WINAPI _tWinMain( HINSTANCE, HINSTANCE, LPTSTR, int ) +#endif +{ + return GenericMain(); +} + +//--------------------------------------------------------------------------- + +#ifdef __MINGW32__ +int __cdecl main() +#else +int __cdecl _tmain() +#endif +{ + return GenericMain(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/guiloader/makefile.mk b/desktop/win32/source/guiloader/makefile.mk new file mode 100755 index 000000000000..7912471fba13 --- /dev/null +++ b/desktop/win32/source/guiloader/makefile.mk @@ -0,0 +1,66 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=guiloader +LIBTARGET=NO +TARGETTYPE=GUI +UWINAPILIB= + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +APP1TARGET=guiloader +APP1NOSAL=TRUE +APP1ICON=$(SOLARRESDIR)$/icons/ooo-main-app.ico +APP1OBJS=\ + $(OBJ)$/extendloaderenvironment.obj \ + $(OBJ)$/genericloader.obj \ + $(SOLARLIBDIR)$/pathutils-obj.obj +STDLIB1=$(SHLWAPILIB) + +.IF "$(LINK_SO)"=="TRUE" +APP2TARGET=so$/guiloader +APP2NOSAL=TRUE +APP2ICON=$(SOLARRESDIR)$/icons/so9_main_app.ico +APP2OBJS=\ + $(OBJ)$/extendloaderenvironment.obj \ + $(OBJ)$/genericloader.obj \ + $(SOLARLIBDIR)$/pathutils-obj.obj +STDLIB2=$(SHLWAPILIB) +.ENDIF # "$(LINK_SO)"=="TRUE" + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/win32/source/guistdio/guistdio.cxx b/desktop/win32/source/guistdio/guistdio.cxx new file mode 100644 index 000000000000..1c12089818f0 --- /dev/null +++ b/desktop/win32/source/guistdio/guistdio.cxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "precompiled_desktop.hxx" + +#include "guistdio.inc" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/guistdio/guistdio.inc b/desktop/win32/source/guistdio/guistdio.inc new file mode 100755 index 000000000000..05d462d23197 --- /dev/null +++ b/desktop/win32/source/guistdio/guistdio.inc @@ -0,0 +1,454 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#define UNICODE +#define WIN32_LEAN_AND_MEAN +#ifdef _MSC_VER +#pragma warning(push,1) // disable warnings within system headers +#endif +#include <windows.h> +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#define _UNICODE +#include <tchar.h> + +#include <string.h> +#include <stdlib.h> +#include <systools/win32/uwinapi.h> + +#include <stdio.h> +#include <sal/macros.h> + +#ifdef UNOPKG + +DWORD passOutputToConsole(HANDLE readPipe, HANDLE console) +{ + BYTE aBuffer[1024]; + DWORD dwRead = 0; + HANDLE hReadPipe = readPipe; + BOOL fSuccess; + DWORD dwWritten; + + //Indicates that we read an odd number of bytes. That is, we only read half of the last + //wchar_t + bool bIncompleteWchar = false; + //fprintf, fwprintf will both send char data without the terminating zero. + //fwprintf converts the unicode string first. + //We expect here to receive unicode without the terminating zero. + //unopkg and the extension manager code MUST + //use dp_misc::writeConsole instead of using fprintf, etc. + + DWORD dwToRead = sizeof(aBuffer); + BYTE * pBuffer = aBuffer; + while ( ReadFile( hReadPipe, pBuffer, dwToRead, &dwRead, NULL ) ) + { + //If the previous ReadFile call read an odd number of bytes, then the last one was + //put at the front of the buffer. We increase the number of read bytes by one to reflect + //that one byte. + if (bIncompleteWchar) + dwRead++; + //We must make sure that only complete wchar_t|s are written. WriteConsolse takes + //the number of wchar_t|s as argument. ReadFile, however, reads bytes. + bIncompleteWchar = dwRead % 2 ? true : false; + if (bIncompleteWchar) + { + //To test this case, give aBuffer a small odd size, e.g. aBuffer[3] + //The last byte, which is the incomplete wchar_t (half of it), will not be written. + fSuccess = WriteConsoleW( console, aBuffer, + (dwRead - 1) / 2, &dwWritten, NULL ); + + //Move the last byte to the front of the buffer, so that it is the start of the + //next string + aBuffer[0] = aBuffer[dwRead - 1]; + + //Make sure that ReadFile does not overwrite the first byte the next time + dwToRead = sizeof(aBuffer) - 1; + pBuffer = aBuffer + 1; + + } + else + { //We have read an even number of bytes. Therefore, we do not put the last incomplete + //wchar_t at the front of the buffer. We will use the complete buffer the next time + //when ReadFile is called. + dwToRead = sizeof(aBuffer); + pBuffer = aBuffer; + fSuccess = WriteConsoleW( console, + aBuffer, dwRead / 2, &dwWritten, NULL ); + } + } + + return 0; +} + +#endif + +#ifdef UNOPKG +DWORD WINAPI OutputThread( LPVOID pParam ) +{ + return passOutputToConsole((HANDLE)pParam, GetStdHandle( STD_OUTPUT_HANDLE )); +} + +#else +DWORD WINAPI OutputThread( LPVOID pParam ) +{ + BYTE aBuffer[256]; + DWORD dwRead = 0; + HANDLE hReadPipe = (HANDLE)pParam; + while ( ReadFile( hReadPipe, &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) + { + BOOL fSuccess; + DWORD dwWritten; + + fSuccess = WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), aBuffer, dwRead, &dwWritten, NULL ); + } + + return 0; +} +#endif +//--------------------------------------------------------------------------- +// Thread that reads from child process standard error pipe +//--------------------------------------------------------------------------- + +#ifdef UNOPKG +DWORD WINAPI ErrorThread( LPVOID pParam ) +{ + return passOutputToConsole((HANDLE)pParam, GetStdHandle( STD_ERROR_HANDLE )); +} + +#else +DWORD WINAPI ErrorThread( LPVOID pParam ) +{ + BYTE aBuffer[256]; + DWORD dwRead = 0; + HANDLE hReadPipe = (HANDLE)pParam; + + while ( ReadFile( hReadPipe, &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) + { + BOOL fSuccess; + DWORD dwWritten; + + fSuccess = WriteFile( GetStdHandle( STD_ERROR_HANDLE ), aBuffer, dwRead, &dwWritten, NULL ); + } + + return 0; +} +#endif +//--------------------------------------------------------------------------- +// Thread that writes to child process standard input pipe +//--------------------------------------------------------------------------- +#ifdef UNOPKG + +DWORD WINAPI InputThread( LPVOID pParam ) +{ + DWORD dwRead = 0; + HANDLE hWritePipe = (HANDLE)pParam; + + //We need to read in the complete input until we encounter a new line before + //converting to Unicode. This is necessary because the input string can use + //characters of one, two, and more bytes. If the last character is not + //complete, then it will not be converted properly. + + //Find out how a new line (0xd 0xa) looks like with the used code page. + //Characters may have one or multiple bytes and different byte ordering + //can be used (little and big endian); + int cNewLine = WideCharToMultiByte( + GetConsoleCP(), 0, L"\r\n", 2, NULL, 0, NULL, NULL); + char * mbBuff = new char[cNewLine]; + WideCharToMultiByte( + GetConsoleCP(), 0, L"\r\n", 2, mbBuff, cNewLine, NULL, NULL); + + const size_t dwBufferSize = 256; + char* readBuf = (char*) malloc(dwBufferSize); + int readAll = 0; + size_t curBufSize = dwBufferSize; + + while ( ReadFile( GetStdHandle( STD_INPUT_HANDLE ), + readBuf + readAll, + curBufSize - readAll, &dwRead, NULL ) ) + { + readAll += dwRead; + int lastBufSize = curBufSize; + //Grow the buffer if necessary + if (readAll > curBufSize * 0.7) + { + curBufSize *= 2; + readBuf = (char *) realloc(readBuf, curBufSize); + } + + //If the buffer was filled completely then + //there could be more input coming. But if we read from the console + //and the console input fits exactly in the buffer, then the next + //ReadFile would block until the users presses return, etc. + //Therefor we check if last character is a new line. + //To test this, set dwBufferSize to 4 and enter "no". This should produce + //4 bytes with most code pages. + if ( readAll == lastBufSize + && memcmp(readBuf + lastBufSize - cNewLine, mbBuff, cNewLine) != 0) + { + //The buffer was completely filled and the last byte(s) are no + //new line, so there is more to come. + continue; + } + //Obtain the size of the buffer for the converted string. + int sizeWBuf = MultiByteToWideChar( + GetConsoleCP(), MB_PRECOMPOSED, readBuf, readAll, NULL, 0); + + wchar_t * wideBuf = new wchar_t[sizeWBuf]; + + //Do the conversion. + MultiByteToWideChar( + GetConsoleCP(), MB_PRECOMPOSED, readBuf, readAll, wideBuf, sizeWBuf); + + BOOL fSuccess; + DWORD dwWritten; + fSuccess = WriteFile( hWritePipe, wideBuf, sizeWBuf * 2, &dwWritten, NULL ); + delete[] wideBuf; + readAll = 0; + } + delete[] mbBuff; + free(readBuf); + return 0; +} +#else +DWORD WINAPI InputThread( LPVOID pParam ) +{ + BYTE aBuffer[256]; + DWORD dwRead = 0; + HANDLE hWritePipe = (HANDLE)pParam; + + while ( ReadFile( GetStdHandle( STD_INPUT_HANDLE ), &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) + { + BOOL fSuccess; + DWORD dwWritten; + + fSuccess = WriteFile( hWritePipe, aBuffer, dwRead, &dwWritten, NULL ); + } + + return 0; +} +#endif + +//--------------------------------------------------------------------------- +// Thread that waits until child process reached input idle +//--------------------------------------------------------------------------- + +DWORD WINAPI WaitForUIThread( LPVOID pParam ) +{ + HANDLE hProcess = (HANDLE)pParam; + +#ifndef UNOPKG + if ( !_tgetenv( TEXT("UNOPKG") ) ) + WaitForInputIdle( hProcess, INFINITE ); +#endif + + return 0; +} + + +//--------------------------------------------------------------------------- +// Ctrl-Break handler that terminates the child process if Ctrl-C was pressed +//--------------------------------------------------------------------------- + +HANDLE hTargetProcess = INVALID_HANDLE_VALUE; + +BOOL WINAPI CtrlBreakHandler( + DWORD // control signal type +) +{ + TerminateProcess( hTargetProcess, 255 ); + return TRUE; +} + + +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- + +#ifdef __MINGW32__ +int main( int, char ** ) +#else +int _tmain( int, _TCHAR ** ) +#endif +{ + TCHAR szTargetFileName[MAX_PATH] = TEXT(""); + STARTUPINFO aStartupInfo; + PROCESS_INFORMATION aProcessInfo; + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof(aStartupInfo); + aStartupInfo.dwFlags = STARTF_USESTDHANDLES; + + // Create an output pipe where the write end is inheritable + + HANDLE hOutputRead, hOutputWrite; + + if ( CreatePipe( &hOutputRead, &hOutputWrite, NULL, 0 ) ) + { + HANDLE hTemp; + + DuplicateHandle( GetCurrentProcess(), hOutputWrite, GetCurrentProcess(), &hTemp, 0, TRUE, DUPLICATE_SAME_ACCESS ); + CloseHandle( hOutputWrite ); + hOutputWrite = hTemp; + + aStartupInfo.hStdOutput = hOutputWrite; + } + + // Create an error pipe where the write end is inheritable + + HANDLE hErrorRead, hErrorWrite; + + if ( CreatePipe( &hErrorRead, &hErrorWrite, NULL, 0 ) ) + { + HANDLE hTemp; + + DuplicateHandle( GetCurrentProcess(), hErrorWrite, GetCurrentProcess(), &hTemp, 0, TRUE, DUPLICATE_SAME_ACCESS ); + CloseHandle( hErrorWrite ); + hErrorWrite = hTemp; + + aStartupInfo.hStdError = hErrorWrite; + } + + // Create an input pipe where the read end is inheritable + + HANDLE hInputRead, hInputWrite; + + if ( CreatePipe( &hInputRead, &hInputWrite, NULL, 0 ) ) + { + HANDLE hTemp; + + DuplicateHandle( GetCurrentProcess(), hInputRead, GetCurrentProcess(), &hTemp, 0, TRUE, DUPLICATE_SAME_ACCESS ); + CloseHandle( hInputRead ); + hInputRead = hTemp; + + aStartupInfo.hStdInput = hInputRead; + } + + // Get image path with same name but with .exe extension + + TCHAR szModuleFileName[MAX_PATH]; + + GetModuleFileName( NULL, szModuleFileName, MAX_PATH ); + _TCHAR *lpLastDot = _tcsrchr( szModuleFileName, '.' ); + if ( lpLastDot && 0 == _tcsicmp( lpLastDot, _T(".COM") ) ) + { + size_t len = lpLastDot - szModuleFileName; + _tcsncpy( szTargetFileName, szModuleFileName, len ); + _tcsncpy( szTargetFileName + len, _T(".EXE"), SAL_N_ELEMENTS(szTargetFileName) - len ); + } + + // Create process with same command line, environment and stdio handles which + // are directed to the created pipes + + BOOL fSuccess = CreateProcess( + szTargetFileName, + GetCommandLine(), + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &aStartupInfo, + &aProcessInfo ); + + if ( fSuccess ) + { + // These pipe ends are inherited by the child process and no longer used + CloseHandle( hOutputWrite ); + CloseHandle( hErrorWrite ); + CloseHandle( hInputRead ); + + // Set the Ctrl-Break handler + hTargetProcess = aProcessInfo.hProcess; + SetConsoleCtrlHandler( CtrlBreakHandler, TRUE ); + + // Create threads that redirect remote pipe io to current process's console stdio + + DWORD dwOutputThreadId, dwErrorThreadId, dwInputThreadId; + + HANDLE hOutputThread = CreateThread( NULL, 0, OutputThread, (LPVOID)hOutputRead, 0, &dwOutputThreadId ); + HANDLE hErrorThread = CreateThread( NULL, 0, OutputThread, (LPVOID)hErrorRead, 0, &dwErrorThreadId ); + HANDLE hInputThread = CreateThread( NULL, 0, InputThread, (LPVOID)hInputWrite, 0, &dwInputThreadId ); + + // Create thread that wait until child process entered input idle + + DWORD dwWaitForUIThreadId; + HANDLE hWaitForUIThread = CreateThread( NULL, 0, WaitForUIThread, (LPVOID)aProcessInfo.hProcess, 0, &dwWaitForUIThreadId ); + + DWORD dwWaitResult; + HANDLE hObjects[] = + { + hTargetProcess, + hWaitForUIThread, + hOutputThread, + hErrorThread + }; + + #ifdef UNOPKG + dwWaitResult = WaitForMultipleObjects( SAL_N_ELEMENTS(hObjects), hObjects, TRUE, INFINITE ); + #else + bool bDetach = false; + int nOpenPipes = 2; + do + { + dwWaitResult = WaitForMultipleObjects( SAL_N_ELEMENTS(hObjects), hObjects, FALSE, INFINITE ); + + switch ( dwWaitResult ) + { + case WAIT_OBJECT_0: // The child process has terminated + case WAIT_OBJECT_0 + 1: // The child process entered input idle + bDetach = true; + break; + case WAIT_OBJECT_0 + 2: // The remote end of stdout pipe was closed + case WAIT_OBJECT_0 + 3: // The remote end of stderr pipe was closed + bDetach = --nOpenPipes <= 0; + break; + default: // Something went wrong + bDetach = true; + break; + } + } while( !bDetach ); + +#endif + + CloseHandle( hOutputThread ); + CloseHandle( hErrorThread ); + CloseHandle( hInputThread ); + CloseHandle( hWaitForUIThread ); + + DWORD dwExitCode = 0; + GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode ); + CloseHandle( aProcessInfo.hProcess ); + CloseHandle( aProcessInfo.hThread ); + + return dwExitCode; + } + + return -1; +} diff --git a/desktop/win32/source/guistdio/makefile.mk b/desktop/win32/source/guistdio/makefile.mk new file mode 100755 index 000000000000..660a48bcdca9 --- /dev/null +++ b/desktop/win32/source/guistdio/makefile.mk @@ -0,0 +1,58 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=guistdio +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +TARGETTYPE=CUI +UWINAPILIB= + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +CFLAGS+= $(LFS_CFLAGS) +CXXFLAGS+= $(LFS_CFLAGS) + +# --- Files -------------------------------------------------------- + +OBJFILES=$(APP1OBJS) $(APP2OBJS) + +APP1NOSAL=TRUE +APP1OBJS=$(OBJ)$/guistdio.obj +APP1TARGET=$(TARGET) + +APP2NOSAL=TRUE +APP2OBJS=$(OBJ)$/unopkgio.obj +APP2TARGET=unopkgio + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/win32/source/guistdio/unopkgio.cxx b/desktop/win32/source/guistdio/unopkgio.cxx new file mode 100644 index 000000000000..8790cedfe98f --- /dev/null +++ b/desktop/win32/source/guistdio/unopkgio.cxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "precompiled_desktop.hxx" + +#define UNOPKG +#include "guistdio.inc" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/lwrapa.cxx b/desktop/win32/source/lwrapa.cxx new file mode 100644 index 000000000000..eba3059da517 --- /dev/null +++ b/desktop/win32/source/lwrapa.cxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" +#define LOCAL +#include "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/lwrapw.cxx b/desktop/win32/source/lwrapw.cxx new file mode 100644 index 000000000000..90a8b5d88f55 --- /dev/null +++ b/desktop/win32/source/lwrapw.cxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" +#define LOCAL +#define UNICODE +#include "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/main.h b/desktop/win32/source/main.h new file mode 100755 index 000000000000..9e3039da1884 --- /dev/null +++ b/desktop/win32/source/main.h @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +int MainA(); +int MainW(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/makefile.mk b/desktop/win32/source/makefile.mk new file mode 100755 index 000000000000..564ba319eb56 --- /dev/null +++ b/desktop/win32/source/makefile.mk @@ -0,0 +1,63 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=sowrap +LIBTARGET=NO +AUTOSEG=true + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +UWINAPILIB = + +# --- Files -------------------------------------------------------- + +OBJFILES = \ + $(OBJ)$/wrappera.obj \ + $(OBJ)$/wrapperw.obj \ + $(OBJ)$/lwrapa.obj \ + $(OBJ)$/lwrapw.obj \ + $(OBJ)$/rwrapa.obj \ + $(OBJ)$/rwrapw.obj \ + $(OBJ)$/sowrapper.obj \ + $(OBJ)$/extendloaderenvironment.obj \ + $(OBJ)$/unoinfo.obj + +APP1TARGET = unoinfo +APP1OBJS = $(OBJ)$/unoinfo.obj $(SOLARLIBDIR)$/pathutils-obj.obj +APP1STDLIBS = +APP1RPATH = BRAND + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/win32/source/officeloader/makefile.mk b/desktop/win32/source/officeloader/makefile.mk new file mode 100755 index 000000000000..5609dea25085 --- /dev/null +++ b/desktop/win32/source/officeloader/makefile.mk @@ -0,0 +1,45 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=officeloader +LIBTARGET=NO + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +OBJFILES = \ + $(OBJ)$/officeloader.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/win32/source/officeloader/officeloader.cxx b/desktop/win32/source/officeloader/officeloader.cxx new file mode 100644 index 000000000000..7a08d7ee64c7 --- /dev/null +++ b/desktop/win32/source/officeloader/officeloader.cxx @@ -0,0 +1,430 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" +#define UNICODE +#define _UNICODE + +#include <cstddef> + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#include <shellapi.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include <tchar.h> + +#include <malloc.h> +#include <string.h> +#include <stdlib.h> +#include <systools/win32/uwinapi.h> + +#include "rtl/string.h" +#include <sal/macros.h> + +#include "../../../source/inc/exithelper.hxx" +#include "../extendloaderenvironment.hxx" + +#define PIPE_PREFIX TEXT("\\\\.\\pipe\\OSL_PIPE_") +#define PIPE_POSTFIX TEXT("_SingleOfficeIPC_") +#define PIPE_TERMINATION_SEQUENCE "InternalIPC::ProcessingDone" + +BOOL WINAPI ConvertSidToStringSid( PSID pSid, LPTSTR* StringSid ) +{ + PSID_IDENTIFIER_AUTHORITY psia; + DWORD dwSubAuthorities; + DWORD dwSidRev=SID_REVISION; + DWORD dwCounter; + DWORD dwSidSize; + + // Validate the binary SID. + + if(!IsValidSid(pSid)) return FALSE; + + // Get the identifier authority value from the SID. + + psia = GetSidIdentifierAuthority(pSid); + + // Get the number of subauthorities in the SID. + + dwSubAuthorities = *GetSidSubAuthorityCount(pSid); + + // Compute the buffer length. + // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL + + dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR); + + *StringSid = (LPTSTR)LocalAlloc( LMEM_FIXED, dwSidSize ); + + // Add 'S' prefix and revision number to the string. + + dwSidSize=wsprintf(*StringSid, TEXT("S-%lu-"), dwSidRev ); + + // Add a SID identifier authority to the string. + + if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) + { + dwSidSize+=wsprintf(*StringSid + lstrlen(*StringSid), + TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), + (USHORT)psia->Value[0], + (USHORT)psia->Value[1], + (USHORT)psia->Value[2], + (USHORT)psia->Value[3], + (USHORT)psia->Value[4], + (USHORT)psia->Value[5]); + } + else + { + dwSidSize+=wsprintf(*StringSid + lstrlen(*StringSid), + TEXT("%lu"), + (ULONG)(psia->Value[5] ) + + (ULONG)(psia->Value[4] << 8) + + (ULONG)(psia->Value[3] << 16) + + (ULONG)(psia->Value[2] << 24) ); + } + + // Add SID subauthorities to the string. + for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++) + { + dwSidSize+=wsprintf(*StringSid + dwSidSize, TEXT("-%lu"), + *GetSidSubAuthority(pSid, dwCounter) ); + } + + return TRUE; +} + + +//--------------------------------------------------------------------------- + +static LPTSTR *GetCommandArgs( int *pArgc ) +{ +#ifdef UNICODE + return CommandLineToArgvW( GetCommandLineW(), pArgc ); +#else + *pArgc = __argc; + return __argv; +#endif +} + +//--------------------------------------------------------------------------- + +namespace { + +bool writeArgument(HANDLE pipe, char prefix, WCHAR const * argument) { + CHAR szBuffer[4096]; + int n = WideCharToMultiByte( + CP_UTF8, 0, argument, -1, szBuffer, sizeof (szBuffer), NULL, NULL); + char b[1 + 2 * ((sizeof szBuffer) - 1)]; // hopefully does not overflow + b[0] = prefix; + char * p = b + 1; + for (int i = 0; i < n - 1; ++i) { // cannot underflow (n >= 0) + char c = szBuffer[i]; + switch (c) { + case '\0': + *p++ = '\\'; + *p++ = '0'; + break; + case ',': + *p++ = '\\'; + *p++ = ','; + break; + case '\\': + *p++ = '\\'; + *p++ = '\\'; + break; + default: + *p++ = c; + break; + } + } + DWORD w; + return WriteFile(pipe, b, p - b, &w, NULL); +} + +} + +#ifdef __MINGW32__ +int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int ) +#else +int WINAPI _tWinMain( HINSTANCE, HINSTANCE, LPTSTR, int ) +#endif +{ + TCHAR szTargetFileName[MAX_PATH] = TEXT(""); + TCHAR szIniDirectory[MAX_PATH]; + TCHAR szPerfTuneIniFile[MAX_PATH] = TEXT(""); + STARTUPINFO aStartupInfo; + + desktop_win32::extendLoaderEnvironment(szTargetFileName, szIniDirectory); + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof(aStartupInfo); + + GetStartupInfo( &aStartupInfo ); + // Get image path with same name but with .bin extension + + TCHAR szModuleFileName[MAX_PATH]; + + GetModuleFileName( NULL, szModuleFileName, MAX_PATH ); + _TCHAR *lpLastSlash = _tcsrchr( szModuleFileName, '\\' ); + if ( lpLastSlash ) + { + size_t len = lpLastSlash - szModuleFileName + 1; + _tcsncpy( szPerfTuneIniFile, szModuleFileName, len ); + _tcsncpy( szPerfTuneIniFile + len, _T("perftune.ini"), SAL_N_ELEMENTS(szPerfTuneIniFile) - len ); + } + + // Create process with same command line, environment and stdio handles which + // are directed to the created pipes + + DWORD dwExitCode = (DWORD)-1; + + BOOL fSuccess = FALSE; + LPTSTR lpCommandLine = NULL; + int argc = 0; + LPTSTR * argv = NULL; + bool bFirst = true; + WCHAR cwd[MAX_PATH]; + DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd); + if (cwdLen >= MAX_PATH) { + cwdLen = 0; + } + + do + { + TCHAR szKey[32]; + + GetPrivateProfileString( + TEXT("PerformanceTuning"), + TEXT("FastPipeCommunication"), + TEXT("0"), + szKey, + SAL_N_ELEMENTS(szKey), + szPerfTuneIniFile + ); + + if ( 0 == _tcscmp( szKey, TEXT("1") ) ) + { + HANDLE hProcessToken; + + if ( OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hProcessToken ) ) + { + TCHAR szPipeName[4096]; + + + DWORD dwTokenLength = 0; + + + fSuccess = GetTokenInformation( hProcessToken, TokenUser, NULL, dwTokenLength, &dwTokenLength ); + + PVOID pTokenInfo = _alloca(dwTokenLength); + fSuccess = GetTokenInformation( hProcessToken, TokenUser, pTokenInfo, dwTokenLength, &dwTokenLength ); + CloseHandle( hProcessToken ); + + PSID pSid = ((PTOKEN_USER)pTokenInfo)->User.Sid; + LPTSTR szUserIdent = NULL; + TCHAR szSUPD[11] = TEXT("0"); + + fSuccess = ConvertSidToStringSid( pSid, &szUserIdent ); + + _tcsncpy( szPipeName, PIPE_PREFIX, SAL_N_ELEMENTS(szPipeName) ); + _tcsncat( szPipeName, szUserIdent, SAL_N_ELEMENTS(szPipeName) - _tcslen(szPipeName) - 1 ); + _tcsncat( szPipeName, PIPE_POSTFIX, SAL_N_ELEMENTS(szPipeName) - _tcslen(szPipeName) - 1 ); + _tcsncat( szPipeName, _ultot( SUPD, szSUPD, 10), SAL_N_ELEMENTS(szPipeName) - _tcslen(szPipeName) - 1 ); + + LocalFree( szUserIdent ); + + HANDLE hPipe = CreateFile( + szPipeName, + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if ( INVALID_HANDLE_VALUE != hPipe ) + { + DWORD dwBytesWritten; + int argc = 0; + LPWSTR *argv = CommandLineToArgvW( GetCommandLine(), &argc ); + + fSuccess = WriteFile( hPipe, RTL_CONSTASCII_STRINGPARAM("InternalIPC::Arguments"), &dwBytesWritten, NULL ); + if (fSuccess) { + if (cwdLen > 0) { + fSuccess = writeArgument(hPipe, '2', cwd); + } else { + fSuccess = WriteFile( + hPipe, RTL_CONSTASCII_STRINGPARAM("0"), + &dwBytesWritten, NULL); + } + } + for ( int argn = 1; fSuccess && argn < argc; argn++ ) + { + fSuccess = writeArgument(hPipe, ',', argv[argn]); + } + + if ( fSuccess ) + { + fSuccess = WriteFile( hPipe, "", 1, &dwBytesWritten, NULL ); + if ( fSuccess ) + { + DWORD dwBytesRead = 0; + char *pBuffer = (char *)_alloca( sizeof(PIPE_TERMINATION_SEQUENCE) ); + fSuccess = ReadFile( hPipe, pBuffer, sizeof(PIPE_TERMINATION_SEQUENCE) - 1, &dwBytesRead, NULL ); + if ( fSuccess ) + { + pBuffer[dwBytesRead] = 0; + if ( 0 != strcmp( PIPE_TERMINATION_SEQUENCE, pBuffer ) ) + fSuccess = FALSE; + } + } + } + + CloseHandle( hPipe ); + + return fSuccess ? 0 : -1; + } + + } + } + + if ( bFirst ) { + argv = GetCommandArgs(&argc); + std::size_t n = wcslen(argv[0]) + 2; + for (int i = 1; i < argc; ++i) { + n += wcslen(argv[i]) + 3; + } + n += MY_LENGTH(L" \"-env:OOO_CWD=2") + 4 * cwdLen + + MY_LENGTH(L"\"") + 1; + // 4 * cwdLen: each char preceded by backslash, each trailing + // backslash doubled + lpCommandLine = new WCHAR[n]; + } + WCHAR * p = desktop_win32::commandLineAppend( + lpCommandLine, MY_STRING(L"\"")); + p = desktop_win32::commandLineAppend(p, argv[0]); + for (int i = 1; i < argc; ++i) { + if (bFirst || ::desktop::ExitHelper::E_NORMAL_RESTART == dwExitCode || wcsncmp(argv[i], MY_STRING(L"-env:")) == 0) { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"\" \"")); + p = desktop_win32::commandLineAppend(p, argv[i]); + } + } + + p = desktop_win32::commandLineAppend( + p, MY_STRING(L"\" \"-env:OOO_CWD=")); + if (cwdLen == 0) { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"0")); + } else { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"2")); + p = desktop_win32::commandLineAppendEncoded(p, cwd); + } + desktop_win32::commandLineAppend(p, MY_STRING(L"\"")); + bFirst = false; + + TCHAR szParentProcessId[64]; // This is more than large enough for a 128 bit decimal value + BOOL bHeadlessMode( FALSE ); + + { + // Check command line arguments for "--headless" parameter. We only + // set the environment variable "ATTACHED_PARENT_PROCESSID" for the headless + // mode as self-destruction of the soffice.bin process can lead to + // certain side-effects (log-off can result in data-loss, ".lock" is not deleted. + // See 138244 for more information. + int argc; + LPTSTR *argv = GetCommandArgs( &argc ); + + if ( argc > 1 ) + { + int n; + + for ( n = 1; n < argc; n++ ) + { + if ( 0 == _tcsnicmp( argv[n], _T("-headless"), 9 ) || + 0 == _tcsnicmp( argv[n], _T("--headless"), 9 ) ) + { + bHeadlessMode = TRUE; + } + } + } + } + + if ( _ltot( (long)GetCurrentProcessId(),szParentProcessId, 10 ) && bHeadlessMode ) + SetEnvironmentVariable( TEXT("ATTACHED_PARENT_PROCESSID"), szParentProcessId ); + + PROCESS_INFORMATION aProcessInfo; + + fSuccess = CreateProcess( + szTargetFileName, + lpCommandLine, + NULL, + NULL, + TRUE, + 0, + NULL, + szIniDirectory, + &aStartupInfo, + &aProcessInfo ); + + if ( fSuccess ) + { + DWORD dwWaitResult; + + do + { + // On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWidth" so we have to do so + // as if we where processing any messages + + dwWaitResult = MsgWaitForMultipleObjects( 1, &aProcessInfo.hProcess, FALSE, INFINITE, QS_ALLEVENTS ); + + if ( WAIT_OBJECT_0 + 1 == dwWaitResult ) + { + MSG msg; + + PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); + } + } while ( WAIT_OBJECT_0 + 1 == dwWaitResult ); + + dwExitCode = 0; + GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode ); + + CloseHandle( aProcessInfo.hProcess ); + CloseHandle( aProcessInfo.hThread ); + } + } while ( false ); + delete[] lpCommandLine; + + return fSuccess ? dwExitCode : -1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/rwrapa.cxx b/desktop/win32/source/rwrapa.cxx new file mode 100644 index 000000000000..080cb4e4be05 --- /dev/null +++ b/desktop/win32/source/rwrapa.cxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" +#define REMOTE +#include "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/rwrapw.cxx b/desktop/win32/source/rwrapw.cxx new file mode 100644 index 000000000000..15abc299a341 --- /dev/null +++ b/desktop/win32/source/rwrapw.cxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" +#define REMOTE +#define UNICODE +#include "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/Resource.h b/desktop/win32/source/setup/Resource.h new file mode 100644 index 000000000000..600056d0a8ee --- /dev/null +++ b/desktop/win32/source/setup/Resource.h @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 _RESOURCE_H +#define _RESOURCE_H + +#define IDS_APP_TITLE 10 +#define IDS_APP_PROD_TITLE 11 +#define IDS_OUTOFMEM 12 +#define IDS_NOMSI 13 +#define IDS_USER_CANCELLED 14 +#define IDS_REQUIRES_ADMIN_PRIV 15 +#define IDS_FILE_NOT_FOUND 16 +#define IDS_INVALID_PARAM 17 +#define IDS_ALLOW_MSI_UPDATE 18 +#define IDS_USAGE 19 +#define IDS_ALREADY_RUNNING 20 +#define IDS_UNKNOWN_ERROR 21 +#define IDS_INVALID_PROFILE 22 +#define IDS_UNKNOWN_LANG 23 +#define IDS_SETUP_TO_OLD 24 +#define IDS_SETUP_NOT_FOUND 25 +#define IDS_LANGUAGE_ENGLISH 50 +#define IDS_LANGUAGE_SPAIN 51 +#define IDS_LANGUAGE_GERMAN 52 +#define IDS_LANGUAGE_ZH_TW 53 +#define IDS_LANGUAGE_CS 54 +#define IDS_LANGUAGE_DA 55 +#define IDS_LANGUAGE_DE_DE 56 +#define IDS_LANGUAGE_EL 57 +#define IDS_LANGUAGE_EN_US 58 +#define IDS_LANGUAGE_ES 59 +#define IDS_LANGUAGE_FI 60 +#define IDS_LANGUAGE_FR_FR 61 +#define IDS_LANGUAGE_HE 62 +#define IDS_LANGUAGE_HU 63 +#define IDS_LANGUAGE_IT_IT 64 +#define IDS_LANGUAGE_JA 65 +#define IDS_LANGUAGE_KO 66 +#define IDS_LANGUAGE_NL_NL 67 +#define IDS_LANGUAGE_NO_NO 68 +#define IDS_LANGUAGE_PL 69 +#define IDS_LANGUAGE_PT_BR 70 +#define IDS_LANGUAGE_RU 71 +#define IDS_LANGUAGE_SK 72 +#define IDS_LANGUAGE_SV_SE 73 +#define IDS_LANGUAGE_TH 74 +#define IDS_LANGUAGE_TR 75 +#define IDS_LANGUAGE_ET 76 +#define IDS_LANGUAGE_ZH_CN 77 +#define IDS_LANGUAGE_PT_PT 78 + +#define IDI_INSTALLER 99 + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/makefile.mk b/desktop/win32/source/setup/makefile.mk new file mode 100644 index 000000000000..f0c6e0e955fd --- /dev/null +++ b/desktop/win32/source/setup/makefile.mk @@ -0,0 +1,90 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 = loader2 +LIBTARGET = NO +DYNAMIC_CRT = +TARGETTYPE = GUI + +ENABLE_EXCEPTIONS = TRUE + +# --- Settings ------------------------------------------------------------ + +.INCLUDE : settings.mk + +# --- Allgemein ----------------------------------------------------------- + +INCPRE+=$(MFC_INCLUDE) + +.IF "$(USE_DEBUG_RUNTIME)"!="" +CDEFS+=-D_DEBUG +.ENDIF # "$(USE_DEBUG_RUNTIME)"!="" + +RCFILES= $(RES)$/$(TARGET).rc + +ULFFILES= setup.ulf + +.IF "$(WITH_LANG)"!="" +ULFDIR:=$(COMMONMISC)$/$(TARGET) +.ELSE # "$(WITH_LANG)"!="" +ULFDIR:=. +.ENDIF # "$(WITH_LANG)"!="" + +OBJFILES= $(OBJ)$/setup_main.obj \ + $(OBJ)$/setup_w.obj + +# --- Targets ------------------------------------------------------ +# Generate the native Windows resource file +# using lngconvex.exe + +UWINAPILIB= $(0) +LIBSALCPPRT= $(0) + +APP1NOSAL= TRUE +APP1TARGET= loader2 + +APP1STDLIBS= $(GDI32LIB) $(ADVAPI32LIB) $(SHELL32LIB) $(MSILIB) +.IF "$(COM)"!="GCC" +APP1STDLIBS+= libcmt.lib +.ENDIF +APP1OBJS= $(OBJFILES) + +APP1DEF= $(MISC)$/$(TARGET).def + +APP1RES= $(RES)$/$(TARGET).res +APP1NOSVRES= $(RES)$/$(TARGET).res + +# --- setup -------------------------------------------------------------- + +.INCLUDE : target.mk + +$(RCFILES) : $(ULFDIR)$/setup.ulf makefile.mk rcfooter.txt rcheader.txt rctmpl.txt + $(LNGCONVEX) -ulf $(ULFDIR)$/setup.ulf -rc $(RCFILES) -rct rctmpl.txt -rch rcheader.txt -rcf rcfooter.txt + diff --git a/desktop/win32/source/setup/rcfooter.txt b/desktop/win32/source/setup/rcfooter.txt new file mode 100644 index 000000000000..3237729437f5 --- /dev/null +++ b/desktop/win32/source/setup/rcfooter.txt @@ -0,0 +1,2 @@ + +// The end diff --git a/desktop/win32/source/setup/rcheader.txt b/desktop/win32/source/setup/rcheader.txt new file mode 100644 index 000000000000..1945c499fef4 --- /dev/null +++ b/desktop/win32/source/setup/rcheader.txt @@ -0,0 +1,43 @@ +#if defined(_MSC_VER) && (_MSC_VER < 1500) +#include <winres.h> +#else +#define WINVER 0x0500 +#include <winresrc.h> +#define LB_ADDSTRING (WM_USER+1) +#define CB_ADDSTRING (WM_USER+3) +#define IDC_STATIC (-1) +#endif +#include "Resource.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,1,0 + PRODUCTVERSION 1,1,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x9L +#else + FILEFLAGS 0x8L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +IDI_INSTALLER ICON "setup.ico" + diff --git a/desktop/win32/source/setup/rctmpl.txt b/desktop/win32/source/setup/rctmpl.txt new file mode 100644 index 000000000000..59f454f70c16 --- /dev/null +++ b/desktop/win32/source/setup/rctmpl.txt @@ -0,0 +1,49 @@ +// String Table + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_TITLE %APP_TITLE% + IDS_APP_PROD_TITLE %APP_PROD_TITLE% + IDS_OUTOFMEM %OUTOFMEM% + IDS_NOMSI %NOMSI% + IDS_USER_CANCELLED %USER_CANCELLED% + IDS_REQUIRES_ADMIN_PRIV %REQUIRES_ADMIN_PRIV% + IDS_FILE_NOT_FOUND %FILE_NOT_FOUND% + IDS_INVALID_PARAM %INVALID_PARAM% + IDS_SETUP_TO_OLD %SETUP_TO_OLD% + IDS_SETUP_NOT_FOUND %SETUP_NOT_FOUND% + IDS_USAGE %USAGE% + IDS_ALREADY_RUNNING %ALREADY_RUNNING% + IDS_UNKNOWN_ERROR %UNKNOWN_ERROR% + IDS_INVALID_PROFILE %INVALID_PROFILE% + IDS_UNKNOWN_LANG %UNKNOWN_LANG% + IDS_LANGUAGE_ENGLISH %LANGUAGE_ENGLISH% + IDS_LANGUAGE_SPAIN %LANGUAGE_SPAIN% + IDS_LANGUAGE_GERMAN %LANGUAGE_GERMAN% + IDS_LANGUAGE_ZH_TW %LANGUAGE_ZH_TW% + IDS_LANGUAGE_CS %LANGUAGE_CS% + IDS_LANGUAGE_DA %LANGUAGE_DA% + IDS_LANGUAGE_DE_DE %LANGUAGE_DE_DE% + IDS_LANGUAGE_EL %LANGUAGE_EL% + IDS_LANGUAGE_EN_US %LANGUAGE_EN_US% + IDS_LANGUAGE_ES %LANGUAGE_ES% + IDS_LANGUAGE_FI %LANGUAGE_FI% + IDS_LANGUAGE_FR_FR %LANGUAGE_FR_FR% + IDS_LANGUAGE_HE %LANGUAGE_HE% + IDS_LANGUAGE_HU %LANGUAGE_HU% + IDS_LANGUAGE_IT_IT %LANGUAGE_IT_IT% + IDS_LANGUAGE_JA %LANGUAGE_JA% + IDS_LANGUAGE_KO %LANGUAGE_KO% + IDS_LANGUAGE_NL_NL %LANGUAGE_NL_NL% + IDS_LANGUAGE_NO_NO %LANGUAGE_NO_NO% + IDS_LANGUAGE_PL %LANGUAGE_PL% + IDS_LANGUAGE_PT_BR %LANGUAGE_PT_BR% + IDS_LANGUAGE_RU %LANGUAGE_RU% + IDS_LANGUAGE_SK %LANGUAGE_SK% + IDS_LANGUAGE_SV_SE %LANGUAGE_SV_SE% + IDS_LANGUAGE_TH %LANGUAGE_TH% + IDS_LANGUAGE_TR %LANGUAGE_TR% + IDS_LANGUAGE_ET %LANGUAGE_ET% + IDS_LANGUAGE_ZH_CN %LANGUAGE_ZH_CN% + IDS_LANGUAGE_PT_PT %LANGUAGE_PT_PT% +END diff --git a/desktop/win32/source/setup/setup.cpp b/desktop/win32/source/setup/setup.cpp new file mode 100644 index 000000000000..673fe57c3c07 --- /dev/null +++ b/desktop/win32/source/setup/setup.cpp @@ -0,0 +1,2063 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#define WIN // scope W32 API +#define _WIN32_WINNT 0x0501 + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <tchar.h> +#include <assert.h> +#include <shlwapi.h> +#include <new> +#include <time.h> +#include <mbctype.h> +#include <locale.h> +#include <msiquery.h> +#include <msidefs.h> +#include "strsafe.h" + +#include "setup.hxx" + +#include "Resource.h" + +//-------------------------------------------------------------------------- + +#define MAX_STR_LENGTH 32000 +#define MAX_TEXT_LENGTH 1024 +#define MAX_LANGUAGE_LEN 80 +#define MAX_STR_CAPTION 256 +#define VERSION_SIZE 80 +#define SECTION_SETUP TEXT( "Setup" ) +#define SECTION_LANGUAGE TEXT( "Languages" ) +#define PRODUCT_NAME_VAR TEXT( "%PRODUCTNAME" ) +#define PRODUCT_VERSION TEXT( "ProductVersion" ) +#define ERROR_SHOW_USAGE -2 +#define ERROR_SETUP_TO_OLD -3 +#define ERROR_SETUP_NOT_FOUND -4 + +#define PARAM_SETUP_USED TEXT( " SETUP_USED=1 " ) +#define PARAM_PACKAGE TEXT( "/I " ) +#define PARAM_MINOR_UPGRADE TEXT( "/FVOMUS " ) +#define PARAM_ADMIN TEXT( "/A " ) +#define PARAM_TRANSFORM TEXT( " TRANSFORMS=" ) +#define PARAM_REBOOT TEXT( " REBOOT=Force" ) +#define PARAM_PATCH TEXT( " /update " ) +#define PARAM_REG_ALL_MSO_TYPES TEXT( "REGISTER_ALL_MSO_TYPES=1 " ) +#define PARAM_REG_NO_MSO_TYPES TEXT( "REGISTER_NO_MSO_TYPES=1 " ) +#define PARAM_SILENTINSTALL TEXT( " /QB" ) + +#define PARAM_RUNNING TEXT( "ignore_running" ) +#define CMDLN_REG_ALL_MSO_TYPES TEXT( "msoreg=1" ) +#define CMDLN_REG_NO_MSO_TYPES TEXT( "msoreg=0" ) + +#define MSI_DLL TEXT( "msi.dll" ) +#define ADVAPI32_DLL TEXT( "advapi32.dll" ) +#define PROFILE_NAME TEXT( "setup.ini" ) + +#define RUNTIME_X64_NAME TEXT( "redist\\vcredist_x64.exe" ) +#define RUNTIME_X86_NAME TEXT( "redist\\vcredist_x86.exe" ) +#define PRODUCTCODE_X86 TEXT( "{1F1C2DFC-2D24-3E06-BCB8-725134ADF989}" ) +#define PRODUCTCODE_X64 TEXT( "{4B6C7001-C7D6-3710-913E-5BC23FCE91E6}" ) + +#define MSIAPI_DllGetVersion "DllGetVersion" +#define ADVAPI32API_CheckTokenMembership "CheckTokenMembership" + +typedef HRESULT (CALLBACK* PFnDllGetVersion)( DLLVERSIONINFO *pdvi); +typedef BOOL (WINAPI* PFnCheckTokenMembership)(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember); + +#ifdef DEBUG +inline void OutputDebugStringFormat( LPCTSTR pFormat, ... ) +{ + TCHAR buffer[1024]; + va_list args; + + va_start( args, pFormat ); + StringCchVPrintf( buffer, sizeof(buffer), pFormat, args ); + OutputDebugString( buffer ); +} +#else +static inline void OutputDebugStringFormat( LPCTSTR, ... ) +{ +} +#endif + +//-------------------------------------------------------------------------- + +const TCHAR sInstKey[] = TEXT( "Software\\Microsoft\\Windows\\CurrentVersion\\Installer" ); +const TCHAR sInstLocValue[] = TEXT( "InstallerLocation" ); +const TCHAR sMsiDll[] = TEXT( "\\msi.dll" ); +const TCHAR sMsiExe[] = TEXT( "\\msiexec.exe" ); +const TCHAR sDelayReboot[] = TEXT( " /c:\"msiinst /delayreboot\"" ); +const TCHAR sMsiQuiet[] = TEXT( " /q" ); +const TCHAR sMemMapName[] = TEXT( "Global\\MsiErrorObject" ); + +//-------------------------------------------------------------------------- +SetupAppX::SetupAppX() +{ + m_hInst = NULL; + m_hMapFile = NULL; + m_pAppTitle = NULL; + m_pCmdLine = NULL; + + m_pDatabase = NULL; + m_pReqVersion = NULL; + m_pProductName = NULL; + m_pAdvertise = NULL; + m_pTmpName = NULL; + m_pLogFile = NULL; + m_pModuleFile = NULL; + m_pPatchFiles = NULL; + m_pMSIErrorCode = NULL; + m_pUpgradeKey = NULL; + m_pProductVersion = NULL; + + m_pErrorText = new TCHAR[ MAX_TEXT_LENGTH ]; + m_pErrorText[0] = '\0'; + + m_nLanguageID = 0; + m_nLanguageCount = 0; + m_ppLanguageList = NULL; + + m_bQuiet = false; + m_bRegNoMsoTypes = false; + m_bRegAllMsoTypes = false; + m_bIsMinorUpgrade = false; + m_bSupportsPatch = false; + + m_bIgnoreAlreadyRunning = false; +} + +//-------------------------------------------------------------------------- +SetupAppX::~SetupAppX() +{ + if ( m_ppLanguageList ) + { + for ( int i = 0; i < m_nLanguageCount; i++ ) + if ( m_ppLanguageList[i] ) + delete m_ppLanguageList[ i ]; + delete [] m_ppLanguageList; + } + + time_t aTime; + time( &aTime ); + tm *pTime = localtime( &aTime ); // Convert time to struct tm form + + Log( TEXT( "End: %s\n\r\n\r\n" ), _tasctime( pTime ) ); + + if ( m_pLogFile ) fclose( m_pLogFile ); + + if ( m_pTmpName ) + { + _tremove( m_pTmpName ); + free( m_pTmpName ); + } + + if ( m_pMSIErrorCode ) UnmapViewOfFile( m_pMSIErrorCode ); + if ( m_hMapFile ) CloseHandle( m_hMapFile ); + + if ( m_pAppTitle ) delete [] m_pAppTitle; + if ( m_pDatabase ) delete [] m_pDatabase; + if ( m_pReqVersion ) delete [] m_pReqVersion; + if ( m_pProductName ) delete [] m_pProductName; + if ( m_pAdvertise ) delete [] m_pAdvertise; + if ( m_pLogFile ) delete [] m_pLogFile; + if ( m_pErrorText ) delete [] m_pErrorText; + if ( m_pModuleFile ) delete [] m_pModuleFile; + if ( m_pPatchFiles ) delete [] m_pPatchFiles; + if ( m_pUpgradeKey ) delete [] m_pUpgradeKey; + if ( m_pProductVersion ) delete [] m_pProductVersion; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::Initialize( HINSTANCE hInst ) +{ + m_pCmdLine = WIN::GetCommandLine(); + m_hInst = hInst; + + // Load our AppTitle (caption) + m_pAppTitle = new TCHAR[ MAX_STR_CAPTION ]; + m_pAppTitle[0] = '\0'; + WIN::LoadString( hInst, IDS_APP_TITLE, m_pAppTitle, MAX_STR_CAPTION ); + + // Obtain path we are running from + m_pModuleFile = new TCHAR[ MAX_PATH ]; + m_pModuleFile[ 0 ] = '\0'; + + if ( 0 == WIN::GetModuleFileName( hInst, m_pModuleFile, MAX_PATH ) ) + { + SetError( WIN::GetLastError() ); + return false; + } + + if ( ! GetCmdLineParameters( &m_pCmdLine ) ) + return false; + + m_hMapFile = CreateFileMapping( + INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max. object size + sizeof( int ), // buffer size + sMemMapName ); + if ( m_hMapFile ) + { + m_pMSIErrorCode = (int*) MapViewOfFile( m_hMapFile, // handle to map object + FILE_MAP_ALL_ACCESS, // read/write permission + 0, + 0, + sizeof( int ) ); + if ( m_pMSIErrorCode ) + *m_pMSIErrorCode = 0; + else + OutputDebugStringFormat( TEXT("Could not map view of file (%d).\n"), GetLastError() ); + } + else + OutputDebugStringFormat( TEXT("Could not create file mapping object (%d).\n"), GetLastError() ); + + Log( TEXT("Starting: %s\r\n"), m_pModuleFile ); + Log( TEXT(" CommandLine=<%s>\r\n"), m_pCmdLine ); + + if ( m_bQuiet ) + Log( TEXT(" Using quiet install mode\r\n") ); + + time_t aTime; + time( &aTime ); + tm* pTime = localtime( &aTime ); + Log( TEXT(" Begin: %s\n"), _tasctime( pTime ) ); + + return true; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetProfileSection( LPCTSTR pFileName, LPCTSTR pSection, + DWORD& rSize, LPTSTR *pRetBuf ) +{ + if ( !rSize || !*pRetBuf ) + { + rSize = 10000; + *pRetBuf = new TCHAR[ rSize ]; + } + + DWORD nRet = GetPrivateProfileSection( pSection, *pRetBuf, rSize, pFileName ); + + while ( nRet && ( nRet + 2 >= rSize ) ) // buffer was too small, retry until big enough + { + if (rSize > 1000000) + break; + delete [] (*pRetBuf); + rSize = rSize * 2; + *pRetBuf = new TCHAR[ rSize ]; + + nRet = GetPrivateProfileSection( pSection, *pRetBuf, rSize, pFileName ); + } + + if ( !nRet ) + { + SetError( WIN::GetLastError() ); + + TCHAR sBuf[80]; + StringCchPrintf( sBuf, 80, TEXT("ERROR: GetPrivateProfileSection(): GetLastError returned %u\r\n"), GetError() ); + Log( sBuf ); + return false; + } + else if ( nRet + 2 >= rSize ) + { + SetError( ERROR_OUTOFMEMORY ); + Log( TEXT( "ERROR: GetPrivateProfileSection() out of memory\r\n" ) ); + return false; + } + + Log( TEXT( " GetProfileSection read %s\r\n" ), pSection ); + + return true; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::ReadProfile() +{ + boolean bRet = false; + TCHAR *sProfilePath = 0; + + if ( GetPathToFile( PROFILE_NAME, &sProfilePath ) ) + { + DWORD nSize = 0; + LPTSTR pRetBuf = NULL; + + Log( TEXT( " Open ini file: <%s>\r\n" ), sProfilePath ); + + bRet = GetProfileSection( sProfilePath, SECTION_SETUP, nSize, &pRetBuf ); + + if ( !bRet ) + { + LPTSTR pTmpFile = CopyIniFile( sProfilePath ); + delete [] sProfilePath; + sProfilePath = pTmpFile; + + if ( sProfilePath ) + { + SetError( ERROR_SUCCESS ); + + Log( TEXT( " Could not open inifile, copied ini file to: <%s>\r\n" ), sProfilePath ); + bRet = GetProfileSection( sProfilePath, SECTION_SETUP, nSize, &pRetBuf ); + } + } + + if ( bRet ) + { + LPTSTR pCurLine = pRetBuf; + while ( *pCurLine ) + { + LPTSTR pName = 0; + LPTSTR pValue = 0; + + pCurLine += GetNameValue( pCurLine, &pName, &pValue ); + + if ( lstrcmpi( TEXT( "database" ), pName ) == 0 ) + { + m_pDatabase = pValue; + Log( TEXT( " Database = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "msiversion" ), pName ) == 0 ) + { + m_pReqVersion = pValue; + Log( TEXT( " msiversion = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "productname" ), pName ) == 0 ) + { + m_pProductName = pValue; + Log( TEXT( " productname = %s\r\n" ), pValue ); + m_pAppTitle = SetProdToAppTitle( m_pProductName ); + } + else if ( lstrcmpi( TEXT( "upgradekey" ), pName ) == 0 ) + { + m_pUpgradeKey = pValue; + Log( TEXT( " upgradekey = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "productversion" ), pName ) == 0 ) + { + m_pProductVersion = pValue; + Log( TEXT( " productversion = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "productcode" ), pName ) == 0 ) + { + delete [] pValue; + } + else + { + Log( TEXT( "Warning: unknown entry in profile <%s>\r\n" ), pName ); + delete [] pValue; + } + } + } + + if ( bRet && ( !m_pDatabase || !m_pReqVersion || !m_pProductName ) ) + { + Log( TEXT( "ERROR: incomplete 'Setup' section in profile\r\n" ) ); + SetError( ERROR_INVALID_DATA ); + bRet = false; + } + + if ( bRet ) + bRet = GetProfileSection( sProfilePath, SECTION_LANGUAGE, nSize, &pRetBuf ); + + if ( bRet ) + { + LPTSTR pName = 0; + LPTSTR pValue = 0; + LPTSTR pCurLine = pRetBuf; + LPTSTR pLastChar; + int nNext = 0; + + // first line in this section should be the language count + nNext = GetNameValue( pCurLine, &pName, &pValue ); + if ( lstrcmpi( TEXT( "count" ), pName ) == 0 ) + { + Log( TEXT( " Languages = %s\r\n" ), pValue ); + m_nLanguageCount = _tcstol( pValue, &pLastChar, 10 ); + pCurLine += nNext; + delete [] pValue; + } + + m_ppLanguageList = new LanguageDataX*[ m_nLanguageCount ]; + + for ( int i=0; i < m_nLanguageCount; i++ ) + { + if ( !*pCurLine ) + { + m_nLanguageCount = i; + break; + } + + pCurLine += GetNameValue( pCurLine, &pName, &pValue ); + m_ppLanguageList[ i ] = new LanguageDataX( pValue ); + Log( TEXT( " Language = %s\r\n" ), pValue ); + + if ( m_ppLanguageList[ i ]->m_pTransform ) + Log( TEXT( " Transform = %s\r\n" ), m_ppLanguageList[ i ]->m_pTransform ); + + delete [] pValue; + } + } + + if ( pRetBuf ) + delete [] pRetBuf; + } + + if ( sProfilePath && ! m_pTmpName ) + delete [] sProfilePath; + + return bRet; +} + +//-------------------------------------------------------------------------- +void SetupAppX::AddFileToPatchList( TCHAR* pPath, TCHAR* pFile ) +{ + if ( m_pPatchFiles == NULL ) + { + m_pPatchFiles = new TCHAR[ MAX_STR_LENGTH ]; + StringCchCopy( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") ); + } + else + StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT(";") ); + + StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, pPath ); + StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, pFile ); +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetPatches() +{ + boolean bRet = true; + + int nPatternLen = lstrlen( m_pModuleFile ) + 7; // 1 for null terminator, 1 for back slash, 5 for extensions + TCHAR* pPattern = new TCHAR[ nPatternLen ]; + TCHAR* pBaseDir = new TCHAR[ nPatternLen ]; + + // find 'setup.exe' in the path so we can remove it + TCHAR *pFilePart = 0; + if ( 0 == GetFullPathName( m_pModuleFile, nPatternLen, pPattern, &pFilePart ) ) + { + SetError( WIN::GetLastError() ); + bRet = false; + } + else + { + if ( pFilePart ) + *pFilePart = '\0'; + StringCchCopy( pBaseDir, nPatternLen, pPattern ); + StringCchCat( pPattern, nPatternLen, TEXT("*.msp") ); + + WIN32_FIND_DATA aFindFileData; + + HANDLE hFindPatches = FindFirstFile( pPattern, &aFindFileData ); + + if ( hFindPatches != INVALID_HANDLE_VALUE ) + { + if ( ! IsPatchInstalled( pBaseDir, aFindFileData.cFileName ) ) + AddFileToPatchList( pBaseDir, aFindFileData.cFileName ); + + while ( FindNextFile( hFindPatches, &aFindFileData ) ) + { + if ( ! IsPatchInstalled( pBaseDir, aFindFileData.cFileName ) ) + AddFileToPatchList( pBaseDir, aFindFileData.cFileName ); + } + + if ( m_pPatchFiles != NULL ) + StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") ); + + FindClose( hFindPatches ); + } + } + + delete [] pPattern; + delete [] pBaseDir; + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetPathToFile( TCHAR* pFileName, TCHAR** pPath ) +{ + // generate the path to the file = szModuleFile + FileName + // note: FileName is a relative path + + boolean bRet = true; + + int nTempPath = lstrlen( m_pModuleFile ) + lstrlen( pFileName ) + 2; // 1 for null terminator, 1 for back slash + TCHAR* pTempPath = new TCHAR[ nTempPath ]; + + // find 'setup.exe' in the path so we can remove it + TCHAR *pFilePart = 0; + if ( 0 == GetFullPathName( m_pModuleFile, nTempPath, pTempPath, &pFilePart ) ) + { + SetError( WIN::GetLastError() ); + bRet = false; + } + else + { + if ( pFilePart ) + *pFilePart = '\0'; + + StringCchCat( pTempPath, nTempPath, pFileName ); + + int nPath = 2 * nTempPath; + *pPath = new TCHAR[ nPath ]; + + // normalize the path + int nReturn = GetFullPathName( pTempPath, nPath, *pPath, &pFilePart ); + + if ( nReturn > nPath ) + { + // try again, with larger buffer + delete [] (*pPath); + nPath = nReturn; + *pPath = new TCHAR[ nPath ]; + + nReturn = GetFullPathName( pTempPath, nPath, *pPath, &pFilePart ); + } + + if ( 0 == nReturn ) + { + // error -- invalid path + SetError( WIN::GetLastError() ); + bRet = false; + } + } + + if ( bRet ) // check for the file's existence + { + DWORD dwFileAttrib = GetFileAttributes( *pPath ); + + if (0xFFFFFFFF == dwFileAttrib) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pFileName ); + SetError( ERROR_FILE_NOT_FOUND ); + bRet = false; + } + } + + delete [] pTempPath; + return bRet; +} + +//-------------------------------------------------------------------------- +int SetupAppX::GetNameValue( TCHAR* pLine, TCHAR** pName, TCHAR** pValue ) +{ + int nRet = lstrlen( pLine ) + 1; + *pValue = 0; + + if ( nRet == 1 ) + return nRet; + + LPTSTR pChar = pLine; + LPTSTR pLast = NULL; + + // Skip leading spaces. + while (' ' == *pChar || '\t' == *pChar) + pChar = CharNext( pChar ); + + *pName = pChar; + + // look for the end of the name + while( *pChar && (' ' != *pChar) && + ( '\t' != *pChar ) && ( '=' != *pChar ) ) + pChar = CharNext( pChar ); + + if ( ! *pChar ) + return nRet; + + pLast = pChar; + pChar = CharNext( pChar ); + *pLast = '\0'; + + // look for the start of the value + while( ( ' ' == *pChar ) || ( '\t' == *pChar ) || + ( '=' == *pChar ) ) + pChar = CharNext( pChar ); + + int nValueLen = lstrlen( pChar ) + 1; + *pValue = new TCHAR[ nValueLen ]; + + if ( *pValue ) + StringCchCopy( *pValue, nValueLen, pChar ); + + return nRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::ChooseLanguage( long& rLanguage ) +{ + rLanguage = 0; + + if ( m_bQuiet ) + return true; + + // When there are none or only one language, there is nothing + // to do here + if ( m_nLanguageCount > 1 ) + { + TCHAR *sString = new TCHAR[ MAX_LANGUAGE_LEN ]; + + LANGID nUserDefLang = GetUserDefaultLangID(); + LANGID nSysDefLang = GetSystemDefaultLangID(); + + int nUserPrimary = PRIMARYLANGID( nUserDefLang ); + int nSysPrimary = PRIMARYLANGID( nSysDefLang ); + + long nUserIndex = -1; + long nUserPrimIndex = -1; + long nSystemIndex = -1; + long nSystemPrimIndex = -1; + long nParamIndex = -1; + + for ( long i=0; i<GetLanguageCount(); i++ ) + { + long nLanguage = GetLanguageID( i ); + int nPrimary = PRIMARYLANGID( nLanguage ); + GetLanguageName( nLanguage, sString ); + Log( TEXT( " Info: found Language: %s\r\n" ), sString ); + + if ( nLanguage == nUserDefLang ) + nUserIndex = i; + if ( nPrimary == nUserPrimary ) + nUserPrimIndex = i; + if ( nLanguage == nSysDefLang ) + nSystemIndex = i; + if ( nPrimary == nSysPrimary ) + nSystemPrimIndex = i; + if ( m_nLanguageID && ( nLanguage == m_nLanguageID ) ) + nParamIndex = i; + } + + if ( m_nLanguageID && ( nParamIndex == -1 ) ) + { + Log( TEXT( "Warning: Language chosen with parameter -lang not found.\r\n" ) ); + } + + if ( nParamIndex != -1 ) + { + Log( TEXT( "Info: Found language chosen with parameter -lang.\r\n" ) ); + rLanguage = GetLanguageID( nParamIndex ); + } + else if ( nUserIndex != -1 ) + { + Log( TEXT( "Info: Found user default language.\r\n" ) ); + rLanguage = GetLanguageID( nUserIndex ); + } + else if ( nUserPrimIndex != -1 ) + { + Log( TEXT( "Info: Found user default primary language.\r\n" ) ); + rLanguage = GetLanguageID( nUserPrimIndex ); + } + else if ( nSystemIndex != -1 ) + { + Log( TEXT( "Info: Found system default language.\r\n" ) ); + rLanguage = GetLanguageID( nSystemIndex ); + } + else if ( nSystemPrimIndex != -1 ) + { + Log( TEXT( "Info: Found system default primary language.\r\n" ) ); + rLanguage = GetLanguageID( nSystemPrimIndex ); + } + else + { + Log( TEXT( "Info: Use default language from ini file.\r\n" ) ); + rLanguage = GetLanguageID( 0 ); + } + delete [] sString; + } + + return true; +} + +//-------------------------------------------------------------------------- +HMODULE SetupAppX::LoadMsiLibrary() +{ + HMODULE hMsi = NULL; + HKEY hInstKey = NULL; + + // find registered location of Msi.dll + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sInstKey, 0, KEY_READ, &hInstKey ) ) + { + long nRet = ERROR_SUCCESS; + TCHAR *sMsiFolder = new TCHAR[ MAX_PATH + 1 ]; + DWORD dwMsiFolderSize = MAX_PATH + 1; + DWORD dwType = 0; + + if ( ERROR_MORE_DATA == ( nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, + &dwType, (BYTE*)sMsiFolder, &dwMsiFolderSize ) ) ) + { + // try again with larger buffer + delete [] sMsiFolder; + sMsiFolder = new TCHAR[ dwMsiFolderSize ]; + + nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, + (BYTE*)sMsiFolder, &dwMsiFolderSize ); + } + + if ( ERROR_SUCCESS == nRet && dwType == REG_SZ && dwMsiFolderSize > 0 ) + { + // load Msi.dll from registered location + int nLength = lstrlen( sMsiDll ) + dwMsiFolderSize + 1; // use StringCchLength ? + TCHAR *pMsiLocation = new TCHAR[ nLength ]; + + if ( SUCCEEDED( StringCchCopy( pMsiLocation, nLength, sMsiFolder ) ) && + SUCCEEDED( StringCchCat( pMsiLocation, nLength, sMsiDll ) ) ) + { + hMsi = LoadLibrary( pMsiLocation ); + } + } + } + + if ( !hMsi ) // use the default location + { + hMsi = LoadLibrary( sMsiDll ); + } + + return hMsi; +} + +//-------------------------------------------------------------------------- +LPCTSTR SetupAppX::GetPathToMSI() +{ + LPTSTR sMsiPath = NULL; + HKEY hInstKey = NULL; + TCHAR *sMsiFolder = new TCHAR[ MAX_PATH + 1 ]; + DWORD nMsiFolderSize = MAX_PATH + 1; + + sMsiFolder[0] = '\0'; + + // find registered location of Msi.dll + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sInstKey, 0, KEY_READ, &hInstKey ) ) + { + LONG nRet = ERROR_SUCCESS; + DWORD dwType = 0; + + if ( ERROR_MORE_DATA == ( nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, + &dwType, (BYTE*)sMsiFolder, &nMsiFolderSize ) ) ) + { + // try again with larger buffer + delete [] sMsiFolder; + sMsiFolder = new TCHAR[ nMsiFolderSize ]; + + nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, + (BYTE*)sMsiFolder, &nMsiFolderSize ); + } + + if ( ERROR_SUCCESS != nRet || dwType != REG_SZ || nMsiFolderSize == 0 ) + sMsiFolder[0] = '\0'; + } + + if ( sMsiFolder[0] == '\0' ) // use the default location + { + Log( TEXT( " Could not find path to msiexec.exe in registry" ) ); + + DWORD nRet = WIN::GetSystemDirectory( sMsiFolder, nMsiFolderSize ); + if ( nRet > nMsiFolderSize ) + { + delete [] sMsiFolder; + sMsiFolder = new TCHAR[ nRet ]; + nMsiFolderSize = nRet; + + nRet = WIN::GetSystemDirectory( sMsiFolder, nMsiFolderSize ); + } + if ( 0 == nRet ) + { + sMsiFolder[0] = '\0'; + SetError( WIN::GetLastError() ); + } + nMsiFolderSize = nRet; + } + + if ( sMsiFolder[0] != '\0' ) + { + int nLength = lstrlen( sMsiExe ) + lstrlen( sMsiFolder ) + 1; + sMsiPath = new TCHAR[ nLength ]; + + if ( FAILED( StringCchCopy( sMsiPath, nLength, sMsiFolder ) ) || + FAILED( StringCchCat( sMsiPath, nLength, sMsiExe ) ) ) + { + delete [] sMsiPath; + sMsiPath = NULL; + } + } + + if ( ! sMsiPath ) + Log( TEXT( "ERROR: Can't build path to msiexec.exe!" ) ); + + return sMsiPath; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::LaunchInstaller( LPCTSTR pParam ) +{ + LPCTSTR sMsiPath = GetPathToMSI(); + + if ( !sMsiPath ) + { + Log( TEXT( "ERROR: msiexec not found!" ) ); + SetError( ERROR_FILE_NOT_FOUND ); + return false; + } + + STARTUPINFO aSUI; + PROCESS_INFORMATION aPI; + + Log( TEXT( " Will install using <%s>\r\n" ), sMsiPath ); + Log( TEXT( " Parameters are: %s\r\n" ), pParam ); + + OutputDebugStringFormat( TEXT( " Will install using <%s>\r\n" ), sMsiPath ); + OutputDebugStringFormat( TEXT( " Parameters are: %s\r\n" ), pParam ); + + ZeroMemory( (void*)&aPI, sizeof( PROCESS_INFORMATION ) ); + ZeroMemory( (void*)&aSUI, sizeof( STARTUPINFO ) ); + + aSUI.cb = sizeof(STARTUPINFO); + aSUI.dwFlags = STARTF_USESHOWWINDOW; + aSUI.wShowWindow = SW_SHOW; + + DWORD nCmdLineLength = lstrlen( sMsiPath ) + lstrlen( pParam ) + 2; + TCHAR *sCmdLine = new TCHAR[ nCmdLineLength ]; + + if ( FAILED( StringCchCopy( sCmdLine, nCmdLineLength, sMsiPath ) ) || + FAILED( StringCchCat( sCmdLine, nCmdLineLength, TEXT( " " ) ) ) || + FAILED( StringCchCat( sCmdLine, nCmdLineLength, pParam ) ) ) + { + delete [] sCmdLine; + SetError( ERROR_INSTALL_FAILURE ); + return false; + } + + if ( !WIN::CreateProcess( NULL, sCmdLine, NULL, NULL, FALSE, + CREATE_DEFAULT_ERROR_MODE, NULL, NULL, + &aSUI, &aPI ) ) + { + Log( TEXT( "ERROR: Could not create process %s.\r\n" ), sCmdLine ); + SetError( WIN::GetLastError() ); + delete [] sCmdLine; + return false; + } + + DWORD nResult = WaitForProcess( aPI.hProcess ); + bool bRet = true; + + if( ERROR_SUCCESS != nResult ) + { + Log( TEXT( "ERROR: While waiting for %s.\r\n" ), sCmdLine ); + SetError( nResult ); + bRet = false; + } + else + { + GetExitCodeProcess( aPI.hProcess, &nResult ); + SetError( nResult ); + + if ( nResult != ERROR_SUCCESS ) + { + TCHAR sBuf[80]; + StringCchPrintf( sBuf, 80, TEXT("Warning: msiexec returned %u.\r\n"), nResult ); + Log( sBuf ); + } + else + Log( TEXT( " Installation completed successfully.\r\n" ) ); + } + + CloseHandle( aPI.hProcess ); + + delete [] sCmdLine; + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::Install( long nLanguage ) +{ + LPTSTR pTransform = NULL; + + if ( nLanguage ) // look for transformation + { + for ( int i = 0; i < m_nLanguageCount; i++ ) + { + if ( m_ppLanguageList[i]->m_nLanguageID == nLanguage ) + { + if ( m_ppLanguageList[i]->m_pTransform ) + { + if ( !GetPathToFile( m_ppLanguageList[i]->m_pTransform, + &pTransform ) ) + { + Log( TEXT( "ERROR: Could not find transform <%s\r\n" ), m_ppLanguageList[i]->m_pTransform ); + return false; + } + } + break; + } + } + } + + TCHAR *pDataBasePath = NULL; + + if ( ! GetPathToFile( m_pDatabase, &pDataBasePath ) ) + { + Log( TEXT( "ERROR: Could not find database <%s\r\n" ), m_pDatabase ); + SetError( ERROR_INSTALL_SOURCE_ABSENT ); + return false; + } + + // we will always use the parameter setup used + int nParLen = lstrlen( PARAM_SETUP_USED ); + + if ( m_bRegNoMsoTypes ) + nParLen += lstrlen( PARAM_REG_NO_MSO_TYPES ); + else if ( m_bRegAllMsoTypes ) + nParLen += lstrlen( PARAM_REG_ALL_MSO_TYPES ); + + if ( m_pAdvertise ) + nParLen += lstrlen( m_pAdvertise ) + 1; // one for the space + else if ( m_bIsMinorUpgrade ) + nParLen += lstrlen( PARAM_MINOR_UPGRADE ); + else + nParLen += lstrlen( PARAM_PACKAGE ); + + nParLen += lstrlen( pDataBasePath ) + 3; // two quotes, one null + + if ( NeedReboot() ) + nParLen += lstrlen( PARAM_REBOOT ); + + if ( m_pPatchFiles ) + { + nParLen += lstrlen( PARAM_PATCH ); + nParLen += lstrlen( m_pPatchFiles ); + } + + if ( pTransform ) + { + nParLen += lstrlen( PARAM_TRANSFORM ); + nParLen += lstrlen( pTransform ) + 2; // two quotes + } + + if ( m_pCmdLine ) + nParLen += lstrlen( m_pCmdLine ) + 1; // one for the space; + + TCHAR *pParams = new TCHAR[ nParLen ]; + + StringCchCopy( pParams, nParLen, PARAM_SETUP_USED ); + + if ( m_bRegNoMsoTypes ) + StringCchCat( pParams, nParLen, PARAM_REG_NO_MSO_TYPES ); + else if ( m_bRegAllMsoTypes ) + StringCchCat( pParams, nParLen, PARAM_REG_ALL_MSO_TYPES ); + + if ( m_pAdvertise ) + StringCchCat( pParams, nParLen, m_pAdvertise ); + else if ( IsAdminInstall() ) + StringCchCat( pParams, nParLen, PARAM_ADMIN ); + else if ( m_bIsMinorUpgrade ) + StringCchCat( pParams, nParLen, PARAM_MINOR_UPGRADE ); + else + StringCchCat( pParams, nParLen, PARAM_PACKAGE ); + + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + StringCchCat( pParams, nParLen, pDataBasePath ); + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + + if ( NeedReboot() ) + StringCchCat( pParams, nParLen, PARAM_REBOOT ); + + if ( m_pPatchFiles ) + { + StringCchCat( pParams, nParLen, PARAM_PATCH ); + StringCchCat( pParams, nParLen, m_pPatchFiles ); + } + + if ( pTransform ) + { + StringCchCat( pParams, nParLen, PARAM_TRANSFORM ); + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + StringCchCat( pParams, nParLen, pTransform ); + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + } + + if ( m_pCmdLine ) + { + StringCchCat( pParams, nParLen, TEXT( " " ) ); + StringCchCat( pParams, nParLen, m_pCmdLine ); + } + + return LaunchInstaller( pParams ); +} + +//-------------------------------------------------------------------------- +UINT SetupAppX::GetError() const +{ + UINT nErr = 0; + + if ( m_pMSIErrorCode ) + nErr = (UINT) *m_pMSIErrorCode; + + if ( nErr == 0 ) + nErr = m_uiRet; + + if ( nErr != 0 ) + OutputDebugStringFormat( TEXT("Setup will return error (%d).\n"), nErr ); + return nErr; +} + +//-------------------------------------------------------------------------- +void SetupAppX::DisplayError( UINT nErr ) const +{ + TCHAR sError[ MAX_TEXT_LENGTH ] = {0}; + TCHAR sTmp[ MAX_TEXT_LENGTH ] = {0}; + + UINT nMsgType = MB_OK | MB_ICONERROR; + + switch ( nErr ) + { + case ERROR_SUCCESS: break; // 0 + + case ERROR_FILE_NOT_FOUND: // 2 + WIN::LoadString( m_hInst, IDS_FILE_NOT_FOUND, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pErrorText ); + break; + case ERROR_INVALID_DATA: // 13 + WIN::LoadString( m_hInst, IDS_INVALID_PROFILE, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_OUTOFMEMORY: WIN::LoadString( m_hInst, IDS_OUTOFMEM, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INSTALL_USEREXIT: + WIN::LoadString( m_hInst, IDS_USER_CANCELLED, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INSTALL_ALREADY_RUNNING: // 1618 + WIN::LoadString( m_hInst, IDS_ALREADY_RUNNING, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INSTALL_SOURCE_ABSENT: + WIN::LoadString( m_hInst, IDS_NOMSI, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_DS_INSUFF_ACCESS_RIGHTS: // 8344 + WIN::LoadString( m_hInst, IDS_REQUIRES_ADMIN_PRIV, sError, MAX_TEXT_LENGTH ); + break; + case E_ABORT: WIN::LoadString( m_hInst, IDS_UNKNOWN_ERROR, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INVALID_PARAMETER: // 87 + WIN::LoadString( m_hInst, IDS_INVALID_PARAM, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pErrorText ); + break; + + case ERROR_SETUP_TO_OLD: // - 3 + WIN::LoadString( m_hInst, IDS_SETUP_TO_OLD, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pReqVersion, m_pErrorText ); + break; + case ERROR_SETUP_NOT_FOUND: // - 4 + WIN::LoadString( m_hInst, IDS_SETUP_NOT_FOUND, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pReqVersion ); + break; + case ERROR_SHOW_USAGE: // - 2 + nMsgType = MB_OK | MB_ICONINFORMATION; + WIN::LoadString( m_hInst, IDS_USAGE, sError, MAX_TEXT_LENGTH ); + break; + + default: WIN::LoadString( m_hInst, IDS_UNKNOWN_ERROR, sError, MAX_TEXT_LENGTH ); + break; + } + + if ( sError[0] ) + { + if ( !m_bQuiet ) + { + ConvertNewline( sError ); + WIN::MessageBox( NULL, sError, m_pAppTitle, nMsgType ); + } + + Log( TEXT( "ERROR: %s\r\n" ), sError ); + } +} + +//-------------------------------------------------------------------------- +long SetupAppX::GetLanguageID( long nIndex ) const +{ + if ( nIndex >=0 && nIndex < m_nLanguageCount ) + return m_ppLanguageList[ nIndex ]->m_nLanguageID; + else + return 0; +} + +//-------------------------------------------------------------------------- +void SetupAppX::GetLanguageName( long nLanguage, LPTSTR sName ) const +{ + switch ( nLanguage ) + { + case 1028: WIN::LoadString( m_hInst, IDS_LANGUAGE_ZH_TW, sName, MAX_LANGUAGE_LEN ); break; + case 1029: WIN::LoadString( m_hInst, IDS_LANGUAGE_CS, sName, MAX_LANGUAGE_LEN ); break; + case 1030: WIN::LoadString( m_hInst, IDS_LANGUAGE_DA, sName, MAX_LANGUAGE_LEN ); break; + case 1031: WIN::LoadString( m_hInst, IDS_LANGUAGE_DE_DE, sName, MAX_LANGUAGE_LEN ); break; + case 1032: WIN::LoadString( m_hInst, IDS_LANGUAGE_EL, sName, MAX_LANGUAGE_LEN ); break; + case 1033: WIN::LoadString( m_hInst, IDS_LANGUAGE_EN_US, sName, MAX_LANGUAGE_LEN ); break; + case 1034: WIN::LoadString( m_hInst, IDS_LANGUAGE_ES, sName, MAX_LANGUAGE_LEN ); break; + case 1035: WIN::LoadString( m_hInst, IDS_LANGUAGE_FI, sName, MAX_LANGUAGE_LEN ); break; + case 1036: WIN::LoadString( m_hInst, IDS_LANGUAGE_FR_FR, sName, MAX_LANGUAGE_LEN ); break; + case 1037: WIN::LoadString( m_hInst, IDS_LANGUAGE_HE, sName, MAX_LANGUAGE_LEN ); break; + case 1038: WIN::LoadString( m_hInst, IDS_LANGUAGE_HU, sName, MAX_LANGUAGE_LEN ); break; + case 1040: WIN::LoadString( m_hInst, IDS_LANGUAGE_IT_IT, sName, MAX_LANGUAGE_LEN ); break; + case 1041: WIN::LoadString( m_hInst, IDS_LANGUAGE_JA, sName, MAX_LANGUAGE_LEN ); break; + case 1042: WIN::LoadString( m_hInst, IDS_LANGUAGE_KO, sName, MAX_LANGUAGE_LEN ); break; + case 1043: WIN::LoadString( m_hInst, IDS_LANGUAGE_NL_NL, sName, MAX_LANGUAGE_LEN ); break; + case 1044: WIN::LoadString( m_hInst, IDS_LANGUAGE_NO_NO, sName, MAX_LANGUAGE_LEN ); break; + case 1045: WIN::LoadString( m_hInst, IDS_LANGUAGE_PL, sName, MAX_LANGUAGE_LEN ); break; + case 1046: WIN::LoadString( m_hInst, IDS_LANGUAGE_PT_BR, sName, MAX_LANGUAGE_LEN ); break; + case 1049: WIN::LoadString( m_hInst, IDS_LANGUAGE_RU, sName, MAX_LANGUAGE_LEN ); break; + case 1051: WIN::LoadString( m_hInst, IDS_LANGUAGE_SK, sName, MAX_LANGUAGE_LEN ); break; + case 1053: WIN::LoadString( m_hInst, IDS_LANGUAGE_SV_SE, sName, MAX_LANGUAGE_LEN ); break; + case 1054: WIN::LoadString( m_hInst, IDS_LANGUAGE_TH, sName, MAX_LANGUAGE_LEN ); break; + case 1055: WIN::LoadString( m_hInst, IDS_LANGUAGE_TR, sName, MAX_LANGUAGE_LEN ); break; + case 1061: WIN::LoadString( m_hInst, IDS_LANGUAGE_ET, sName, MAX_LANGUAGE_LEN ); break; + case 2052: WIN::LoadString( m_hInst, IDS_LANGUAGE_ZH_CN, sName, MAX_LANGUAGE_LEN ); break; + case 2070: WIN::LoadString( m_hInst, IDS_LANGUAGE_PT_PT, sName, MAX_LANGUAGE_LEN ); break; + + default: + { + TCHAR sTmp[ MAX_LANGUAGE_LEN ] = {0}; + + WIN::LoadString( m_hInst, IDS_UNKNOWN_LANG, sTmp, MAX_LANGUAGE_LEN ); + StringCchPrintf( sName, MAX_LANGUAGE_LEN, sTmp, nLanguage ); + } + } +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::CheckVersion() +{ + boolean bRet = false; + HMODULE hMsi = LoadMsiLibrary(); + + Log( TEXT( " Looking for installed MSI with version >= %s\r\n" ), m_pReqVersion ); + + if ( !hMsi ) + { + Log( TEXT( "Error: No MSI found!\r\n" ) ); + SetError( (UINT) ERROR_SETUP_NOT_FOUND ); + } + else + { + PFnDllGetVersion pDllGetVersion = (PFnDllGetVersion) GetProcAddress( hMsi, MSIAPI_DllGetVersion ); + + if ( pDllGetVersion ) + { + DLLVERSIONINFO aInfo; + + aInfo.cbSize = sizeof( DLLVERSIONINFO ); + if ( NOERROR == pDllGetVersion( &aInfo ) ) + { + TCHAR pMsiVersion[ VERSION_SIZE ]; + StringCchPrintf( pMsiVersion, VERSION_SIZE, TEXT("%d.%d.%4d"), + aInfo.dwMajorVersion, + aInfo.dwMinorVersion, + aInfo.dwBuildNumber ); + if ( _tcsncmp( pMsiVersion, m_pReqVersion, _tcslen( pMsiVersion ) ) < 0 ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pMsiVersion ); + SetError( (UINT) ERROR_SETUP_TO_OLD ); + Log( TEXT( "Warning: Old MSI version found <%s>, update needed!\r\n" ), pMsiVersion ); + } + else + { + Log( TEXT( " Found MSI version <%s>, no update needed\r\n" ), pMsiVersion ); + bRet = true; + } + if ( aInfo.dwMajorVersion >= 3 ) + m_bSupportsPatch = true; + else + Log( TEXT("Warning: Patching not supported! MSI-Version <%s>\r\n"), pMsiVersion ); + } + } + + FreeLibrary( hMsi ); + } + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::CheckForUpgrade() +{ + // When we have patch files we will never try an Minor upgrade + if ( m_pPatchFiles ) return true; + + if ( !m_pUpgradeKey || ( _tcslen( m_pUpgradeKey ) == 0 ) ) + { + Log( TEXT( " No Upgrade Key Found -> continue with standard installation!\r\n" ) ); + return true; + } + + HKEY hInstKey = NULL; + + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, m_pUpgradeKey, 0, KEY_READ, &hInstKey ) ) + { + Log( TEXT( " Found Upgrade Key in Registry (HKLM) -> will try minor upgrade!\r\n" ) ); + m_bIsMinorUpgrade = true; + } + else if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_CURRENT_USER, m_pUpgradeKey, 0, KEY_READ, &hInstKey ) ) + { + Log( TEXT( " Found Upgrade Key in Registry (HKCU) -> will try minor upgrade!\r\n" ) ); + m_bIsMinorUpgrade = true; + } + else + { + Log( TEXT( " Didn't Find Upgrade Key in Registry -> continue with standard installation!\r\n" ) ); + return true; + } + + if ( m_pProductVersion && ( _tcslen( m_pProductVersion ) > 0 ) ) + { + TCHAR *sProductVersion = new TCHAR[ MAX_PATH + 1 ]; + DWORD nSize = MAX_PATH + 1; + + sProductVersion[0] = '\0'; + + // get product version + if ( ERROR_SUCCESS == RegQueryValueEx( hInstKey, PRODUCT_VERSION, NULL, NULL, (LPBYTE)sProductVersion, &nSize ) ) + { + if ( lstrcmpi( sProductVersion, m_pProductVersion ) == 0 ) + { + Log( TEXT( " Same Product Version already installed, no minor upgrade!\r\n" ) ); + m_bIsMinorUpgrade = false; + } + } + + delete [] sProductVersion; + } + + return true; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::IsTerminalServerInstalled() const +{ + boolean bIsTerminalServer = false; + + const TCHAR sSearchStr[] = TEXT("Terminal Server"); + const TCHAR sKey[] = TEXT("System\\CurrentControlSet\\Control\\ProductOptions"); + const TCHAR sValue[] = TEXT("ProductSuite"); + + DWORD dwSize = 0; + HKEY hKey = 0; + DWORD dwType = 0; + + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sKey, 0, KEY_READ, &hKey ) && + ERROR_SUCCESS == RegQueryValueEx( hKey, sValue, NULL, &dwType, NULL, &dwSize ) && + dwSize > 0 && + REG_MULTI_SZ == dwType ) + { + TCHAR* sSuiteList = new TCHAR[ (dwSize*sizeof(byte)/sizeof(TCHAR)) + 1 ]; + + ZeroMemory(sSuiteList, dwSize); + + if ( ERROR_SUCCESS == RegQueryValueEx( hKey, sValue, NULL, &dwType, (LPBYTE)sSuiteList, &dwSize) ) + { + DWORD nMulti = 0; + DWORD nSrch = lstrlen( sSearchStr ); + const TCHAR *sSubString = sSuiteList; + + while (*sSubString) + { + nMulti = lstrlen( sSubString ); + if ( nMulti == nSrch && 0 == lstrcmp( sSearchStr, sSubString ) ) + { + bIsTerminalServer = true; + break; + } + + sSubString += (nMulti + 1); + } + } + delete [] sSuiteList; + } + + if ( hKey ) + RegCloseKey( hKey ); + + return bIsTerminalServer; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::AlreadyRunning() const +{ + if ( m_bIgnoreAlreadyRunning ) + { + Log( TEXT("Ignoring already running MSI instance!\r\n") ); + return false; + } + + const TCHAR *sMutexName = NULL; + const TCHAR sGUniqueName[] = TEXT( "Global\\_MSISETUP_{EA8130C1-8D3D-4338-9309-1A52D530D846}" ); + const TCHAR sUniqueName[] = TEXT( "_MSISETUP_{EA8130C1-8D3D-4338-9309-1A52D530D846}" ); + + if ( ( GetOSVersion() < 5 ) && ! IsTerminalServerInstalled() ) + sMutexName = sUniqueName; + else + sMutexName = sGUniqueName; + + HANDLE hMutex = 0; + + hMutex = WIN::CreateMutex( NULL, FALSE, sMutexName ); + + if ( !hMutex || ERROR_ALREADY_EXISTS == WIN::GetLastError() ) + { + if ( !hMutex ) + Log( TEXT( "ERROR: AlreadyRunning() could not create mutex!\r\n" ) ); + else + Log( TEXT( "ERROR: There's already a setup running!\r\n" ) ); + + return true; + } + Log( TEXT( " No running Setup found\r\n" ) ); + + return false; +} + +//-------------------------------------------------------------------------- +DWORD SetupAppX::WaitForProcess( HANDLE hHandle ) +{ + DWORD nResult = NOERROR; + boolean bLoop = true; + + MSG aMsg; + ZeroMemory( (void*) &aMsg, sizeof(MSG) ); + + while ( bLoop ) + { + switch ( WIN::MsgWaitForMultipleObjects( 1, &hHandle, false, + INFINITE, QS_ALLINPUT ) ) + { + case WAIT_OBJECT_0: bLoop = false; + break; + + case (WAIT_OBJECT_0 + 1): + { + if ( WIN::PeekMessage( &aMsg, NULL, NULL, NULL, PM_REMOVE ) ) + { + WIN::TranslateMessage( &aMsg ); + WIN::DispatchMessage( &aMsg ); + } + break; + } + + default: + { + nResult = WIN::GetLastError(); + bLoop = false; + } + } + } + + return nResult; +} + +//-------------------------------------------------------------------------- +void SetupAppX::Log( LPCTSTR pMessage, LPCTSTR pText ) const +{ + if ( m_pLogFile ) + { + static boolean bInit = false; + + if ( !bInit ) + { + bInit = true; + _ftprintf( m_pLogFile, TEXT("%c"), 0xfeff ); + + _tsetlocale( LC_ALL, TEXT("") ); + _ftprintf( m_pLogFile, TEXT("\nCodepage=%s\nMultiByte Codepage=[%d]\n"), + _tsetlocale( LC_ALL, NULL ), _getmbcp() ); + } + if ( pText ) + { + _ftprintf( m_pLogFile, pMessage, pText ); + OutputDebugStringFormat( pMessage, pText ); + } + else + { + _ftprintf( m_pLogFile, pMessage ); + OutputDebugStringFormat( pMessage ); + } + + fflush( m_pLogFile ); + } +} + +//-------------------------------------------------------------------------- +DWORD SetupAppX::GetNextArgument( LPCTSTR pStr, LPTSTR *pArg, LPTSTR *pNext, + boolean bStripQuotes ) +{ + boolean bInQuotes = false; + boolean bFoundArgEnd = false; + LPCTSTR pChar = pStr; + LPCTSTR pFirst = NULL; + + if ( NULL == pChar ) + return ERROR_NO_MORE_ITEMS; + + while ( ' ' == (*pChar) || '\t' == (*pChar) ) + pChar = CharNext( pChar ); + + if ( '\0' == (*pChar) ) + return ERROR_NO_MORE_ITEMS; + + int nCount = 1; + pFirst = pChar; + + while ( ! bFoundArgEnd ) + { + if ( '\0' == (*pChar) ) + bFoundArgEnd = true; + else if ( !bInQuotes && ' ' == (*pChar) ) + bFoundArgEnd = true; + else if ( !bInQuotes && '\t' == (*pChar) ) + bFoundArgEnd = true; + else + { + if ( '\"' == (*pChar) ) + { + bInQuotes = !bInQuotes; + if ( bStripQuotes ) + { + if ( pChar == pFirst ) + pFirst = CharNext( pFirst ); + nCount -= 1; + } + } + + pChar = CharNext( pChar ); + nCount += 1; + } + } + + if ( pArg ) + { + *pArg = new TCHAR[ nCount ]; + StringCchCopyN ( *pArg, nCount, pFirst, nCount-1 ); + } + + if ( pNext ) + *pNext = CharNext( pChar ); + + return ERROR_SUCCESS; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetCmdLineParameters( LPTSTR *pCmdLine ) +{ + int nRet = ERROR_SUCCESS; + LPTSTR pStart = NULL; + LPTSTR pNext = NULL; + + if ( GetNextArgument( *pCmdLine, NULL, &pNext ) != ERROR_SUCCESS ) + { + SetError( ERROR_NO_MORE_ITEMS ); + return false; + } + + int nSize = lstrlen( *pCmdLine ) + 2; + TCHAR *pNewCmdLine = new TCHAR[ nSize ]; + pNewCmdLine[0] = '\0'; + + while ( GetNextArgument( pNext, &pStart, &pNext ) == ERROR_SUCCESS ) + { + boolean bDeleteStart = true; + + if ( (*pStart) == '/' || (*pStart) == '-' ) + { + LPTSTR pSub = CharNext( pStart ); + if ( (*pSub) == 'l' || (*pSub) == 'L' ) + { + pSub = CharNext( pSub ); + if ( (*pSub) == 'a' || (*pSub) == 'A' ) + { // --- handle the lang parameter --- + LPTSTR pLanguage = NULL; + LPTSTR pLastChar; + if ( GetNextArgument( pNext, &pLanguage, &pNext, true ) != ERROR_SUCCESS ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); + nRet = ERROR_INVALID_PARAMETER; + break; + } + + m_nLanguageID = _tcstol( pLanguage, &pLastChar, 10 ); + delete [] pLanguage; + } + else + { // --- handle the l(og) parameter --- + boolean bAppend = false; + LPTSTR pFileName = NULL; + + while ( *pSub ) + { + if ( *pSub == '+' ) + { + bAppend = true; + break; + } + pSub = CharNext( pSub ); + } + + if ( GetNextArgument( pNext, &pFileName, &pNext, true ) != ERROR_SUCCESS ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); + nRet = ERROR_INVALID_PARAMETER; + break; + } + + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + // we need to append a '+' otherwise msiexec would overwrite our log file + if ( !bAppend && FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( "+" ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + if ( FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " \"" ) ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, pFileName ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( "\" " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + + if ( bAppend ) + m_pLogFile = _tfopen( pFileName, TEXT( "ab" ) ); + else + m_pLogFile = _tfopen( pFileName, TEXT( "wb" ) ); + + delete [] pFileName; + } + } + else if ( (*pSub) == 'q' || (*pSub) == 'Q' ) + { // --- Handle quiet file parameter --- + pSub = CharNext( pSub ); + if ( ! (*pSub) || (*pSub) == 'n' || (*pSub) == 'N' ) + m_bQuiet = true; + + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + } + else if ( _tcsnicmp( pSub, PARAM_RUNNING, _tcslen( PARAM_RUNNING ) ) == 0 ) + { + m_bIgnoreAlreadyRunning = true; + } + else if ( _tcsnicmp( pSub, CMDLN_REG_ALL_MSO_TYPES, _tcslen( CMDLN_REG_ALL_MSO_TYPES ) ) == 0 ) + { + m_bRegAllMsoTypes = true; + } + else if ( _tcsnicmp( pSub, CMDLN_REG_NO_MSO_TYPES, _tcslen( CMDLN_REG_NO_MSO_TYPES ) ) == 0 ) + { + m_bRegNoMsoTypes = true; + } + else if ( (*pSub) == 'i' || (*pSub) == 'I' || (*pSub) == 'f' || (*pSub) == 'F' || + (*pSub) == 'p' || (*pSub) == 'P' || (*pSub) == 'x' || (*pSub) == 'X' || + (*pSub) == 'y' || (*pSub) == 'Y' || (*pSub) == 'z' || (*pSub) == 'Z' ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); + nRet = ERROR_INVALID_PARAMETER; + break; + } + else if ( (*pSub) == 'a' || (*pSub) == 'A' ) + { // --- Handle Adminstrative Installation --- + SetAdminInstall( true ); + } + else if ( (*pSub) == 'j' || (*pSub) == 'J' ) + { // --- Handle Adminstrative Installation --- + m_pAdvertise = pStart; + m_bQuiet = true; + bDeleteStart = false; + } + else if ( (*pSub) == '?' || (*pSub) == 'h' || (*pSub) == 'H' ) + { // --- Handle Show Usage --- + nRet = ERROR_SHOW_USAGE; + break; + } + else + { + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + } + } + else + { + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + } + + if ( bDeleteStart ) delete [] pStart; + pStart = NULL; + } + + if ( pStart ) delete [] pStart; + + *pCmdLine = pNewCmdLine; + + if ( nRet != ERROR_SUCCESS ) + { + SetError( nRet ); + return false; + } + else + return true;; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::IsAdmin() +{ + PSID aPsidAdmin; + SID_IDENTIFIER_AUTHORITY aAuthority = SECURITY_NT_AUTHORITY; + + if ( !AllocateAndInitializeSid( &aAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, + &aPsidAdmin ) ) + return false; + + BOOL bIsAdmin = FALSE; + + if ( GetOSVersion() >= 5 ) + { + HMODULE hAdvapi32 = LoadLibrary( ADVAPI32_DLL ); + + if ( !hAdvapi32 ) + bIsAdmin = FALSE; + else + { + PFnCheckTokenMembership pfnCheckTokenMembership = (PFnCheckTokenMembership) GetProcAddress( hAdvapi32, ADVAPI32API_CheckTokenMembership); + if ( !pfnCheckTokenMembership || !pfnCheckTokenMembership( NULL, aPsidAdmin, &bIsAdmin ) ) + bIsAdmin = FALSE; + } + FreeLibrary( hAdvapi32 ); + } + else + { + // NT4, check groups of user + HANDLE hAccessToken = 0; + UCHAR *szInfoBuffer = new UCHAR[ 1024 ]; // may need to resize if TokenInfo too big + DWORD dwInfoBufferSize = 1024; + DWORD dwRetInfoBufferSize = 0; + UINT i=0; + + if ( WIN::OpenProcessToken( WIN::GetCurrentProcess(), TOKEN_READ, &hAccessToken ) ) + { + bool bSuccess = false; + bSuccess = WIN::GetTokenInformation( hAccessToken, TokenGroups, + szInfoBuffer, dwInfoBufferSize, + &dwRetInfoBufferSize ) == TRUE; + + if( dwRetInfoBufferSize > dwInfoBufferSize ) + { + delete [] szInfoBuffer; + szInfoBuffer = new UCHAR[ dwRetInfoBufferSize ]; + dwInfoBufferSize = dwRetInfoBufferSize; + bSuccess = WIN::GetTokenInformation( hAccessToken, TokenGroups, + szInfoBuffer, dwInfoBufferSize, + &dwRetInfoBufferSize ) == TRUE; + } + + WIN::CloseHandle( hAccessToken ); + + if ( bSuccess ) + { + PTOKEN_GROUPS pGroups = (PTOKEN_GROUPS)(UCHAR*) szInfoBuffer; + for( i=0; i<pGroups->GroupCount; i++ ) + { + if( WIN::EqualSid( aPsidAdmin, pGroups->Groups[i].Sid ) ) + { + bIsAdmin = TRUE; + break; + } + } + } + + delete [] szInfoBuffer; + } + } + + WIN::FreeSid( aPsidAdmin ); + + return bIsAdmin ? true : false; +} + +//-------------------------------------------------------------------------- +LPTSTR SetupAppX::CopyIniFile( LPCTSTR pIniFile ) +{ + m_pTmpName = _ttempnam( TEXT( "C:\\" ), TEXT( "Setup" ) ); + + if ( !m_pTmpName ) + { + Log( TEXT( "ERROR: Could not create temp file\n" ) ); + return NULL; + } + + FILE *pOut = _tfopen( m_pTmpName, TEXT( "wb" ) ); + FILE *pIn = _tfopen( pIniFile, TEXT( "rb" ) ); + + if ( pOut && pIn ) + { + size_t nRead, nWritten; + BYTE pBuf[1024]; + + nRead = fread( pBuf, sizeof( BYTE ), 1024, pIn ); + while ( nRead && !ferror( pIn ) ) + { + nWritten = fwrite( pBuf, sizeof( BYTE ), nRead, pOut ); + if ( nWritten != nRead ) + { + Log( TEXT( "ERROR: Could not write all bytes to temp file\n" ) ); + break; + } + nRead = fread( pBuf, sizeof( BYTE ), 1024, pIn ); + } + } + + if ( pOut ) fclose( pOut ); + if ( pIn ) fclose( pIn ); + + return m_pTmpName; +} + +//-------------------------------------------------------------------------- +void SetupAppX::ConvertNewline( LPTSTR pText ) const +{ + int i=0; + + while ( pText[i] != 0 ) + { + if ( ( pText[i] == '\\' ) && ( pText[i+1] == 'n' ) ) + { + pText[i] = 0x0d; + pText[i+1] = 0x0a; + i+=2; + } + else + i+=1; + } +} + +//-------------------------------------------------------------------------- +LPTSTR SetupAppX::SetProdToAppTitle( LPCTSTR pProdName ) +{ + if ( !pProdName ) return m_pAppTitle; + + LPTSTR pAppProdTitle = new TCHAR[ MAX_STR_CAPTION ]; + pAppProdTitle[0] = '\0'; + + WIN::LoadString( m_hInst, IDS_APP_PROD_TITLE, pAppProdTitle, MAX_STR_CAPTION ); + + int nAppLen = lstrlen( pAppProdTitle ); + int nProdLen = lstrlen( pProdName ); + + if ( ( nAppLen == 0 ) || ( nProdLen == 0 ) ) + { + delete [] pAppProdTitle; + return m_pAppTitle; + } + + int nLen = nAppLen + nProdLen + 3; + + if ( nLen > STRSAFE_MAX_CCH ) return m_pAppTitle; + + LPTSTR pIndex = _tcsstr( pAppProdTitle, PRODUCT_NAME_VAR ); + + if ( pIndex ) + { + int nOffset = pIndex - pAppProdTitle; + int nVarLen = lstrlen( PRODUCT_NAME_VAR ); + + LPTSTR pNewTitle = new TCHAR[ nLen ]; + pNewTitle[0] = '\0'; + + if ( nOffset > 0 ) + { + StringCchCopyN( pNewTitle, nLen, pAppProdTitle, nOffset ); + } + + StringCchCat( pNewTitle, nLen, pProdName ); + + if ( nOffset + nVarLen < nAppLen ) + { + StringCchCat( pNewTitle, nLen, pIndex + nVarLen ); + } + + delete [] m_pAppTitle; + m_pAppTitle = pNewTitle; + } + + delete [] pAppProdTitle; + + return m_pAppTitle; +} + + +//-------------------------------------------------------------------------- +boolean SetupAppX::IsPatchInstalled( TCHAR* pBaseDir, TCHAR* pFileName ) +{ + if ( !m_bSupportsPatch ) + return false; + + PMSIHANDLE hSummaryInfo; + int nLen = lstrlen( pBaseDir ) + lstrlen( pFileName ) + 1; + TCHAR *szDatabasePath = new TCHAR [ nLen ]; + TCHAR sBuf[80]; + + StringCchCopy( szDatabasePath, nLen, pBaseDir ); + StringCchCat( szDatabasePath, nLen, pFileName ); + + UINT nRet = MsiGetSummaryInformation( NULL, szDatabasePath, 0, &hSummaryInfo ); + + if ( nRet != ERROR_SUCCESS ) + { + StringCchPrintf( sBuf, 80, TEXT("ERROR: IsPatchInstalled: MsiGetSummaryInformation returned %u.\r\n"), nRet ); + Log( sBuf ); + return false; + } + + UINT uiDataType; + LPTSTR szPatchID = new TCHAR[ 64 ]; + DWORD cchValueBuf = 64; + nRet = MsiSummaryInfoGetProperty( hSummaryInfo, PID_REVNUMBER, &uiDataType, NULL, NULL, szPatchID, &cchValueBuf ); + + if ( nRet != ERROR_SUCCESS ) + { + StringCchPrintf( sBuf, 80, TEXT("ERROR: IsPatchInstalled: MsiSummaryInfoGetProperty returned %u.\r\n"), nRet ); + Log( sBuf ); + return false; + } + + nRet = MsiGetPatchInfo( szPatchID, INSTALLPROPERTY_LOCALPACKAGE, NULL, NULL ); + + StringCchPrintf( sBuf, 80, TEXT(" GetPatchInfo for (%s) returned (%u)\r\n"), szPatchID, nRet ); + Log( sBuf ); + + delete []szPatchID; + + if ( nRet == ERROR_BAD_CONFIGURATION ) + return false; + else if ( nRet == ERROR_INVALID_PARAMETER ) + return false; + else if ( nRet == ERROR_MORE_DATA ) + return true; + else if ( nRet == ERROR_SUCCESS ) + return true; + else if ( nRet == ERROR_UNKNOWN_PRODUCT ) + return false; + else if ( nRet == ERROR_UNKNOWN_PROPERTY ) + return false; + else return false; + + return false; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::InstallRuntimes( TCHAR *sProductCode, TCHAR *sRuntimePath ) +{ + INSTALLSTATE nRet = MsiQueryProductState( sProductCode ); + OutputDebugStringFormat( TEXT( "MsiQueryProductState returned <%d>\r\n" ), nRet ); + if ( nRet == INSTALLSTATE_DEFAULT ) + return true; + + Log( TEXT( " Will install runtime <%s>\r\n" ), sRuntimePath ); + OutputDebugStringFormat( TEXT( " Will install runtime <%s>\r\n" ), sRuntimePath ); + + STARTUPINFO aSUI; + PROCESS_INFORMATION aPI; + + ZeroMemory( (void*)&aPI, sizeof( PROCESS_INFORMATION ) ); + ZeroMemory( (void*)&aSUI, sizeof( STARTUPINFO ) ); + + aSUI.cb = sizeof(STARTUPINFO); + aSUI.dwFlags = STARTF_USESHOWWINDOW; + aSUI.wShowWindow = SW_SHOW; + + DWORD nCmdLineLength = lstrlen( sRuntimePath ) + lstrlen( PARAM_SILENTINSTALL ) + 2; + TCHAR *sCmdLine = new TCHAR[ nCmdLineLength ]; + + if ( FAILED( StringCchCopy( sCmdLine, nCmdLineLength, sRuntimePath ) ) || + FAILED( StringCchCat( sCmdLine, nCmdLineLength, PARAM_SILENTINSTALL ) ) ) + { + delete [] sCmdLine; + SetError( ERROR_INSTALL_FAILURE ); + return false; + } + + if ( !WIN::CreateProcess( NULL, sCmdLine, NULL, NULL, FALSE, + CREATE_DEFAULT_ERROR_MODE, NULL, NULL, + &aSUI, &aPI ) ) + { + Log( TEXT( "ERROR: Could not create process %s.\r\n" ), sCmdLine ); + SetError( WIN::GetLastError() ); + delete [] sCmdLine; + return false; + } + + DWORD nResult = WaitForProcess( aPI.hProcess ); + bool bRet = true; + + if( ERROR_SUCCESS != nResult ) + { + Log( TEXT( "ERROR: While waiting for %s.\r\n" ), sCmdLine ); + SetError( nResult ); + bRet = false; + } + else + { + GetExitCodeProcess( aPI.hProcess, &nResult ); + SetError( nResult ); + + if ( nResult != ERROR_SUCCESS ) + { + TCHAR sBuf[80]; + StringCchPrintf( sBuf, 80, TEXT("Warning: install runtime returned %u.\r\n"), nResult ); + Log( sBuf ); + } + else + Log( TEXT( " Installation of runtime completed successfully.\r\n" ) ); + } + + CloseHandle( aPI.hProcess ); + + delete [] sCmdLine; + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::InstallRuntimes() +{ + TCHAR *sRuntimePath = 0; + SYSTEM_INFO siSysInfo; + + HMODULE hKernel32 = ::LoadLibrary(_T("Kernel32.dll")); + if ( hKernel32 != NULL ) + { + typedef void (CALLBACK* pfnGetNativeSystemInfo_t)(LPSYSTEM_INFO); + pfnGetNativeSystemInfo_t pfnGetNativeSystemInfo; + pfnGetNativeSystemInfo = (pfnGetNativeSystemInfo_t)::GetProcAddress(hKernel32, "GetNativeSystemInfo"); + if ( pfnGetNativeSystemInfo != NULL ) + { + pfnGetNativeSystemInfo(&siSysInfo); + } + else + { + // GetNativeSystemInfo does not exist. Maybe the code is running under Windows 2000. + // Use GetSystemInfo instead. + GetSystemInfo(&siSysInfo); + } + FreeLibrary(hKernel32); + } + else + { + // Failed to check Kernel32.dll. There may be something wrong. + // Use GetSystemInfo instead anyway. + GetSystemInfo(&siSysInfo); + } + + OutputDebugStringFormat( TEXT( "found architecture<%d>\r\n" ), siSysInfo.wProcessorArchitecture ); + + if ( siSysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ) + { + if ( GetPathToFile( RUNTIME_X64_NAME, &sRuntimePath ) ) + InstallRuntimes( PRODUCTCODE_X64, sRuntimePath ); + else + Log( TEXT( "ERROR: no installer for x64 runtime libraries found!" ) ); + + if ( sRuntimePath ) + { + delete [] sRuntimePath; + sRuntimePath = 0; + } + } + + if ( GetPathToFile( RUNTIME_X86_NAME, &sRuntimePath ) ) + InstallRuntimes( PRODUCTCODE_X86, sRuntimePath ); + else + Log( TEXT( "ERROR: no installer for x86 runtime libraries found!" ) ); + + if ( sRuntimePath ) + delete [] sRuntimePath; + + return true; +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +LanguageDataX::LanguageDataX( LPTSTR pData ) +{ + m_nLanguageID = 0; + m_pTransform = NULL; + + LPTSTR pLastChar; + + m_nLanguageID = _tcstol( pData, &pLastChar, 10 ); + + if ( *pLastChar == ',' ) + { + pLastChar += 1; + int nLen = lstrlen( pLastChar ) + 1; + m_pTransform = new TCHAR [ nLen ]; + StringCchCopy( m_pTransform, nLen, pLastChar ); + } +} + +//-------------------------------------------------------------------------- +LanguageDataX::~LanguageDataX() +{ + if ( m_pTransform ) delete [] m_pTransform; +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +SetupApp* Create_SetupAppX() +{ + return new SetupAppX; +} + +//-------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup.hxx b/desktop/win32/source/setup/setup.hxx new file mode 100644 index 000000000000..6eccda100699 --- /dev/null +++ b/desktop/win32/source/setup/setup.hxx @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "setup_main.hxx" + +//-------------------------------------------------------------------------- + +#ifdef SetupAppX + #undef SetupAppX +#endif + +#ifdef Create_SetupAppX + #undef Create_SetupAppX +#endif + +#ifdef LanguageDataX + #undef LanguageDataX +#endif + + +#ifdef UNICODE + #define SetupAppX SetupAppW + #define Create_SetupAppX Create_SetupAppW + #define LanguageDataX LanguageDataW +#else + #define SetupAppX SetupAppA + #define Create_SetupAppX Create_SetupAppA + #define LanguageDataX LanguageDataA +#endif + +//-------------------------------------------------------------------------- + +struct LanguageDataX +{ + long m_nLanguageID; + LPTSTR m_pTransform; + + LanguageDataX( LPTSTR pData ); + ~LanguageDataX(); +}; + +//-------------------------------------------------------------------------- + +class SetupAppX : public SetupApp +{ + HINSTANCE m_hInst; + HANDLE m_hMapFile; + LPTSTR m_pAppTitle; + LPTSTR m_pCmdLine; + LPTSTR m_pDatabase; + LPTSTR m_pReqVersion; + LPTSTR m_pProductName; + LPTSTR m_pAdvertise; + LPTSTR m_pTmpName; + LPTSTR m_pErrorText; + LPTSTR m_pModuleFile; + LPTSTR m_pPatchFiles; + LPCTSTR m_pUpgradeKey; + LPCTSTR m_pProductVersion; + int *m_pMSIErrorCode; + + boolean m_bQuiet : 1; + boolean m_bIgnoreAlreadyRunning : 1; + boolean m_bRegNoMsoTypes :1; + boolean m_bRegAllMsoTypes :1; + boolean m_bIsMinorUpgrade :1; + boolean m_bSupportsPatch :1; + + FILE *m_pLogFile; + + long m_nLanguageID; + long m_nLanguageCount; + LanguageDataX** m_ppLanguageList; + +private: + + boolean GetPathToFile( TCHAR* pFileName, TCHAR **pPath ); + LPCTSTR GetPathToMSI(); + + int GetNameValue( TCHAR* pLine, TCHAR **pName, TCHAR **pValue ); + boolean GetProfileSection( LPCTSTR pFileName, LPCTSTR pSection, + DWORD& rSize, LPTSTR *pRetBuf ); + LPTSTR CopyIniFile( LPCTSTR pIniFile ); + void ConvertNewline( LPTSTR pText ) const; + + boolean LaunchInstaller( LPCTSTR pParam ); + HMODULE LoadMsiLibrary(); + DWORD WaitForProcess( HANDLE hHandle ); + + boolean GetCmdLineParameters( LPTSTR *pCmdLine ); + DWORD GetNextArgument( LPCTSTR pStr, LPTSTR *pArg, + LPTSTR *pNext, boolean bStripQuotes = false ); + boolean IsAdmin(); + + boolean GetCommandLine(); + + boolean IsTerminalServerInstalled() const; + void AddFileToPatchList( TCHAR* pPath, TCHAR* pFile ); + boolean IsPatchInstalled( TCHAR* pBaseDir, TCHAR* pFileName ); + boolean InstallRuntimes( TCHAR* pProductCode, TCHAR* pFileName ); + +public: + SetupAppX(); + ~SetupAppX(); + + virtual boolean Initialize( HINSTANCE hInst ); + virtual boolean AlreadyRunning() const; + virtual boolean ReadProfile(); + virtual boolean GetPatches(); + virtual boolean ChooseLanguage( long& rLanguage ); + virtual boolean CheckVersion(); + virtual boolean CheckForUpgrade(); + virtual boolean InstallRuntimes(); + virtual boolean Install( long nLanguage ); + + virtual UINT GetError() const; + virtual void DisplayError( UINT nErr ) const; + + void Log( LPCTSTR pMessage, LPCTSTR pText = NULL ) const; + + long GetLanguageCount() const { return m_nLanguageCount; } + long GetLanguageID( long nIndex ) const; + void GetLanguageName( long nLanguage, LPTSTR sName ) const; + + LPCTSTR GetAppTitle() const { return m_pAppTitle; } + LPTSTR SetProdToAppTitle( LPCTSTR pProdName ); + HINSTANCE GetHInst() const { return m_hInst; } +}; + +//-------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup.ico b/desktop/win32/source/setup/setup.ico Binary files differnew file mode 100644 index 000000000000..2a7ebda53a25 --- /dev/null +++ b/desktop/win32/source/setup/setup.ico diff --git a/desktop/win32/source/setup/setup.ulf b/desktop/win32/source/setup/setup.ulf new file mode 100644 index 000000000000..85d43f43aa55 --- /dev/null +++ b/desktop/win32/source/setup/setup.ulf @@ -0,0 +1,162 @@ +[%APP_TITLE%] +en-US = "Setup" + + +[%APP_PROD_TITLE%] +en-US = "The %PRODUCTNAME Setup" + + +[%OUTOFMEM%] +en-US = "Out of Memory" + + +[%NOMSI%] +en-US = "Setup was unable to find the msi package." + + +[%USER_CANCELLED%] +en-US = "Setup was cancelled" + + +[%REQUIRES_ADMIN_PRIV%] +en-US = "Administrator privileges are required for upgrading the Windows Installer." + + +[%FILE_NOT_FOUND%] +en-US = "Setup was unable to find the file '%s'." + + +[%INVALID_PARAM%] +en-US = "Invalid command line option '%s'. Please use '/?' for help." + + +[%SETUP_TO_OLD%] +en-US = "This package requires at least the version '%s' of the Windows Installer. \nYou have Windows Installer '%s' on your system!" + +[%SETUP_NOT_FOUND%] +en-US = "This package requires the Windows Installer. \nYou need at least Windows Installer '%s' on your system!" + + +[%USAGE%] +en-US = "Usage:\n /? : Shows this dialog.\n /a : Performs an administrative installation.\n /j[u|m] : Performs an advertising installation.\n /q[n] : Do not show any user interface (silent mode).\n" + + +[%ALREADY_RUNNING%] +en-US = "There is already a setup process running." + + +[%UNKNOWN_ERROR%] +en-US = "An Unknown Error occurred!" + + +[%INVALID_PROFILE%] +en-US = "Invalid or incomplete profile." + + +[%UNKNOWN_LANG%] +en-US = "Unknown Language: %d" + + +[%LANGUAGE_ZH_TW%] +en-US = "Chinese (traditional)" + + +[%LANGUAGE_CS%] +en-US = "Czech" + + +[%LANGUAGE_DA%] +en-US = "Danish" + + +[%LANGUAGE_DE_DE%] +en-US = "German (Germany)" + + +[%LANGUAGE_EL%] +en-US = "Greek" + + +[%LANGUAGE_EN_US%] +en-US = "English (USA)" + + +[%LANGUAGE_ES%] +en-US = "Spanish (Spain)" + + +[%LANGUAGE_FI%] +en-US = "Finnish" + + +[%LANGUAGE_FR_FR%] +en-US = "French (France)" + + +[%LANGUAGE_HE%] +en-US = "Hebrew" + + +[%LANGUAGE_HU%] +en-US = "Hungarian" + + +[%LANGUAGE_IT_IT%] +en-US = "Italian (Italy)" + + +[%LANGUAGE_JA%] +en-US = "Japanese" + + +[%LANGUAGE_KO%] +en-US = "Korean" + + +[%LANGUAGE_NL_NL%] +en-US = "Dutch (Netherlands)" + + +[%LANGUAGE_NO_NO%] +en-US = "Norwegian (Bokmål)" + + +[%LANGUAGE_PL%] +en-US = "Polish" + + +[%LANGUAGE_PT_BR%] +en-US = "Portuguese (Brazil)" + + +[%LANGUAGE_RU%] +en-US = "Russian" + + +[%LANGUAGE_SK%] +en-US = "Slovakian" + + +[%LANGUAGE_SV_SE%] +en-US = "Swedish (Sweden)" + + +[%LANGUAGE_TH%] +en-US = "Thai" + + +[%LANGUAGE_TR%] +en-US = "Turkish" + + +[%LANGUAGE_ET%] +en-US = "Estonian" + + +[%LANGUAGE_ZH_CN%] +en-US = "Chinese (Simplified)" + + +[%LANGUAGE_PT_PT%] +en-US = "Portuguese (Portugal)" + diff --git a/desktop/win32/source/setup/setup_help.hxx b/desktop/win32/source/setup/setup_help.hxx new file mode 100644 index 000000000000..1330fa70f191 --- /dev/null +++ b/desktop/win32/source/setup/setup_help.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 SETUP_HELP_HXX +#define SETUP_HELP_HXX + +//-------------------------------------------------------------------------- + + +#ifdef UNICODE +#else + #define LanguageDataX LanguageDataA +#endif + +//-------------------------------------------------------------------------- + +class SetupHelperX +{ +}; + +//-------------------------------------------------------------------------- + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup_main.cxx b/desktop/win32/source/setup/setup_main.cxx new file mode 100644 index 000000000000..0fb9aac2533e --- /dev/null +++ b/desktop/win32/source/setup/setup_main.cxx @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <new> + +#include "setup_main.hxx" + +//-------------------------------------------------------------------------- + +void __cdecl newhandler() +{ + throw std::bad_alloc(); + return; +} + +//-------------------------------------------------------------------------- + +SetupApp::SetupApp() +{ + m_uiRet = ERROR_SUCCESS; + + // Get OS version + OSVERSIONINFO sInfoOS; + + ZeroMemory( &sInfoOS, sizeof(OSVERSIONINFO) ); + sInfoOS.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); + + GetVersionEx( &sInfoOS ); + + m_nOSVersion = sInfoOS.dwMajorVersion; + m_nMinorVersion = sInfoOS.dwMinorVersion; + m_bNeedReboot = false; + m_bAdministrative = false; +} + +//-------------------------------------------------------------------------- + +SetupApp::~SetupApp() +{ +} + +//-------------------------------------------------------------------------- + +extern "C" int __stdcall WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int ) +{ + // Get OS version + OSVERSIONINFO sInfoOS; + + ZeroMemory( &sInfoOS, sizeof(OSVERSIONINFO) ); + sInfoOS.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); + + GetVersionEx( &sInfoOS ); + + SetupApp *pSetup; + + pSetup = Create_SetupAppW(); + + try + { + if ( ! pSetup->Initialize( hInst ) ) + throw pSetup->GetError(); + + if ( pSetup->AlreadyRunning() ) + throw (UINT) ERROR_INSTALL_ALREADY_RUNNING; + + if ( ! pSetup->ReadProfile() ) + throw pSetup->GetError(); + + if ( ! pSetup->CheckVersion() ) + throw pSetup->GetError(); + + if ( ! pSetup->IsAdminInstall() ) + if ( ! pSetup->GetPatches() ) + throw pSetup->GetError(); + + // CheckForUpgrade() has to be called after calling GetPatches()! + if ( ! pSetup->CheckForUpgrade() ) + throw pSetup->GetError(); + + long nLanguage; + + if ( ! pSetup->ChooseLanguage( nLanguage ) ) + throw pSetup->GetError(); + + if ( ! pSetup->InstallRuntimes() ) + throw pSetup->GetError(); + + if ( ! pSetup->Install( nLanguage ) ) + throw pSetup->GetError(); + } + catch ( std::bad_alloc ) + { + pSetup->DisplayError( ERROR_OUTOFMEMORY ); + } + catch ( UINT &nErr ) + { + pSetup->DisplayError( nErr ); + } + + int nRet = pSetup->GetError(); + + delete pSetup; + + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup_main.hxx b/desktop/win32/source/setup/setup_main.hxx new file mode 100644 index 000000000000..dfcb201e3cd3 --- /dev/null +++ b/desktop/win32/source/setup/setup_main.hxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 SETUP_MAIN_HXX +#define SETUP_MAIN_HXX + +class SetupApp +{ + DWORD m_nOSVersion; + DWORD m_nMinorVersion; + boolean m_bNeedReboot : 1; + boolean m_bAdministrative : 1; + +public: + UINT m_uiRet; + + SetupApp(); + virtual ~SetupApp(); + + virtual boolean Initialize( HINSTANCE hInst ) = 0; + virtual boolean AlreadyRunning() const = 0; + virtual boolean ReadProfile() = 0; + virtual boolean GetPatches() = 0; + virtual boolean ChooseLanguage( long& rLanguage ) = 0; + virtual boolean CheckVersion() = 0; + virtual boolean CheckForUpgrade() = 0; + virtual boolean InstallRuntimes() = 0; + virtual boolean Install( long nLanguage ) = 0; + + virtual UINT GetError() const = 0; + virtual void DisplayError( UINT nErr ) const = 0; + + void SetError( UINT nErr ) { m_uiRet = nErr; } + DWORD GetOSVersion() const { return m_nOSVersion; } + DWORD GetMinorVersion() const { return m_nMinorVersion; } + + boolean IsAdminInstall() { return m_bAdministrative; } + void SetAdminInstall( boolean bValue ) { m_bAdministrative = bValue; } + + void SetRebootNeeded( boolean bNeedReboot ) { m_bNeedReboot = bNeedReboot; } + boolean NeedReboot() const { return m_bNeedReboot; } +}; + +SetupApp* Create_SetupAppW(); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup_w.cxx b/desktop/win32/source/setup/setup_w.cxx new file mode 100644 index 000000000000..9de15b2e535d --- /dev/null +++ b/desktop/win32/source/setup/setup_w.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" + +#define UNICODE 1 +#define _UNICODE 1 + +#include "setup.cpp" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/sowrapper.cxx b/desktop/win32/source/sowrapper.cxx new file mode 100644 index 000000000000..f62536a86525 --- /dev/null +++ b/desktop/win32/source/sowrapper.cxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include "main.h" + +int APIENTRY WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) +{ + if ( (LONG)GetVersion() < 0 ) + return MainA(); + else + return MainW(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/unoinfo.cxx b/desktop/win32/source/unoinfo.cxx new file mode 100644 index 000000000000..0ce5c98b7215 --- /dev/null +++ b/desktop/win32/source/unoinfo.cxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 <cstddef> +#include <stdio.h> +#include <stdlib.h> +#include <wchar.h> + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include "tools/pathutils.hxx" + +#define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1) +#define MY_STRING(s) (s), MY_LENGTH(s) + +namespace { + +wchar_t * getBrandPath(wchar_t * path) { + DWORD n = GetModuleFileNameW(NULL, path, MAX_PATH); + if (n == 0 || n >= MAX_PATH) { + exit(EXIT_FAILURE); + } + return tools::filename(path); +} + +void writeNull() { + if (fwrite("\0\0", 1, 2, stdout) != 2) { + exit(EXIT_FAILURE); + } +} + +void writePath( + wchar_t const * frontBegin, wchar_t const * frontEnd, + wchar_t const * backBegin, std::size_t backLength) +{ + wchar_t path[MAX_PATH]; + wchar_t * end = tools::buildPath( + path, frontBegin, frontEnd, backBegin, backLength); + if (end == NULL) { + exit(EXIT_FAILURE); + } + std::size_t n = (end - path) * sizeof (wchar_t); + if (fwrite(path, 1, n, stdout) != n) { + exit(EXIT_FAILURE); + } +} + +} + +#ifdef __MINGW32__ +int main(int argc, char ** argv, char **) { + if (argc == 2 && strcmp(argv[1], "c++") == 0) { +#else +int wmain(int argc, wchar_t ** argv, wchar_t **) { + if (argc == 2 && wcscmp(argv[1], L"c++") == 0) { +#endif + wchar_t path[MAX_PATH]; + wchar_t * pathEnd = getBrandPath(path); + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"..\\basis-link")) + == NULL) + { + exit(EXIT_FAILURE); + } + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL || + (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == + NULL)) + { + exit(EXIT_FAILURE); + } + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL) { + exit(EXIT_FAILURE); + } + writePath(path, pathEnd, MY_STRING(L"\\bin")); +#ifdef __MINGW32__ + } else if (argc == 2 && strcmp(argv[1], "java") == 0) { +#else + } else if (argc == 2 && wcscmp(argv[1], L"java") == 0) { +#endif + if (fwrite("1", 1, 1, stdout) != 1) { + exit(EXIT_FAILURE); + } + wchar_t path[MAX_PATH]; + wchar_t * pathEnd = getBrandPath(path); + writePath(path, pathEnd, MY_STRING(L"")); + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"..\\basis-link")) + == NULL) + { + exit(EXIT_FAILURE); + } + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL) { + exit(EXIT_FAILURE); + } + writeNull(); + writePath(path, pathEnd, MY_STRING(L"\\program\\classes\\unoil.jar")); + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == + NULL) + { + exit(EXIT_FAILURE); + } + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL) { + exit(EXIT_FAILURE); + } + writeNull(); + writePath(path, pathEnd, MY_STRING(L"\\java\\ridl.jar")); + writeNull(); + writePath(path, pathEnd, MY_STRING(L"\\java\\jurt.jar")); + writeNull(); + writePath(path, pathEnd, MY_STRING(L"\\java\\juh.jar")); + } else { + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/wrapper.h b/desktop/win32/source/wrapper.h new file mode 100755 index 000000000000..f0ff5b617f99 --- /dev/null +++ b/desktop/win32/source/wrapper.h @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#pragma once +#ifndef __cplusplus +#error Need C++ to compile +#endif + +#include "main.h" + +#ifndef _WINDOWS_ +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +# include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#endif + + +#ifndef _INC_TCHAR +# ifdef UNICODE +# define _UNICODE +# endif +# include <tchar.h> +#endif + +#ifdef UNICODE +# define Main MainW +# define GetArgv( pArgc ) CommandLineToArgvW( GetCommandLine(), pArgc ) +# define PROCESS_CREATIONFLAGS CREATE_UNICODE_ENVIRONMENT +#else +# define GetArgv( pArgc ) (*pArgc = __argc, __argv) +# define PROCESS_CREATIONFLAGS 0 +# define Main MainA +#endif + +#define BIN_EXT_STR TEXT(".bin") +#define PARAM_LIBPATH_STR TEXT("-libpath=") +#define PARAM_LOCAL_STR TEXT("-local") +#define PARAM_REMOTE_STR TEXT("-remote") + +#if defined( REMOTE ) +#define DEFAULT_LIBPATH TEXT("remote;") +#elif defined( LOCAL ) +#define DEFAULT_LIBPATH TEXT("local;") +#endif + +extern "C" int Main() +{ + // Retreive startup info + + STARTUPINFO aStartupInfo; + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof( aStartupInfo ); + GetStartupInfo( &aStartupInfo ); + + // Retrieve command line + + LPTSTR lpCommandLine = GetCommandLine(); + + LPTSTR *ppArguments = NULL; + int nArguments = 0; + + ppArguments = GetArgv( &nArguments ); + + // Calculate application name + + + TCHAR szApplicationName[MAX_PATH]; + TCHAR szDrive[MAX_PATH]; + TCHAR szDir[MAX_PATH]; + TCHAR szFileName[MAX_PATH]; + TCHAR szExt[MAX_PATH]; + + GetModuleFileName( NULL, szApplicationName, MAX_PATH ); + _tsplitpath( szApplicationName, szDrive, szDir, szFileName, szExt ); + _tmakepath( szApplicationName, szDrive, szDir, szFileName, BIN_EXT_STR ); + + // Retreive actual environment + + TCHAR szBuffer[1024]; + TCHAR szPathValue[1024] = TEXT(""); + +#ifdef DEFAULT_LIBPATH + _tmakepath( szPathValue, szDrive, szDir, DEFAULT_LIBPATH, TEXT("") ); +#endif + + for ( int argn = 1; argn < nArguments; argn++ ) + { + if ( 0 == _tcscmp( ppArguments[argn], PARAM_REMOTE_STR ) ) + { + _tmakepath( szPathValue, szDrive, szDir, TEXT("remote;"), TEXT("") ); + break; + } + else if ( 0 == _tcscmp( ppArguments[argn], PARAM_LOCAL_STR ) ) + { + _tmakepath( szPathValue, szDrive, szDir, TEXT("local;"), TEXT("") ); + break; + } + else if ( 0 == _tcsncmp( ppArguments[argn], PARAM_LIBPATH_STR, _tcslen(PARAM_LIBPATH_STR) ) ) + { + LPTSTR pFileSpec = NULL; + + GetFullPathName( ppArguments[argn] + _tcslen(PARAM_LIBPATH_STR), sizeof(szPathValue) / sizeof(TCHAR), szPathValue, &pFileSpec ); + _tcscat( szPathValue, TEXT(";") ); + break; + } + } + + GetEnvironmentVariable( TEXT("PATH"), szBuffer, sizeof(szBuffer) ); + _tcscat( szPathValue, szBuffer ); + SetEnvironmentVariable( TEXT("PATH"), szPathValue); + + LPVOID lpEnvironment = GetEnvironmentStrings(); + + + // Retrieve current directory + + TCHAR szCurrentDirectory[MAX_PATH]; + GetCurrentDirectory( MAX_PATH, szCurrentDirectory ); + + // Set the Flags + + DWORD dwCreationFlags = PROCESS_CREATIONFLAGS; + + PROCESS_INFORMATION aProcessInfo; + + BOOL fSuccess = CreateProcess( + szApplicationName, + lpCommandLine, + NULL, + NULL, + TRUE, + dwCreationFlags, + lpEnvironment, + szCurrentDirectory, + &aStartupInfo, + &aProcessInfo ); + + if ( fSuccess ) + { + DWORD dwExitCode; + + WaitForSingleObject( aProcessInfo.hProcess, INFINITE ); + fSuccess = GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode ); + + return dwExitCode; + } + + DWORD dwError = GetLastError(); + + LPVOID lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&lpMsgBuf, + 0, + NULL + ); + + // Display the string. + MessageBox( NULL, (LPCTSTR)lpMsgBuf, NULL, MB_OK | MB_ICONERROR ); + + // Free the buffer. + LocalFree( lpMsgBuf ); + + return GetLastError(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/wrappera.cxx b/desktop/win32/source/wrappera.cxx new file mode 100644 index 000000000000..0a74b1030a3a --- /dev/null +++ b/desktop/win32/source/wrappera.cxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/wrapperw.cxx b/desktop/win32/source/wrapperw.cxx new file mode 100644 index 000000000000..d76ca9b678ad --- /dev/null +++ b/desktop/win32/source/wrapperw.cxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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" +#define UNICODE +#include "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/zipintro/delzip b/desktop/zipintro/delzip new file mode 100755 index 000000000000..8b137891791f --- /dev/null +++ b/desktop/zipintro/delzip @@ -0,0 +1 @@ + diff --git a/desktop/zipintro/makefile.mk b/desktop/zipintro/makefile.mk new file mode 100755 index 000000000000..c0f14068823f --- /dev/null +++ b/desktop/zipintro/makefile.mk @@ -0,0 +1,92 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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=zipintro + +.INCLUDE : settings.mk + +ZIP1LIST= \ + $(MISC)$/$(RSCDEFIMG)$/brand$/intro.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/about.png +ZIP2LIST= \ + $(MISC)$/$(RSCDEFIMG)$/brand_dev$/intro.png \ + $(MISC)$/$(RSCDEFIMG)$/brand_dev$/about.png +ZIP3LIST= \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_left.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_right.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_space.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_rtl_left.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_rtl_right.png + +ZIP1TARGET=brand +ZIP1DEPS=$(ZIP1LIST) +ZIP2TARGET=brand_dev +ZIP2DEPS=$(ZIP2LIST) +ZIP3TARGET=shell +ZIP3DEPS=$(ZIP3LIST) + +.INCLUDE : target.mk + +ALLTAR : \ + $(COMMONBIN)$/intro.zip \ + $(COMMONBIN)$/brand_dev$/intro.zip \ + $(COMMONBIN)$/shell/shell.zip + +$(COMMONBIN)$/brand_dev$/intro.zip : $(COMMONBIN)$/brand_dev.zip + @@-$(MKDIR) $(@:d) + @$(COPY) $< $@ + +$(COMMONBIN)$/intro.zip : $(COMMONBIN)$/brand.zip + @@-$(MKDIR) $(@:d) + @$(COPY) $< $@ + +$(COMMONBIN)$/shell$/shell.zip : $(COMMONBIN)$/shell.zip + @@-$(MKDIR) $(@:d) + @$(COPY) $< $@ + +$(MISC)$/%.bmp : $(SOLARSRC)$/%.bmp + @@-$(MKDIRHIER) $(@:d) + $(COPY) $< $@ + +$(MISC)$/%.png : $(SOLARSRC)$/%.png + @@-$(MKDIRHIER) $(@:d) + $(COPY) $< $@ + +.IF "$(INTRO_BITMAP)" != "" +$(MISC)$/$(RSCDEFIMG)$/brand$/intro.png : $(INTRO_BITMAP) + @@-$(MKDIRHIER) $(@:d) + $(COPY) $< $@ +.ENDIF + +.IF "$(ABOUT_BITMAP)" != "" +$(MISC)$/$(RSCDEFIMG)$/brand$/about.png : $(ABOUT_BITMAP) + @@-$(MKDIRHIER) $(@:d) + $(COPY) $< $@ +.ENDIF |