16d739b60SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 36d739b60SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 46d739b60SAndrew Rist * or more contributor license agreements. See the NOTICE file 56d739b60SAndrew Rist * distributed with this work for additional information 66d739b60SAndrew Rist * regarding copyright ownership. The ASF licenses this file 76d739b60SAndrew Rist * to you under the Apache License, Version 2.0 (the 86d739b60SAndrew Rist * "License"); you may not use this file except in compliance 96d739b60SAndrew Rist * with the License. You may obtain a copy of the License at 106d739b60SAndrew Rist * 116d739b60SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 126d739b60SAndrew Rist * 136d739b60SAndrew Rist * Unless required by applicable law or agreed to in writing, 146d739b60SAndrew Rist * software distributed under the License is distributed on an 156d739b60SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 166d739b60SAndrew Rist * KIND, either express or implied. See the License for the 176d739b60SAndrew Rist * specific language governing permissions and limitations 186d739b60SAndrew Rist * under the License. 196d739b60SAndrew Rist * 206d739b60SAndrew Rist *************************************************************/ 216d739b60SAndrew Rist 226d739b60SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_framework.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include "services/autorecovery.hxx" 28cdf0e10cSrcweir #include <loadenv/loadenv.hxx> 29cdf0e10cSrcweir 30cdf0e10cSrcweir //_______________________________________________ 31cdf0e10cSrcweir // own includes 32cdf0e10cSrcweir #include <loadenv/targethelper.hxx> 33cdf0e10cSrcweir #include <pattern/frame.hxx> 34cdf0e10cSrcweir #include <threadhelp/readguard.hxx> 35cdf0e10cSrcweir #include <threadhelp/writeguard.hxx> 36cdf0e10cSrcweir 37cdf0e10cSrcweir #include <classes/resource.hrc> 38cdf0e10cSrcweir #include <classes/fwkresid.hxx> 39cdf0e10cSrcweir #include <protocols.h> 40cdf0e10cSrcweir #include <properties.h> 41cdf0e10cSrcweir #include <services.h> 42cdf0e10cSrcweir 43cdf0e10cSrcweir //_______________________________________________ 44cdf0e10cSrcweir // interface includes 45cdf0e10cSrcweir #include <com/sun/star/ucb/NameClash.hpp> 46cdf0e10cSrcweir #include <com/sun/star/container/XNameAccess.hpp> 47cdf0e10cSrcweir #include <com/sun/star/frame/XLoadable.hpp> 48cdf0e10cSrcweir #include <com/sun/star/frame/XModel2.hpp> 49cdf0e10cSrcweir #include <com/sun/star/frame/XModuleManager.hpp> 50cdf0e10cSrcweir #include <com/sun/star/frame/XTitle.hpp> 51cdf0e10cSrcweir #include <com/sun/star/frame/XFrame.hpp> 52cdf0e10cSrcweir #include <com/sun/star/frame/XDispatchProvider.hpp> 53cdf0e10cSrcweir #include <com/sun/star/frame/DispatchResultState.hpp> 54cdf0e10cSrcweir #include <com/sun/star/frame/XNotifyingDispatch.hpp> 55cdf0e10cSrcweir #include <com/sun/star/frame/XController.hpp> 56cdf0e10cSrcweir #include <com/sun/star/frame/XModel.hpp> 57cdf0e10cSrcweir #include <com/sun/star/frame/XStorable.hpp> 58cdf0e10cSrcweir #include <com/sun/star/util/XModifiable.hpp> 59cdf0e10cSrcweir #include <com/sun/star/util/XURLTransformer.hpp> 60cdf0e10cSrcweir #include <com/sun/star/frame/XDesktop.hpp> 61cdf0e10cSrcweir #include <com/sun/star/container/XHierarchicalNameAccess.hpp> 62cdf0e10cSrcweir #include <com/sun/star/container/XNameContainer.hpp> 63cdf0e10cSrcweir #include <com/sun/star/util/XChangesNotifier.hpp> 64cdf0e10cSrcweir #include <com/sun/star/util/XChangesBatch.hpp> 65cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp> 66cdf0e10cSrcweir #include <com/sun/star/beans/PropertyAttribute.hpp> 67cdf0e10cSrcweir #include <com/sun/star/container/XContainerQuery.hpp> 68cdf0e10cSrcweir #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> 69cdf0e10cSrcweir #include <com/sun/star/document/XDocumentRecovery.hpp> 70cdf0e10cSrcweir #include <com/sun/star/util/XCloseable.hpp> 71cdf0e10cSrcweir #include <com/sun/star/awt/XWindow2.hpp> 72cdf0e10cSrcweir #include <com/sun/star/task/XStatusIndicatorFactory.hpp> 73cdf0e10cSrcweir 74cdf0e10cSrcweir //_______________________________________________ 75cdf0e10cSrcweir // other includes 76cdf0e10cSrcweir #include <comphelper/configurationhelper.hxx> 77cdf0e10cSrcweir #include <comphelper/mediadescriptor.hxx> 78cdf0e10cSrcweir #include <comphelper/namedvaluecollection.hxx> 79cdf0e10cSrcweir #include <vcl/svapp.hxx> 80cdf0e10cSrcweir #include <unotools/pathoptions.hxx> 81cdf0e10cSrcweir #include <tools/link.hxx> 82cdf0e10cSrcweir #include <tools/string.hxx> 83cdf0e10cSrcweir #include <tools/diagnose_ex.h> 84cdf0e10cSrcweir #include <unotools/tempfile.hxx> 85cdf0e10cSrcweir #include <ucbhelper/content.hxx> 86cdf0e10cSrcweir 87cdf0e10cSrcweir #include <osl/time.h> 88cdf0e10cSrcweir #include <vcl/msgbox.hxx> 89cdf0e10cSrcweir #include <osl/file.hxx> 90cdf0e10cSrcweir #include <unotools/bootstrap.hxx> 91cdf0e10cSrcweir #include <unotools/configmgr.hxx> 92cdf0e10cSrcweir #include <svl/documentlockfile.hxx> 93cdf0e10cSrcweir #include <cppuhelper/exc_hlp.hxx> 94cdf0e10cSrcweir 95cdf0e10cSrcweir #include <tools/urlobj.hxx> 96cdf0e10cSrcweir 97cdf0e10cSrcweir #include <fwkdllapi.h> 98cdf0e10cSrcweir 99cdf0e10cSrcweir //_______________________________________________ 100cdf0e10cSrcweir // namespaces 101cdf0e10cSrcweir 102cdf0e10cSrcweir #ifndef css 103cdf0e10cSrcweir namespace css = ::com::sun::star; 104cdf0e10cSrcweir #endif 105cdf0e10cSrcweir 106cdf0e10cSrcweir using ::com::sun::star::uno::Sequence; 107cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY; 108cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY_THROW; 109cdf0e10cSrcweir using ::com::sun::star::uno::UNO_SET_THROW; 110cdf0e10cSrcweir using ::com::sun::star::uno::Reference; 111cdf0e10cSrcweir using ::com::sun::star::uno::Any; 112cdf0e10cSrcweir using ::com::sun::star::beans::PropertyValue; 113cdf0e10cSrcweir using ::com::sun::star::container::XEnumeration; 114cdf0e10cSrcweir using ::com::sun::star::document::XDocumentRecovery; 115cdf0e10cSrcweir using ::com::sun::star::frame::XModel2; 116cdf0e10cSrcweir using ::com::sun::star::frame::XModel; 117cdf0e10cSrcweir using ::com::sun::star::frame::XFrame; 118cdf0e10cSrcweir using ::com::sun::star::frame::XController2; 119cdf0e10cSrcweir using ::com::sun::star::frame::XLoadable; 120cdf0e10cSrcweir using ::com::sun::star::frame::XStorable; 121cdf0e10cSrcweir using ::com::sun::star::lang::XComponent; 122cdf0e10cSrcweir 123cdf0e10cSrcweir namespace fpf = ::framework::pattern::frame; 124cdf0e10cSrcweir 125cdf0e10cSrcweir 126cdf0e10cSrcweir namespace framework 127cdf0e10cSrcweir { 128cdf0e10cSrcweir 129cdf0e10cSrcweir //----------------------------------------------- 130cdf0e10cSrcweir // recovery.xcu 131cdf0e10cSrcweir static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/"); 132cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_RECOVERYLIST = ::rtl::OUString::createFromAscii("RecoveryList" ); 133cdf0e10cSrcweir static const ::rtl::OUString CFG_PATH_RECOVERYINFO = ::rtl::OUString::createFromAscii("RecoveryInfo" ); 134cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_ENABLED = ::rtl::OUString::createFromAscii("Enabled" ); 135cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_CRASHED = ::rtl::OUString::createFromAscii("Crashed" ); 136cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_SESSIONDATA = ::rtl::OUString::createFromAscii("SessionData" ); 137cdf0e10cSrcweir 138cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_AUTOSAVE_ENABLED = ::rtl::OUString::createFromAscii("AutoSave/Enabled" ); 139cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_AUTOSAVE_TIMEINTERVALL = ::rtl::OUString::createFromAscii("AutoSave/TimeIntervall" ); 140cdf0e10cSrcweir 141cdf0e10cSrcweir static const ::rtl::OUString CFG_PATH_AUTOSAVE = ::rtl::OUString::createFromAscii("AutoSave" ); 142cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_MINSPACE_DOCSAVE = ::rtl::OUString::createFromAscii("MinSpaceDocSave" ); 143cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_MINSPACE_CONFIGSAVE = ::rtl::OUString::createFromAscii("MinSpaceConfigSave" ); 144cdf0e10cSrcweir 145cdf0e10cSrcweir static const ::rtl::OUString CFG_PACKAGE_MODULES = ::rtl::OUString::createFromAscii("org.openoffice.Setup/Office/Factories"); 146cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_REALDEFAULTFILTER = ::rtl::OUString::createFromAscii("ooSetupFactoryActualFilter" ); 147cdf0e10cSrcweir 148cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_TEMPURL = ::rtl::OUString::createFromAscii("TempURL" ); 149cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_ORIGINALURL = ::rtl::OUString::createFromAscii("OriginalURL" ); 150cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_TEMPLATEURL = ::rtl::OUString::createFromAscii("TemplateURL" ); 151cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_FACTORYURL = ::rtl::OUString::createFromAscii("FactoryURL" ); 152cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_MODULE = ::rtl::OUString::createFromAscii("Module" ); 153cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_DOCUMENTSTATE = ::rtl::OUString::createFromAscii("DocumentState"); 154cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_FILTER = ::rtl::OUString::createFromAscii("Filter" ); 155cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_TITLE = ::rtl::OUString::createFromAscii("Title" ); 156cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_ID = ::rtl::OUString::createFromAscii("ID" ); 157cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_VIEWNAMES = ::rtl::OUString::createFromAscii("ViewNames" ); 158cdf0e10cSrcweir 159cdf0e10cSrcweir static const ::rtl::OUString FILTER_PROP_TYPE = ::rtl::OUString::createFromAscii("Type" ); 160cdf0e10cSrcweir static const ::rtl::OUString FILTER_PROP_NAME = ::rtl::OUString::createFromAscii("Name" ); 161cdf0e10cSrcweir static const ::rtl::OUString TYPE_PROP_EXTENSIONS = ::rtl::OUString::createFromAscii("Extensions" ); 162cdf0e10cSrcweir static const ::rtl::OUString DOCINFO_PROP_TEMPLATE = ::rtl::OUString::createFromAscii("TemplateFileName"); 163cdf0e10cSrcweir 164cdf0e10cSrcweir // setup.xcu 165cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_EMPTYDOCUMENTURL = ::rtl::OUString::createFromAscii("ooSetupFactoryEmptyDocumentURL"); 166cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_DEFAULTFILTER = ::rtl::OUString::createFromAscii("ooSetupFactoryDefaultFilter" ); 167cdf0e10cSrcweir static const ::rtl::OUString CFG_ENTRY_PROP_FACTORYSERVICE = ::rtl::OUString::createFromAscii("ooSetupFactoryDocumentService" ); 168cdf0e10cSrcweir 169cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_NEW = ::rtl::OUString::createFromAscii("OnNew" ); 170cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_LOAD = ::rtl::OUString::createFromAscii("OnLoad" ); 171cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_UNLOAD = ::rtl::OUString::createFromAscii("OnUnload" ); 172cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_MODIFYCHANGED = ::rtl::OUString::createFromAscii("OnModifyChanged"); 173cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_SAVE = ::rtl::OUString::createFromAscii("OnSave" ); 174cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_SAVEAS = ::rtl::OUString::createFromAscii("OnSaveAs" ); 175cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_SAVETO = ::rtl::OUString::createFromAscii("OnCopyTo" ); 176cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_SAVEDONE = ::rtl::OUString::createFromAscii("OnSaveDone" ); 177cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_SAVEASDONE = ::rtl::OUString::createFromAscii("OnSaveAsDone" ); 178cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_SAVETODONE = ::rtl::OUString::createFromAscii("OnCopyToDone" ); 179cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_SAVEFAILED = ::rtl::OUString::createFromAscii("OnSaveFailed" ); 180cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_SAVEASFAILED = ::rtl::OUString::createFromAscii("OnSaveAsFailed" ); 181cdf0e10cSrcweir static const ::rtl::OUString EVENT_ON_SAVETOFAILED = ::rtl::OUString::createFromAscii("OnCopyToFailed" ); 182cdf0e10cSrcweir 183cdf0e10cSrcweir static const ::rtl::OUString RECOVERY_ITEM_BASE_IDENTIFIER = ::rtl::OUString::createFromAscii("recovery_item_" ); 184cdf0e10cSrcweir 185cdf0e10cSrcweir static const ::rtl::OUString CMD_PROTOCOL = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:"); 186cdf0e10cSrcweir 187cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_AUTO_SAVE = ::rtl::OUString::createFromAscii("/doAutoSave" ); // force AutoSave ignoring the AutoSave timer 188cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_PREPARE_EMERGENCY_SAVE = ::rtl::OUString::createFromAscii("/doPrepareEmergencySave" ); // prepare the office for the following EmergencySave step (hide windows etcpp.) 189cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_EMERGENCY_SAVE = ::rtl::OUString::createFromAscii("/doEmergencySave" ); // do EmergencySave on crash 190cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_RECOVERY = ::rtl::OUString::createFromAscii("/doAutoRecovery" ); // recover all crashed documents 191cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_ENTRY_BACKUP = ::rtl::OUString::createFromAscii("/doEntryBackup" ); // try to store a temp or original file to a user defined location 192cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_ENTRY_CLEANUP = ::rtl::OUString::createFromAscii("/doEntryCleanUp" ); // remove the specified entry from the recovery cache 193cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_SESSION_SAVE = ::rtl::OUString::createFromAscii("/doSessionSave" ); // save all open documents if e.g. a window manager closes an user session 194cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_SESSION_QUIET_QUIT = ::rtl::OUString::createFromAscii("/doSessionQuietQuit" ); // let the current session be quietly closed ( the saving should be done using doSessionSave previously ) if e.g. a window manager closes an user session 195cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_SESSION_RESTORE = ::rtl::OUString::createFromAscii("/doSessionRestore" ); // restore a saved user session from disc 196cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_DISABLE_RECOVERY = ::rtl::OUString::createFromAscii("/disableRecovery" ); // disable recovery and auto save (!) temp. for this office session 197cdf0e10cSrcweir static const ::rtl::OUString CMD_DO_SET_AUTOSAVE_STATE = ::rtl::OUString::createFromAscii("/setAutoSaveState" ); // disable/enable auto save (not crash save) for this office session 198cdf0e10cSrcweir 199cdf0e10cSrcweir static const ::rtl::OUString REFERRER_USER = ::rtl::OUString::createFromAscii("private:user"); 200cdf0e10cSrcweir 201cdf0e10cSrcweir static const ::rtl::OUString PROP_DISPATCH_ASYNCHRON = ::rtl::OUString::createFromAscii("DispatchAsynchron"); 202cdf0e10cSrcweir static const ::rtl::OUString PROP_PROGRESS = ::rtl::OUString::createFromAscii("StatusIndicator" ); 203cdf0e10cSrcweir static const ::rtl::OUString PROP_SAVEPATH = ::rtl::OUString::createFromAscii("SavePath" ); 204cdf0e10cSrcweir static const ::rtl::OUString PROP_ENTRY_ID = ::rtl::OUString::createFromAscii("EntryID" ); 205cdf0e10cSrcweir static const ::rtl::OUString PROP_DBG_MAKE_IT_FASTER = ::rtl::OUString::createFromAscii("DBGMakeItFaster" ); 206cdf0e10cSrcweir static const ::rtl::OUString PROP_AUTOSAVE_STATE = ::rtl::OUString::createFromAscii("AutoSaveState" ); 207cdf0e10cSrcweir 208cdf0e10cSrcweir static const ::rtl::OUString OPERATION_START = ::rtl::OUString::createFromAscii("start" ); 209cdf0e10cSrcweir static const ::rtl::OUString OPERATION_STOP = ::rtl::OUString::createFromAscii("stop" ); 210cdf0e10cSrcweir static const ::rtl::OUString OPERATION_UPDATE = ::rtl::OUString::createFromAscii("update"); 211cdf0e10cSrcweir 212cdf0e10cSrcweir static const sal_Int32 MIN_DISCSPACE_DOCSAVE = 5; // [MB] 213cdf0e10cSrcweir static const sal_Int32 MIN_DISCSPACE_CONFIGSAVE = 1; // [MB] 214cdf0e10cSrcweir static const sal_Int32 RETRY_STORE_ON_FULL_DISC_FOREVER = 300; // not forever ... but often enough .-) 215cdf0e10cSrcweir static const sal_Int32 RETRY_STORE_ON_MIGHT_FULL_DISC_USEFULL = 3; // in case FULL DISC does not seam the real problem 216cdf0e10cSrcweir static const sal_Int32 GIVE_UP_RETRY = 1; // in case FULL DISC does not seam the real problem 217cdf0e10cSrcweir 218cdf0e10cSrcweir #define SAVE_IN_PROGRESS sal_True 219cdf0e10cSrcweir #define SAVE_FINISHED sal_False 220cdf0e10cSrcweir 221cdf0e10cSrcweir #define LOCK_FOR_CACHE_ADD_REMOVE sal_True 222cdf0e10cSrcweir #define LOCK_FOR_CACHE_USE sal_False 223cdf0e10cSrcweir 224cdf0e10cSrcweir #define MIN_TIME_FOR_USER_IDLE 10000 // 10s user idle 225cdf0e10cSrcweir 226cdf0e10cSrcweir // enable the following defines in case you whish to simulate a full disc for debug purposes .-) 227cdf0e10cSrcweir 22807a3d7f1SPedro Giffuni // this define throws every time a document is stored or a configuration change 229cdf0e10cSrcweir // should be flushed an exception ... so the special error handler for this scenario is triggered 230cdf0e10cSrcweir // #define TRIGGER_FULL_DISC_CHECK 231cdf0e10cSrcweir 232cdf0e10cSrcweir // force "return sal_False" for the method impl_enoughDiscSpace(). 233cdf0e10cSrcweir // #define SIMULATE_FULL_DISC 234cdf0e10cSrcweir 235cdf0e10cSrcweir //----------------------------------------------- 236cdf0e10cSrcweir // #define ENABLE_RECOVERY_LOGGING 237cdf0e10cSrcweir #undef ENABLE_RECOVERY_LOGGING 238cdf0e10cSrcweir #ifdef ENABLE_RECOVERY_LOGGING 239cdf0e10cSrcweir #define LOGFILE_RECOVERY "recovery.log" 240cdf0e10cSrcweir 241cdf0e10cSrcweir #define LOG_RECOVERY(MSG) \ 242cdf0e10cSrcweir { \ 243cdf0e10cSrcweir WRITE_LOGFILE(LOGFILE_RECOVERY, MSG) \ 244cdf0e10cSrcweir WRITE_LOGFILE(LOGFILE_RECOVERY, "\n") \ 245cdf0e10cSrcweir } 246cdf0e10cSrcweir #else 247cdf0e10cSrcweir #undef LOGFILE_RECOVERY 248cdf0e10cSrcweir #define LOG_RECOVERY(MSG) 249cdf0e10cSrcweir #endif 250cdf0e10cSrcweir 251cdf0e10cSrcweir //----------------------------------------------- 252cdf0e10cSrcweir // TODO debug - remove it! 253cdf0e10cSrcweir class DbgListener : private ThreadHelpBase 254cdf0e10cSrcweir , public ::cppu::OWeakObject 255cdf0e10cSrcweir , public css::frame::XStatusListener 256cdf0e10cSrcweir { 257cdf0e10cSrcweir public: 258cdf0e10cSrcweir 259cdf0e10cSrcweir FWK_DECLARE_XINTERFACE 260cdf0e10cSrcweir 261cdf0e10cSrcweir DbgListener() 262cdf0e10cSrcweir { 263cdf0e10cSrcweir WRITE_LOGFILE("autorecovery_states.txt", "\n\nDbgListener::ctor()\n\n") 264cdf0e10cSrcweir } 265cdf0e10cSrcweir 266cdf0e10cSrcweir virtual ~DbgListener() 267cdf0e10cSrcweir { 268cdf0e10cSrcweir WRITE_LOGFILE("autorecovery_states.txt", "\n\nDbgListener::dtor()\n\n") 269cdf0e10cSrcweir } 270cdf0e10cSrcweir 271cdf0e10cSrcweir void startListening(const css::uno::Reference< css::frame::XDispatch >& xBroadcaster) 272cdf0e10cSrcweir { 273cdf0e10cSrcweir ::rtl::OUStringBuffer sMsg1(256); 274cdf0e10cSrcweir sMsg1.appendAscii("//**********************************************************************************\n"); 275cdf0e10cSrcweir sMsg1.appendAscii("start listening\n{\n"); 276cdf0e10cSrcweir WRITE_LOGFILE("autorecovery_states.txt", U2B(sMsg1.makeStringAndClear())) 277cdf0e10cSrcweir 278cdf0e10cSrcweir ++m_refCount; 279cdf0e10cSrcweir 280cdf0e10cSrcweir css::util::URL aURL; 281cdf0e10cSrcweir aURL.Complete = ::rtl::OUString(); 282cdf0e10cSrcweir xBroadcaster->addStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL); 283cdf0e10cSrcweir 284cdf0e10cSrcweir --m_refCount; 285cdf0e10cSrcweir 286cdf0e10cSrcweir ::rtl::OUStringBuffer sMsg2(256); 287cdf0e10cSrcweir sMsg2.appendAscii("}\nstart listening\n"); 288cdf0e10cSrcweir sMsg2.appendAscii("//**********************************************************************************\n"); 289cdf0e10cSrcweir WRITE_LOGFILE("autorecovery_states.txt", U2B(sMsg2.makeStringAndClear())) 290cdf0e10cSrcweir } 291cdf0e10cSrcweir 292cdf0e10cSrcweir virtual void SAL_CALL disposing(const css::lang::EventObject&) 293cdf0e10cSrcweir throw(css::uno::RuntimeException) 294cdf0e10cSrcweir { 295cdf0e10cSrcweir WRITE_LOGFILE("autorecovery_states.txt", "\n\nDbgListener::dtor()\n\n") 296cdf0e10cSrcweir } 297cdf0e10cSrcweir 298cdf0e10cSrcweir virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& aEvent) 299cdf0e10cSrcweir throw(css::uno::RuntimeException) 300cdf0e10cSrcweir { 301cdf0e10cSrcweir ::rtl::OUStringBuffer sMsg(256); 302cdf0e10cSrcweir 303cdf0e10cSrcweir sMsg.appendAscii("//**********************************************************************************\n"); 304cdf0e10cSrcweir 305cdf0e10cSrcweir sMsg.appendAscii("FeatureURL = \""); 306cdf0e10cSrcweir sMsg.append (aEvent.FeatureURL.Complete); 307cdf0e10cSrcweir sMsg.appendAscii("\"\n"); 308cdf0e10cSrcweir 309cdf0e10cSrcweir sMsg.appendAscii("State = ["); 310cdf0e10cSrcweir sal_Int32 nState = -1; 311cdf0e10cSrcweir aEvent.State >>= nState; 312cdf0e10cSrcweir if (nState==-1) 313cdf0e10cSrcweir { 314cdf0e10cSrcweir sMsg.appendAscii("?-"); 315cdf0e10cSrcweir sMsg.append (::rtl::OUString::valueOf(nState)); 316cdf0e10cSrcweir sMsg.appendAscii("-? "); 317cdf0e10cSrcweir } 318cdf0e10cSrcweir if (nState==0) 319cdf0e10cSrcweir sMsg.appendAscii("UNKNOWN "); 320cdf0e10cSrcweir if ((nState & 1)==1) 321cdf0e10cSrcweir sMsg.appendAscii("MODIFIED "); 322cdf0e10cSrcweir if ((nState & 2)==2) 323cdf0e10cSrcweir sMsg.appendAscii("TRYIT "); 324cdf0e10cSrcweir if ((nState & 4)==4) 325cdf0e10cSrcweir sMsg.appendAscii("HANDLED "); 326cdf0e10cSrcweir if ((nState & 8)==8) 327cdf0e10cSrcweir sMsg.appendAscii("POSTPONED "); 328cdf0e10cSrcweir if ((nState & 16)==16) 329cdf0e10cSrcweir sMsg.appendAscii("INCOMPLETE "); 330cdf0e10cSrcweir if ((nState & 32)==32) 331cdf0e10cSrcweir sMsg.appendAscii("DAMAGED "); 332cdf0e10cSrcweir sMsg.appendAscii("]\n"); 333cdf0e10cSrcweir /* 334cdf0e10cSrcweir sMsg.appendAscii("IsEnabled = \""); 335cdf0e10cSrcweir sMsg.append (::rtl::OUString::valueOf(aEvent.IsEnabled)); 336cdf0e10cSrcweir sMsg.appendAscii("\"\n"); 337cdf0e10cSrcweir 338cdf0e10cSrcweir sMsg.appendAscii("Requery = \""); 339cdf0e10cSrcweir sMsg.append (::rtl::OUString::valueOf(aEvent.Requery)); 340cdf0e10cSrcweir sMsg.appendAscii("\"\n"); 341cdf0e10cSrcweir */ 342cdf0e10cSrcweir sMsg.appendAscii("\n"); 343cdf0e10cSrcweir 344cdf0e10cSrcweir WRITE_LOGFILE("autorecovery_states.txt", U2B(sMsg.makeStringAndClear())) 345cdf0e10cSrcweir } 346cdf0e10cSrcweir }; 347cdf0e10cSrcweir 348cdf0e10cSrcweir //----------------------------------------------- 349cdf0e10cSrcweir class CacheLockGuard 350cdf0e10cSrcweir { 351cdf0e10cSrcweir private: 352cdf0e10cSrcweir 353cdf0e10cSrcweir // holds the outside calli alive, so it's shared resources 354cdf0e10cSrcweir // are valid everytimes 355cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface > m_xOwner; 356cdf0e10cSrcweir 357cdf0e10cSrcweir // mutex shared with outside calli ! 358cdf0e10cSrcweir LockHelper& m_rSharedMutex; 359cdf0e10cSrcweir 360cdf0e10cSrcweir // this variable knows the state of the "cache lock" 361cdf0e10cSrcweir sal_Int32& m_rCacheLock; 362cdf0e10cSrcweir 363cdf0e10cSrcweir // to prevent increasing/decreasing of m_rCacheLock more then ones 364cdf0e10cSrcweir // we must know if THIS guard has an actual lock set there ! 365cdf0e10cSrcweir sal_Bool m_bLockedByThisGuard; 366cdf0e10cSrcweir 367cdf0e10cSrcweir public: 368cdf0e10cSrcweir 369cdf0e10cSrcweir CacheLockGuard(AutoRecovery* pOwner , 370cdf0e10cSrcweir LockHelper& rMutex , 371cdf0e10cSrcweir sal_Int32& rCacheLock , 372cdf0e10cSrcweir sal_Bool bLockForAddRemoveVectorItems); 373cdf0e10cSrcweir ~CacheLockGuard(); 374cdf0e10cSrcweir 375cdf0e10cSrcweir void lock(sal_Bool bLockForAddRemoveVectorItems); 376cdf0e10cSrcweir void unlock(); 377cdf0e10cSrcweir }; 378cdf0e10cSrcweir 379cdf0e10cSrcweir //----------------------------------------------- 380cdf0e10cSrcweir CacheLockGuard::CacheLockGuard(AutoRecovery* pOwner , 381cdf0e10cSrcweir LockHelper& rMutex , 382cdf0e10cSrcweir sal_Int32& rCacheLock , 383cdf0e10cSrcweir sal_Bool bLockForAddRemoveVectorItems) 384cdf0e10cSrcweir : m_xOwner (static_cast< css::frame::XDispatch* >(pOwner)) 385cdf0e10cSrcweir , m_rSharedMutex (rMutex ) 386cdf0e10cSrcweir , m_rCacheLock (rCacheLock ) 387cdf0e10cSrcweir , m_bLockedByThisGuard(sal_False ) 388cdf0e10cSrcweir { 389cdf0e10cSrcweir lock(bLockForAddRemoveVectorItems); 390cdf0e10cSrcweir } 391cdf0e10cSrcweir 392cdf0e10cSrcweir //----------------------------------------------- 393cdf0e10cSrcweir CacheLockGuard::~CacheLockGuard() 394cdf0e10cSrcweir { 395cdf0e10cSrcweir unlock(); 396cdf0e10cSrcweir m_xOwner.clear(); 397cdf0e10cSrcweir } 398cdf0e10cSrcweir 399cdf0e10cSrcweir //----------------------------------------------- 400cdf0e10cSrcweir void CacheLockGuard::lock(sal_Bool bLockForAddRemoveVectorItems) 401cdf0e10cSrcweir { 402cdf0e10cSrcweir // SAFE -> ---------------------------------- 403cdf0e10cSrcweir WriteGuard aWriteLock(m_rSharedMutex); 404cdf0e10cSrcweir 405cdf0e10cSrcweir if (m_bLockedByThisGuard) 406cdf0e10cSrcweir return; 407cdf0e10cSrcweir 408cdf0e10cSrcweir // This cache lock is needed only to prevent us from removing/adding 409cdf0e10cSrcweir // items from/into the recovery cache ... during it's used at another code place 410cdf0e10cSrcweir // for iterating .-) 411cdf0e10cSrcweir 412cdf0e10cSrcweir // Modifying of item properties is allowed and sometimes needed! 413cdf0e10cSrcweir // So we should detect only the dangerous state of concurrent add/remove 414cdf0e10cSrcweir // requests and throw an exception then ... which can of course break the whole 415cdf0e10cSrcweir // operation. On the other side a crash reasoned by an invalid stl iterator 416cdf0e10cSrcweir // will have the same effect .-) 417cdf0e10cSrcweir 418cdf0e10cSrcweir if ( 419cdf0e10cSrcweir (m_rCacheLock > 0 ) && 420cdf0e10cSrcweir (bLockForAddRemoveVectorItems) 421cdf0e10cSrcweir ) 422cdf0e10cSrcweir { 423cdf0e10cSrcweir OSL_ENSURE(sal_False, "Re-entrance problem detected. Using of an stl structure in combination with iteration, adding, removing of elements etcpp."); 424cdf0e10cSrcweir throw css::uno::RuntimeException( 425cdf0e10cSrcweir ::rtl::OUString::createFromAscii("Re-entrance problem detected. Using of an stl structure in combination with iteration, adding, removing of elements etcpp."), 426cdf0e10cSrcweir m_xOwner); 427cdf0e10cSrcweir } 428cdf0e10cSrcweir 429cdf0e10cSrcweir ++m_rCacheLock; 430cdf0e10cSrcweir m_bLockedByThisGuard = sal_True; 431cdf0e10cSrcweir 432cdf0e10cSrcweir aWriteLock.unlock(); 433cdf0e10cSrcweir // <- SAFE ---------------------------------- 434cdf0e10cSrcweir } 435cdf0e10cSrcweir 436cdf0e10cSrcweir //----------------------------------------------- 437cdf0e10cSrcweir void CacheLockGuard::unlock() 438cdf0e10cSrcweir { 439cdf0e10cSrcweir // SAFE -> ---------------------------------- 440cdf0e10cSrcweir WriteGuard aWriteLock(m_rSharedMutex); 441cdf0e10cSrcweir 442cdf0e10cSrcweir if ( ! m_bLockedByThisGuard) 443cdf0e10cSrcweir return; 444cdf0e10cSrcweir 445cdf0e10cSrcweir --m_rCacheLock; 446cdf0e10cSrcweir m_bLockedByThisGuard = sal_False; 447cdf0e10cSrcweir 448cdf0e10cSrcweir if (m_rCacheLock < 0) 449cdf0e10cSrcweir { 450cdf0e10cSrcweir OSL_ENSURE(sal_False, "Wrong using of member m_nDocCacheLock detected. A ref counted value shouldn't reach values <0 .-)"); 451cdf0e10cSrcweir throw css::uno::RuntimeException( 452cdf0e10cSrcweir ::rtl::OUString::createFromAscii("Wrong using of member m_nDocCacheLock detected. A ref counted value shouldn't reach values <0 .-)"), 453cdf0e10cSrcweir m_xOwner); 454cdf0e10cSrcweir } 455cdf0e10cSrcweir aWriteLock.unlock(); 456cdf0e10cSrcweir // <- SAFE ---------------------------------- 457cdf0e10cSrcweir } 458cdf0e10cSrcweir 459cdf0e10cSrcweir //----------------------------------------------- 460cdf0e10cSrcweir DispatchParams::DispatchParams() 461cdf0e10cSrcweir : m_nWorkingEntryID(-1) 462cdf0e10cSrcweir { 463cdf0e10cSrcweir }; 464cdf0e10cSrcweir 465cdf0e10cSrcweir //----------------------------------------------- 466cdf0e10cSrcweir DispatchParams::DispatchParams(const ::comphelper::SequenceAsHashMap& lArgs , 467cdf0e10cSrcweir const css::uno::Reference< css::uno::XInterface >& xOwner) 468cdf0e10cSrcweir { 469cdf0e10cSrcweir m_nWorkingEntryID = lArgs.getUnpackedValueOrDefault(PROP_ENTRY_ID, (sal_Int32)-1 ); 470cdf0e10cSrcweir m_xProgress = lArgs.getUnpackedValueOrDefault(PROP_PROGRESS, css::uno::Reference< css::task::XStatusIndicator >()); 471cdf0e10cSrcweir m_sSavePath = lArgs.getUnpackedValueOrDefault(PROP_SAVEPATH, ::rtl::OUString() ); 472cdf0e10cSrcweir m_xHoldRefForAsyncOpAlive = xOwner; 473cdf0e10cSrcweir }; 474cdf0e10cSrcweir 475cdf0e10cSrcweir //----------------------------------------------- 476cdf0e10cSrcweir DispatchParams::DispatchParams(const DispatchParams& rCopy) 477cdf0e10cSrcweir { 478cdf0e10cSrcweir m_xProgress = rCopy.m_xProgress; 479cdf0e10cSrcweir m_sSavePath = rCopy.m_sSavePath; 480cdf0e10cSrcweir m_nWorkingEntryID = rCopy.m_nWorkingEntryID; 481cdf0e10cSrcweir m_xHoldRefForAsyncOpAlive = rCopy.m_xHoldRefForAsyncOpAlive; 482cdf0e10cSrcweir }; 483cdf0e10cSrcweir 484cdf0e10cSrcweir //----------------------------------------------- 485cdf0e10cSrcweir DispatchParams::~DispatchParams() 486cdf0e10cSrcweir {}; 487cdf0e10cSrcweir 488cdf0e10cSrcweir //----------------------------------------------- 489cdf0e10cSrcweir DispatchParams& DispatchParams::operator=(const DispatchParams& rCopy) 490cdf0e10cSrcweir { 491cdf0e10cSrcweir m_xProgress = rCopy.m_xProgress; 492cdf0e10cSrcweir m_sSavePath = rCopy.m_sSavePath; 493cdf0e10cSrcweir m_nWorkingEntryID = rCopy.m_nWorkingEntryID; 494cdf0e10cSrcweir m_xHoldRefForAsyncOpAlive = rCopy.m_xHoldRefForAsyncOpAlive; 495cdf0e10cSrcweir return *this; 496cdf0e10cSrcweir } 497cdf0e10cSrcweir 498cdf0e10cSrcweir //----------------------------------------------- 499cdf0e10cSrcweir void DispatchParams::forget() 500cdf0e10cSrcweir { 501cdf0e10cSrcweir m_sSavePath = ::rtl::OUString(); 502cdf0e10cSrcweir m_nWorkingEntryID = -1; 503cdf0e10cSrcweir m_xProgress.clear(); 504cdf0e10cSrcweir m_xHoldRefForAsyncOpAlive.clear(); 505cdf0e10cSrcweir }; 506cdf0e10cSrcweir 507cdf0e10cSrcweir //----------------------------------------------- 508cdf0e10cSrcweir DEFINE_XINTERFACE_1(DbgListener , 509cdf0e10cSrcweir OWeakObject , 510cdf0e10cSrcweir DIRECT_INTERFACE(css::frame::XStatusListener)) 511cdf0e10cSrcweir 512cdf0e10cSrcweir //----------------------------------------------- 513cdf0e10cSrcweir DEFINE_XINTERFACE_10(AutoRecovery , 514cdf0e10cSrcweir OWeakObject , 515cdf0e10cSrcweir DIRECT_INTERFACE (css::lang::XTypeProvider ), 516cdf0e10cSrcweir DIRECT_INTERFACE (css::lang::XServiceInfo ), 517cdf0e10cSrcweir DIRECT_INTERFACE (css::frame::XDispatch ), 518cdf0e10cSrcweir DIRECT_INTERFACE (css::beans::XMultiPropertySet ), 519cdf0e10cSrcweir DIRECT_INTERFACE (css::beans::XFastPropertySet ), 520cdf0e10cSrcweir DIRECT_INTERFACE (css::beans::XPropertySet ), 521cdf0e10cSrcweir DIRECT_INTERFACE (css::document::XEventListener ), 522cdf0e10cSrcweir DIRECT_INTERFACE (css::util::XChangesListener ), 523cdf0e10cSrcweir DIRECT_INTERFACE (css::util::XModifyListener ), 524cdf0e10cSrcweir DERIVED_INTERFACE(css::lang::XEventListener, css::document::XEventListener)) 525cdf0e10cSrcweir 526cdf0e10cSrcweir //----------------------------------------------- 527cdf0e10cSrcweir DEFINE_XTYPEPROVIDER_6(AutoRecovery , 528cdf0e10cSrcweir css::lang::XTypeProvider , 529cdf0e10cSrcweir css::lang::XServiceInfo , 530cdf0e10cSrcweir css::frame::XDispatch , 531cdf0e10cSrcweir css::beans::XMultiPropertySet, 532cdf0e10cSrcweir css::beans::XFastPropertySet , 533cdf0e10cSrcweir css::beans::XPropertySet ) 534cdf0e10cSrcweir 535cdf0e10cSrcweir //----------------------------------------------- 536cdf0e10cSrcweir DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(AutoRecovery , 537cdf0e10cSrcweir ::cppu::OWeakObject , 538cdf0e10cSrcweir SERVICENAME_AUTORECOVERY , 539cdf0e10cSrcweir IMPLEMENTATIONNAME_AUTORECOVERY) 540cdf0e10cSrcweir 541cdf0e10cSrcweir //----------------------------------------------- 542cdf0e10cSrcweir DEFINE_INIT_SERVICE( 543cdf0e10cSrcweir AutoRecovery, 544cdf0e10cSrcweir { 545cdf0e10cSrcweir /*Attention 546cdf0e10cSrcweir I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance() 547cdf0e10cSrcweir to create a new instance of this class by our own supported service factory. 548cdf0e10cSrcweir see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations! 549cdf0e10cSrcweir */ 550cdf0e10cSrcweir 551cdf0e10cSrcweir // read configuration to know if autosave/recovery is on/off etcpp... 552cdf0e10cSrcweir implts_readConfig(); 553cdf0e10cSrcweir 554cdf0e10cSrcweir implts_startListening(); 555cdf0e10cSrcweir 556cdf0e10cSrcweir // establish callback for our internal used timer. 557cdf0e10cSrcweir // Note: Its only active, if the timer will be started ... 558cdf0e10cSrcweir m_aTimer.SetTimeoutHdl(LINK(this, AutoRecovery, implts_timerExpired)); 559cdf0e10cSrcweir /* 560cdf0e10cSrcweir DbgListener* pListener = new DbgListener(); 561cdf0e10cSrcweir pListener->startListening(this); 562cdf0e10cSrcweir */ 563cdf0e10cSrcweir } 564cdf0e10cSrcweir ) 565cdf0e10cSrcweir 566cdf0e10cSrcweir //----------------------------------------------- 567cdf0e10cSrcweir AutoRecovery::AutoRecovery(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 568cdf0e10cSrcweir : ThreadHelpBase (&Application::GetSolarMutex() ) 569cdf0e10cSrcweir , ::cppu::OBroadcastHelper ( m_aLock.getShareableOslMutex() ) 570cdf0e10cSrcweir , ::cppu::OPropertySetHelper( *(static_cast< ::cppu::OBroadcastHelper* >(this)) ) 571cdf0e10cSrcweir , ::cppu::OWeakObject ( ) 572cdf0e10cSrcweir , m_xSMGR (xSMGR ) 573cdf0e10cSrcweir , m_bListenForDocEvents (sal_False ) 574cdf0e10cSrcweir , m_bListenForConfigChanges (sal_False ) 575cdf0e10cSrcweir , m_nAutoSaveTimeIntervall (0 ) 576cdf0e10cSrcweir , m_eJob (AutoRecovery::E_NO_JOB ) 577cdf0e10cSrcweir , m_aAsyncDispatcher ( LINK( this, AutoRecovery, implts_asyncDispatch ) ) 578cdf0e10cSrcweir , m_eTimerType (E_DONT_START_TIMER ) 579cdf0e10cSrcweir , m_nIdPool (0 ) 580cdf0e10cSrcweir , m_lListener (m_aLock.getShareableOslMutex() ) 581cdf0e10cSrcweir , m_nDocCacheLock (0 ) 582cdf0e10cSrcweir , m_nMinSpaceDocSave (MIN_DISCSPACE_DOCSAVE ) 583cdf0e10cSrcweir , m_nMinSpaceConfigSave (MIN_DISCSPACE_CONFIGSAVE ) 584cdf0e10cSrcweir 585cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 586cdf0e10cSrcweir , m_dbg_bMakeItFaster (sal_False ) 587cdf0e10cSrcweir #endif 588cdf0e10cSrcweir { 589cdf0e10cSrcweir } 590cdf0e10cSrcweir 591cdf0e10cSrcweir //----------------------------------------------- 592cdf0e10cSrcweir AutoRecovery::~AutoRecovery() 593cdf0e10cSrcweir { 594cdf0e10cSrcweir implts_stopTimer(); 595cdf0e10cSrcweir } 596cdf0e10cSrcweir 597cdf0e10cSrcweir //----------------------------------------------- 598cdf0e10cSrcweir void SAL_CALL AutoRecovery::dispatch(const css::util::URL& aURL , 599cdf0e10cSrcweir const css::uno::Sequence< css::beans::PropertyValue >& lArguments) 600cdf0e10cSrcweir throw(css::uno::RuntimeException) 601cdf0e10cSrcweir { 602cdf0e10cSrcweir LOG_RECOVERY("AutoRecovery::dispatch() starts ...") 603cdf0e10cSrcweir LOG_RECOVERY(U2B(aURL.Complete).getStr()) 604cdf0e10cSrcweir 605cdf0e10cSrcweir // valid request ? 606cdf0e10cSrcweir sal_Int32 eNewJob = AutoRecovery::implst_classifyJob(aURL); 607cdf0e10cSrcweir if (eNewJob == AutoRecovery::E_NO_JOB) 608cdf0e10cSrcweir return; 609cdf0e10cSrcweir 610cdf0e10cSrcweir // SAFE -> ---------------------------------- 611cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 612cdf0e10cSrcweir 613cdf0e10cSrcweir // still running operation ... ignoring AUTO_SAVE. 614cdf0e10cSrcweir // All other requests has higher prio! 615cdf0e10cSrcweir if ( 616cdf0e10cSrcweir ( m_eJob != AutoRecovery::E_NO_JOB ) && 617cdf0e10cSrcweir ((m_eJob & AutoRecovery::E_AUTO_SAVE ) != AutoRecovery::E_AUTO_SAVE) 618cdf0e10cSrcweir ) 619cdf0e10cSrcweir { 620cdf0e10cSrcweir LOG_WARNING("AutoRecovery::dispatch()", "There is already an asynchronous dispatch() running. New request will be ignored!") 621cdf0e10cSrcweir return; 622cdf0e10cSrcweir } 623cdf0e10cSrcweir 624cdf0e10cSrcweir ::comphelper::SequenceAsHashMap lArgs(lArguments); 625cdf0e10cSrcweir 626cdf0e10cSrcweir // check if somewhere wish to disable recovery temp. for this office session 62707a3d7f1SPedro Giffuni // This can be done immediately ... must not been done asynchronous. 628cdf0e10cSrcweir if ((eNewJob & AutoRecovery::E_DISABLE_AUTORECOVERY) == AutoRecovery::E_DISABLE_AUTORECOVERY) 629cdf0e10cSrcweir { 630a49f1911Smseidel // it's important to set a flag internally, so AutoRecovery will be suppressed - even if it's requested. 631cdf0e10cSrcweir m_eJob |= eNewJob; 632cdf0e10cSrcweir implts_stopTimer(); 633cdf0e10cSrcweir implts_stopListening(); 634cdf0e10cSrcweir return; 635cdf0e10cSrcweir } 636cdf0e10cSrcweir 637cdf0e10cSrcweir // disable/enable AutoSave for this office session only 638cdf0e10cSrcweir // independend from the configuration entry. 639cdf0e10cSrcweir if ((eNewJob & AutoRecovery::E_SET_AUTOSAVE_STATE) == AutoRecovery::E_SET_AUTOSAVE_STATE) 640cdf0e10cSrcweir { 641cdf0e10cSrcweir sal_Bool bOn = lArgs.getUnpackedValueOrDefault(PROP_AUTOSAVE_STATE, (sal_Bool)sal_True); 642cdf0e10cSrcweir if (bOn) 643cdf0e10cSrcweir { 644cdf0e10cSrcweir // dont enable AutoSave hardly ! 645cdf0e10cSrcweir // reload configuration to know the current state. 646cdf0e10cSrcweir implts_readAutoSaveConfig(); 647cdf0e10cSrcweir implts_updateTimer(); 648cdf0e10cSrcweir // can it happen that might be the listener was stopped ? .-) 649cdf0e10cSrcweir // make sure it runs always ... even if AutoSave itself was disabled temporarly. 650cdf0e10cSrcweir implts_startListening(); 651cdf0e10cSrcweir } 652cdf0e10cSrcweir else 653cdf0e10cSrcweir { 654cdf0e10cSrcweir implts_stopTimer(); 655cdf0e10cSrcweir m_eJob &= ~AutoRecovery::E_AUTO_SAVE; 656cdf0e10cSrcweir m_eTimerType = AutoRecovery::E_DONT_START_TIMER; 657cdf0e10cSrcweir } 658cdf0e10cSrcweir return; 659cdf0e10cSrcweir } 660cdf0e10cSrcweir 661cdf0e10cSrcweir m_eJob |= eNewJob; 662cdf0e10cSrcweir 663cdf0e10cSrcweir sal_Bool bAsync = lArgs.getUnpackedValueOrDefault(PROP_DISPATCH_ASYNCHRON, (sal_Bool)sal_False); 664cdf0e10cSrcweir DispatchParams aParams (lArgs, static_cast< css::frame::XDispatch* >(this)); 665cdf0e10cSrcweir 666cdf0e10cSrcweir // Hold this instance alive till the asynchronous operation will be finished. 667cdf0e10cSrcweir if (bAsync) 668cdf0e10cSrcweir m_aDispatchParams = aParams; 669cdf0e10cSrcweir 670cdf0e10cSrcweir aWriteLock.unlock(); 671cdf0e10cSrcweir // <- SAFE ---------------------------------- 672cdf0e10cSrcweir 673cdf0e10cSrcweir if (bAsync) 674cdf0e10cSrcweir m_aAsyncDispatcher.Post(0); 675cdf0e10cSrcweir else 676cdf0e10cSrcweir implts_dispatch(aParams); 677cdf0e10cSrcweir } 678cdf0e10cSrcweir 679cdf0e10cSrcweir //----------------------------------------------- 680cdf0e10cSrcweir void AutoRecovery::implts_dispatch(const DispatchParams& aParams) 681cdf0e10cSrcweir { 682cdf0e10cSrcweir // SAFE -> ---------------------------------- 683cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 684cdf0e10cSrcweir sal_Int32 eJob = m_eJob; 685cdf0e10cSrcweir aWriteLock.unlock(); 686cdf0e10cSrcweir // <- SAFE ---------------------------------- 687cdf0e10cSrcweir 688cdf0e10cSrcweir // in case a new dispatch overwrites a may ba active AutoSave session 689cdf0e10cSrcweir // we must restore this session later. see below ... 690cdf0e10cSrcweir sal_Bool bWasAutoSaveActive = ((eJob & AutoRecovery::E_AUTO_SAVE) == AutoRecovery::E_AUTO_SAVE); 691cdf0e10cSrcweir 692cdf0e10cSrcweir // On the other side it make no sense to reactivate the AutoSave operation 693cdf0e10cSrcweir // if the new dispatch indicates a final decision ... 694cdf0e10cSrcweir // E.g. an EmergencySave/SessionSave indicates the end of life of the current office session. 695cdf0e10cSrcweir // It make no sense to reactivate an AutoSave then. 696cdf0e10cSrcweir // But a Recovery or SessionRestore should reactivate a may be already active AutoSave. 697cdf0e10cSrcweir sal_Bool bAllowAutoSaveReactivation = sal_True; 698cdf0e10cSrcweir 699cdf0e10cSrcweir implts_stopTimer(); 700cdf0e10cSrcweir implts_stopListening(); 701cdf0e10cSrcweir 702cdf0e10cSrcweir implts_informListener(eJob, 703cdf0e10cSrcweir AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_START, NULL)); 704cdf0e10cSrcweir 705cdf0e10cSrcweir try 706cdf0e10cSrcweir { 707cdf0e10cSrcweir // if ((eJob & AutoRecovery::E_AUTO_SAVE) == AutoRecovery::E_AUTO_SAVE) 708cdf0e10cSrcweir // Auto save is called from our internal timer ... not via dispatch() API ! 709cdf0e10cSrcweir // else 710cdf0e10cSrcweir if ( 711cdf0e10cSrcweir ((eJob & AutoRecovery::E_PREPARE_EMERGENCY_SAVE) == AutoRecovery::E_PREPARE_EMERGENCY_SAVE) && 712cdf0e10cSrcweir ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY ) != AutoRecovery::E_DISABLE_AUTORECOVERY ) 713cdf0e10cSrcweir ) 714cdf0e10cSrcweir { 715cdf0e10cSrcweir LOG_RECOVERY("... prepare emergency save ...") 716cdf0e10cSrcweir bAllowAutoSaveReactivation = sal_False; 717cdf0e10cSrcweir implts_prepareEmergencySave(); 718cdf0e10cSrcweir } 719cdf0e10cSrcweir else 720cdf0e10cSrcweir if ( 721cdf0e10cSrcweir ((eJob & AutoRecovery::E_EMERGENCY_SAVE ) == AutoRecovery::E_EMERGENCY_SAVE ) && 722cdf0e10cSrcweir ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY) 723cdf0e10cSrcweir ) 724cdf0e10cSrcweir { 725cdf0e10cSrcweir LOG_RECOVERY("... do emergency save ...") 726cdf0e10cSrcweir bAllowAutoSaveReactivation = sal_False; 727cdf0e10cSrcweir implts_doEmergencySave(aParams); 728cdf0e10cSrcweir } 729cdf0e10cSrcweir else 730cdf0e10cSrcweir if ( 731cdf0e10cSrcweir ((eJob & AutoRecovery::E_RECOVERY ) == AutoRecovery::E_RECOVERY ) && 732cdf0e10cSrcweir ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY) 733cdf0e10cSrcweir ) 734cdf0e10cSrcweir { 735cdf0e10cSrcweir LOG_RECOVERY("... do recovery ...") 736cdf0e10cSrcweir implts_doRecovery(aParams); 737cdf0e10cSrcweir } 738cdf0e10cSrcweir else 739cdf0e10cSrcweir if ( 740cdf0e10cSrcweir ((eJob & AutoRecovery::E_SESSION_SAVE ) == AutoRecovery::E_SESSION_SAVE ) && 741cdf0e10cSrcweir ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY) 742cdf0e10cSrcweir ) 743cdf0e10cSrcweir { 744cdf0e10cSrcweir LOG_RECOVERY("... do session save ...") 745cdf0e10cSrcweir bAllowAutoSaveReactivation = sal_False; 746cdf0e10cSrcweir implts_doSessionSave(aParams); 747cdf0e10cSrcweir } 748cdf0e10cSrcweir else 749cdf0e10cSrcweir if ( 750cdf0e10cSrcweir ((eJob & AutoRecovery::E_SESSION_QUIET_QUIT ) == AutoRecovery::E_SESSION_QUIET_QUIT ) && 751cdf0e10cSrcweir ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY) 752cdf0e10cSrcweir ) 753cdf0e10cSrcweir { 754cdf0e10cSrcweir LOG_RECOVERY("... do session quiet quit ...") 755cdf0e10cSrcweir bAllowAutoSaveReactivation = sal_False; 756cdf0e10cSrcweir implts_doSessionQuietQuit(aParams); 757cdf0e10cSrcweir } 758cdf0e10cSrcweir else 759cdf0e10cSrcweir if ( 760cdf0e10cSrcweir ((eJob & AutoRecovery::E_SESSION_RESTORE ) == AutoRecovery::E_SESSION_RESTORE ) && 761cdf0e10cSrcweir ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY) 762cdf0e10cSrcweir ) 763cdf0e10cSrcweir { 764cdf0e10cSrcweir LOG_RECOVERY("... do session restore ...") 765cdf0e10cSrcweir implts_doSessionRestore(aParams); 766cdf0e10cSrcweir } 767cdf0e10cSrcweir else 768cdf0e10cSrcweir if ( 769cdf0e10cSrcweir ((eJob & AutoRecovery::E_ENTRY_BACKUP ) == AutoRecovery::E_ENTRY_BACKUP ) && 770cdf0e10cSrcweir ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY) 771cdf0e10cSrcweir ) 772cdf0e10cSrcweir implts_backupWorkingEntry(aParams); 773cdf0e10cSrcweir else 774cdf0e10cSrcweir if ( 775cdf0e10cSrcweir ((eJob & AutoRecovery::E_ENTRY_CLEANUP ) == AutoRecovery::E_ENTRY_CLEANUP ) && 776cdf0e10cSrcweir ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY) 777cdf0e10cSrcweir ) 778cdf0e10cSrcweir implts_cleanUpWorkingEntry(aParams); 779cdf0e10cSrcweir } 780cdf0e10cSrcweir catch(const css::uno::RuntimeException& exRun) 781cdf0e10cSrcweir { throw exRun; } 782cdf0e10cSrcweir catch(const css::uno::Exception&) 783cdf0e10cSrcweir {} // TODO better error handling 784cdf0e10cSrcweir 785cdf0e10cSrcweir implts_informListener(eJob, 786cdf0e10cSrcweir AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_STOP, NULL)); 787cdf0e10cSrcweir 788cdf0e10cSrcweir // SAFE -> ---------------------------------- 789cdf0e10cSrcweir aWriteLock.lock(); 790cdf0e10cSrcweir m_eJob = E_NO_JOB; 791cdf0e10cSrcweir if ( 792cdf0e10cSrcweir (bAllowAutoSaveReactivation) && 793cdf0e10cSrcweir (bWasAutoSaveActive ) 794cdf0e10cSrcweir ) 795cdf0e10cSrcweir { 796cdf0e10cSrcweir m_eJob |= AutoRecovery::E_AUTO_SAVE; 797cdf0e10cSrcweir } 798cdf0e10cSrcweir 799cdf0e10cSrcweir aWriteLock.unlock(); 800cdf0e10cSrcweir // <- SAFE ---------------------------------- 801cdf0e10cSrcweir 802cdf0e10cSrcweir // depends on bAllowAutoSaveReactivation implicitly by looking on m_eJob=E_AUTO_SAVE! see before ... 803cdf0e10cSrcweir implts_updateTimer(); 804cdf0e10cSrcweir 805cdf0e10cSrcweir if (bAllowAutoSaveReactivation) 806cdf0e10cSrcweir implts_startListening(); 807cdf0e10cSrcweir } 808cdf0e10cSrcweir 809cdf0e10cSrcweir //----------------------------------------------- 810cdf0e10cSrcweir void SAL_CALL AutoRecovery::addStatusListener(const css::uno::Reference< css::frame::XStatusListener >& xListener, 811cdf0e10cSrcweir const css::util::URL& aURL ) 812cdf0e10cSrcweir throw(css::uno::RuntimeException) 813cdf0e10cSrcweir { 814cdf0e10cSrcweir if (!xListener.is()) 815cdf0e10cSrcweir throw css::uno::RuntimeException(::rtl::OUString::createFromAscii("Invalid listener reference."), static_cast< css::frame::XDispatch* >(this)); 816cdf0e10cSrcweir // container is threadsafe by using a shared mutex! 817cdf0e10cSrcweir m_lListener.addInterface(aURL.Complete, xListener); 818cdf0e10cSrcweir 819cdf0e10cSrcweir // REENTRANT !? -> -------------------------------- 820cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 821cdf0e10cSrcweir 822cdf0e10cSrcweir // THREAD SAFE -> ---------------------------------- 823cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 824cdf0e10cSrcweir 825cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt; 826cdf0e10cSrcweir for( pIt = m_lDocCache.begin(); 827cdf0e10cSrcweir pIt != m_lDocCache.end() ; 828cdf0e10cSrcweir ++pIt ) 829cdf0e10cSrcweir { 830cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo = *pIt; 831cdf0e10cSrcweir css::frame::FeatureStateEvent aEvent = AutoRecovery::implst_createFeatureStateEvent(m_eJob, OPERATION_UPDATE, &rInfo); 832cdf0e10cSrcweir 833cdf0e10cSrcweir // <- SAFE ------------------------------ 834cdf0e10cSrcweir aReadLock.unlock(); 835cdf0e10cSrcweir xListener->statusChanged(aEvent); 836cdf0e10cSrcweir aReadLock.lock(); 837cdf0e10cSrcweir // SAFE -> ------------------------------ 838cdf0e10cSrcweir } 839cdf0e10cSrcweir 840cdf0e10cSrcweir aReadLock.unlock(); 841cdf0e10cSrcweir // <- SAFE ---------------------------------- 842cdf0e10cSrcweir } 843cdf0e10cSrcweir 844cdf0e10cSrcweir //----------------------------------------------- 845cdf0e10cSrcweir void SAL_CALL AutoRecovery::removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >& xListener, 846cdf0e10cSrcweir const css::util::URL& aURL ) 847cdf0e10cSrcweir throw(css::uno::RuntimeException) 848cdf0e10cSrcweir { 849cdf0e10cSrcweir if (!xListener.is()) 850cdf0e10cSrcweir throw css::uno::RuntimeException(::rtl::OUString::createFromAscii("Invalid listener reference."), static_cast< css::frame::XDispatch* >(this)); 851cdf0e10cSrcweir // container is threadsafe by using a shared mutex! 852cdf0e10cSrcweir m_lListener.removeInterface(aURL.Complete, xListener); 853cdf0e10cSrcweir } 854cdf0e10cSrcweir 855cdf0e10cSrcweir //----------------------------------------------- 856cdf0e10cSrcweir void SAL_CALL AutoRecovery::notifyEvent(const css::document::EventObject& aEvent) 857cdf0e10cSrcweir throw(css::uno::RuntimeException) 858cdf0e10cSrcweir { 859cdf0e10cSrcweir css::uno::Reference< css::frame::XModel > xDocument(aEvent.Source, css::uno::UNO_QUERY); 860cdf0e10cSrcweir 861cdf0e10cSrcweir // new document => put it into the internal list 862cdf0e10cSrcweir if ( 863cdf0e10cSrcweir (aEvent.EventName.equals(EVENT_ON_NEW )) || 864cdf0e10cSrcweir (aEvent.EventName.equals(EVENT_ON_LOAD)) 865cdf0e10cSrcweir ) 866cdf0e10cSrcweir { 867cdf0e10cSrcweir implts_registerDocument(xDocument); 868cdf0e10cSrcweir } 869cdf0e10cSrcweir // document modified => set its modify state new (means modified against the original file!) 870cdf0e10cSrcweir else 871cdf0e10cSrcweir if (aEvent.EventName.equals(EVENT_ON_MODIFYCHANGED)) 872cdf0e10cSrcweir { 873cdf0e10cSrcweir implts_updateModifiedState(xDocument); 874cdf0e10cSrcweir } 875cdf0e10cSrcweir /* at least one document starts saving process => 87607a3d7f1SPedro Giffuni Our application code isn't ready for multiple save requests 87707a3d7f1SPedro Giffuni at the same time. So we have to suppress our AutoSave feature 878cdf0e10cSrcweir for the moment, till this other save requests will be finished. 879cdf0e10cSrcweir */ 880cdf0e10cSrcweir else 881cdf0e10cSrcweir if ( 882cdf0e10cSrcweir (aEvent.EventName.equals(EVENT_ON_SAVE )) || 883cdf0e10cSrcweir (aEvent.EventName.equals(EVENT_ON_SAVEAS)) || 884cdf0e10cSrcweir (aEvent.EventName.equals(EVENT_ON_SAVETO)) 885cdf0e10cSrcweir ) 886cdf0e10cSrcweir { 887cdf0e10cSrcweir implts_updateDocumentUsedForSavingState(xDocument, SAVE_IN_PROGRESS); 888cdf0e10cSrcweir } 889cdf0e10cSrcweir // document saved => remove tmp. files - but hold config entries alive! 890cdf0e10cSrcweir else 891cdf0e10cSrcweir if ( 892cdf0e10cSrcweir (aEvent.EventName.equals(EVENT_ON_SAVEDONE )) || 893cdf0e10cSrcweir (aEvent.EventName.equals(EVENT_ON_SAVEASDONE)) 894cdf0e10cSrcweir ) 895cdf0e10cSrcweir { 896cdf0e10cSrcweir implts_markDocumentAsSaved(xDocument); 897cdf0e10cSrcweir implts_updateDocumentUsedForSavingState(xDocument, SAVE_FINISHED); 898cdf0e10cSrcweir } 899cdf0e10cSrcweir /* document saved as copy => mark it as "non used by concurrent save operation". 900cdf0e10cSrcweir so we can try to create a backup copy if next time AutoSave is started too. 9014e7d57d8Smseidel Don't remove temp. files or change the modified state of the document! 90207a3d7f1SPedro Giffuni It was not really saved to the original file ... 903cdf0e10cSrcweir */ 904cdf0e10cSrcweir else 905cdf0e10cSrcweir if (aEvent.EventName.equals(EVENT_ON_SAVETODONE)) 906cdf0e10cSrcweir { 907cdf0e10cSrcweir implts_updateDocumentUsedForSavingState(xDocument, SAVE_FINISHED); 908cdf0e10cSrcweir } 909cdf0e10cSrcweir // If saving of a document failed by an error ... we have to save this document 910cdf0e10cSrcweir // by ourself next time AutoSave or EmergencySave is triggered. 9114e7d57d8Smseidel // But we can reset the state "used for other save requests". Otherwise 912cdf0e10cSrcweir // these documents will never be saved! 913cdf0e10cSrcweir else 914cdf0e10cSrcweir if ( 915cdf0e10cSrcweir (aEvent.EventName.equals(EVENT_ON_SAVEFAILED )) || 916cdf0e10cSrcweir (aEvent.EventName.equals(EVENT_ON_SAVEASFAILED)) || 917cdf0e10cSrcweir (aEvent.EventName.equals(EVENT_ON_SAVETOFAILED)) 918cdf0e10cSrcweir ) 919cdf0e10cSrcweir { 920cdf0e10cSrcweir implts_updateDocumentUsedForSavingState(xDocument, SAVE_FINISHED); 921cdf0e10cSrcweir } 922cdf0e10cSrcweir // document closed => remove temp. files and configuration entries 923cdf0e10cSrcweir else 924cdf0e10cSrcweir if (aEvent.EventName.equals(EVENT_ON_UNLOAD)) 925cdf0e10cSrcweir { 926cdf0e10cSrcweir implts_deregisterDocument(xDocument, sal_True); // sal_True => stop listening for disposing() ! 927cdf0e10cSrcweir } 928cdf0e10cSrcweir } 929cdf0e10cSrcweir 930cdf0e10cSrcweir //----------------------------------------------- 931cdf0e10cSrcweir void SAL_CALL AutoRecovery::changesOccurred(const css::util::ChangesEvent& aEvent) 932cdf0e10cSrcweir throw(css::uno::RuntimeException) 933cdf0e10cSrcweir { 934cdf0e10cSrcweir const css::uno::Sequence< css::util::ElementChange > lChanges (aEvent.Changes); 935cdf0e10cSrcweir const css::util::ElementChange* pChanges = lChanges.getConstArray(); 936cdf0e10cSrcweir 937cdf0e10cSrcweir sal_Int32 c = lChanges.getLength(); 938cdf0e10cSrcweir sal_Int32 i = 0; 939cdf0e10cSrcweir 940cdf0e10cSrcweir // SAFE -> ---------------------------------- 941cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 942cdf0e10cSrcweir 943cdf0e10cSrcweir // Changes of the configuration must be ignored if AutoSave/Recovery was disabled for this 944cdf0e10cSrcweir // office session. That can happen if e.g. the command line arguments "-norestore" or "-headless" 945cdf0e10cSrcweir // was set. 946cdf0e10cSrcweir if ((m_eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) == AutoRecovery::E_DISABLE_AUTORECOVERY) 947cdf0e10cSrcweir return; 948cdf0e10cSrcweir 949cdf0e10cSrcweir for (i=0; i<c; ++i) 950cdf0e10cSrcweir { 951cdf0e10cSrcweir ::rtl::OUString sPath; 952cdf0e10cSrcweir pChanges[i].Accessor >>= sPath; 953cdf0e10cSrcweir 954cdf0e10cSrcweir if (sPath.equals(CFG_ENTRY_AUTOSAVE_ENABLED)) 955cdf0e10cSrcweir { 956cdf0e10cSrcweir sal_Bool bEnabled = sal_False; 957cdf0e10cSrcweir if (pChanges[i].Element >>= bEnabled) 958cdf0e10cSrcweir { 959cdf0e10cSrcweir if (bEnabled) 960cdf0e10cSrcweir { 961cdf0e10cSrcweir m_eJob |= AutoRecovery::E_AUTO_SAVE; 962cdf0e10cSrcweir m_eTimerType = AutoRecovery::E_NORMAL_AUTOSAVE_INTERVALL; 963cdf0e10cSrcweir } 964cdf0e10cSrcweir else 965cdf0e10cSrcweir { 966cdf0e10cSrcweir m_eJob &= ~AutoRecovery::E_AUTO_SAVE; 967cdf0e10cSrcweir m_eTimerType = AutoRecovery::E_DONT_START_TIMER; 968cdf0e10cSrcweir } 969cdf0e10cSrcweir } 970cdf0e10cSrcweir } 971cdf0e10cSrcweir else 972cdf0e10cSrcweir if (sPath.equals(CFG_ENTRY_AUTOSAVE_TIMEINTERVALL)) 973cdf0e10cSrcweir pChanges[i].Element >>= m_nAutoSaveTimeIntervall; 974cdf0e10cSrcweir } 975cdf0e10cSrcweir 976cdf0e10cSrcweir aWriteLock.unlock(); 977cdf0e10cSrcweir // <- SAFE ---------------------------------- 978cdf0e10cSrcweir 979cdf0e10cSrcweir // Note: This call stops the timer and starts it again. 980a49f1911Smseidel // But it checks the different timer states internally and 981a49f1911Smseidel // may suppress the restart! 982cdf0e10cSrcweir implts_updateTimer(); 983cdf0e10cSrcweir } 984cdf0e10cSrcweir 985cdf0e10cSrcweir //----------------------------------------------- 986cdf0e10cSrcweir void SAL_CALL AutoRecovery::modified(const css::lang::EventObject& aEvent) 987cdf0e10cSrcweir throw(css::uno::RuntimeException) 988cdf0e10cSrcweir { 989cdf0e10cSrcweir css::uno::Reference< css::frame::XModel > xDocument(aEvent.Source, css::uno::UNO_QUERY); 990cdf0e10cSrcweir if (! xDocument.is()) 991cdf0e10cSrcweir return; 992cdf0e10cSrcweir 993cdf0e10cSrcweir implts_markDocumentModifiedAgainstLastBackup(xDocument); 994cdf0e10cSrcweir } 995cdf0e10cSrcweir 996cdf0e10cSrcweir //----------------------------------------------- 997cdf0e10cSrcweir void SAL_CALL AutoRecovery::disposing(const css::lang::EventObject& aEvent) 998cdf0e10cSrcweir throw(css::uno::RuntimeException) 999cdf0e10cSrcweir { 1000cdf0e10cSrcweir // SAFE -> ---------------------------------- 1001cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1002cdf0e10cSrcweir 1003cdf0e10cSrcweir if (aEvent.Source == m_xNewDocBroadcaster) 1004cdf0e10cSrcweir { 1005cdf0e10cSrcweir m_xNewDocBroadcaster.clear(); 1006cdf0e10cSrcweir return; 1007cdf0e10cSrcweir } 1008cdf0e10cSrcweir 1009cdf0e10cSrcweir if (aEvent.Source == m_xRecoveryCFG) 1010cdf0e10cSrcweir { 1011cdf0e10cSrcweir m_xRecoveryCFG.clear(); 1012cdf0e10cSrcweir return; 1013cdf0e10cSrcweir } 1014cdf0e10cSrcweir 1015cdf0e10cSrcweir // dispose from one of our cached documents ? 1016e9faf1d9Smseidel // Normally they should send a OnUnload message ... 1017cdf0e10cSrcweir // But some stacktraces shows another possible use case .-) 1018cdf0e10cSrcweir css::uno::Reference< css::frame::XModel > xDocument(aEvent.Source, css::uno::UNO_QUERY); 1019cdf0e10cSrcweir if (xDocument.is()) 1020cdf0e10cSrcweir { 1021cdf0e10cSrcweir implts_deregisterDocument(xDocument, sal_False); // sal_False => dont call removeEventListener() .. because it's not needed here 1022cdf0e10cSrcweir return; 1023cdf0e10cSrcweir } 1024cdf0e10cSrcweir 1025cdf0e10cSrcweir // <- SAFE ---------------------------------- 1026cdf0e10cSrcweir } 1027cdf0e10cSrcweir 1028cdf0e10cSrcweir //----------------------------------------------- 1029cdf0e10cSrcweir css::uno::Reference< css::container::XNameAccess > AutoRecovery::implts_openConfig() 1030cdf0e10cSrcweir { 1031cdf0e10cSrcweir // SAFE -> ---------------------------------- 1032cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1033cdf0e10cSrcweir 1034cdf0e10cSrcweir if (m_xRecoveryCFG.is()) 1035cdf0e10cSrcweir return m_xRecoveryCFG; 1036cdf0e10cSrcweir css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 1037cdf0e10cSrcweir 1038cdf0e10cSrcweir aWriteLock.unlock(); 1039cdf0e10cSrcweir // <- SAFE ---------------------------------- 1040cdf0e10cSrcweir 1041cdf0e10cSrcweir // throws a RuntimeException if an error occure! 1042cdf0e10cSrcweir css::uno::Reference< css::container::XNameAccess > xCFG( 1043cdf0e10cSrcweir ::comphelper::ConfigurationHelper::openConfig(xSMGR, CFG_PACKAGE_RECOVERY, ::comphelper::ConfigurationHelper::E_STANDARD), 1044cdf0e10cSrcweir css::uno::UNO_QUERY); 1045cdf0e10cSrcweir 1046cdf0e10cSrcweir sal_Int32 nMinSpaceDocSave = MIN_DISCSPACE_DOCSAVE; 1047cdf0e10cSrcweir sal_Int32 nMinSpaceConfigSave = MIN_DISCSPACE_CONFIGSAVE; 1048cdf0e10cSrcweir 1049cdf0e10cSrcweir try 1050cdf0e10cSrcweir { 1051cdf0e10cSrcweir ::comphelper::ConfigurationHelper::readDirectKey(xSMGR, 1052cdf0e10cSrcweir CFG_PACKAGE_RECOVERY, 1053cdf0e10cSrcweir CFG_PATH_AUTOSAVE, 1054cdf0e10cSrcweir CFG_ENTRY_MINSPACE_DOCSAVE, 1055cdf0e10cSrcweir ::comphelper::ConfigurationHelper::E_STANDARD) >>= nMinSpaceDocSave; 1056cdf0e10cSrcweir 1057cdf0e10cSrcweir ::comphelper::ConfigurationHelper::readDirectKey(xSMGR, 1058cdf0e10cSrcweir CFG_PACKAGE_RECOVERY, 1059cdf0e10cSrcweir CFG_PATH_AUTOSAVE, 1060cdf0e10cSrcweir CFG_ENTRY_MINSPACE_CONFIGSAVE, 1061cdf0e10cSrcweir ::comphelper::ConfigurationHelper::E_STANDARD) >>= nMinSpaceConfigSave; 1062cdf0e10cSrcweir } 1063cdf0e10cSrcweir catch(const css::uno::Exception&) 1064cdf0e10cSrcweir { 1065cdf0e10cSrcweir // These config keys are not sooooo important, that 106607a3d7f1SPedro Giffuni // we are interested on errors here really .-) 1067cdf0e10cSrcweir nMinSpaceDocSave = MIN_DISCSPACE_DOCSAVE; 1068cdf0e10cSrcweir nMinSpaceConfigSave = MIN_DISCSPACE_CONFIGSAVE; 1069cdf0e10cSrcweir } 1070cdf0e10cSrcweir 1071cdf0e10cSrcweir // SAFE -> ---------------------------------- 1072cdf0e10cSrcweir aWriteLock.lock(); 1073cdf0e10cSrcweir m_xRecoveryCFG = xCFG; 1074cdf0e10cSrcweir m_nMinSpaceDocSave = nMinSpaceDocSave; 1075cdf0e10cSrcweir m_nMinSpaceConfigSave = nMinSpaceConfigSave; 1076cdf0e10cSrcweir aWriteLock.unlock(); 1077cdf0e10cSrcweir // <- SAFE ---------------------------------- 1078cdf0e10cSrcweir 1079cdf0e10cSrcweir return xCFG; 1080cdf0e10cSrcweir } 1081cdf0e10cSrcweir 1082cdf0e10cSrcweir //----------------------------------------------- 1083cdf0e10cSrcweir void AutoRecovery::implts_readAutoSaveConfig() 1084cdf0e10cSrcweir { 1085cdf0e10cSrcweir css::uno::Reference< css::container::XHierarchicalNameAccess > xCommonRegistry(implts_openConfig(), css::uno::UNO_QUERY); 1086cdf0e10cSrcweir 1087cdf0e10cSrcweir // AutoSave [bool] 1088cdf0e10cSrcweir sal_Bool bEnabled = sal_False; 1089cdf0e10cSrcweir xCommonRegistry->getByHierarchicalName(CFG_ENTRY_AUTOSAVE_ENABLED) >>= bEnabled; 1090cdf0e10cSrcweir 1091cdf0e10cSrcweir // SAFE -> ------------------------------ 1092cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1093cdf0e10cSrcweir if (bEnabled) 1094cdf0e10cSrcweir { 1095cdf0e10cSrcweir m_eJob |= AutoRecovery::E_AUTO_SAVE; 1096cdf0e10cSrcweir m_eTimerType = AutoRecovery::E_NORMAL_AUTOSAVE_INTERVALL; 1097cdf0e10cSrcweir } 1098cdf0e10cSrcweir else 1099cdf0e10cSrcweir { 1100cdf0e10cSrcweir m_eJob &= ~AutoRecovery::E_AUTO_SAVE; 1101cdf0e10cSrcweir m_eTimerType = AutoRecovery::E_DONT_START_TIMER; 1102cdf0e10cSrcweir } 1103cdf0e10cSrcweir aWriteLock.unlock(); 1104cdf0e10cSrcweir // <- SAFE ------------------------------ 1105cdf0e10cSrcweir 1106cdf0e10cSrcweir // AutoSaveTimeIntervall [int] in min 1107cdf0e10cSrcweir sal_Int32 nTimeIntervall = 15; 1108cdf0e10cSrcweir xCommonRegistry->getByHierarchicalName(CFG_ENTRY_AUTOSAVE_TIMEINTERVALL) >>= nTimeIntervall; 1109cdf0e10cSrcweir 1110cdf0e10cSrcweir // SAFE -> ---------------------------------- 1111cdf0e10cSrcweir aWriteLock.lock(); 1112cdf0e10cSrcweir m_nAutoSaveTimeIntervall = nTimeIntervall; 1113cdf0e10cSrcweir aWriteLock.unlock(); 1114cdf0e10cSrcweir // <- SAFE ---------------------------------- 1115cdf0e10cSrcweir } 1116cdf0e10cSrcweir 1117cdf0e10cSrcweir //----------------------------------------------- 1118cdf0e10cSrcweir void AutoRecovery::implts_readConfig() 1119cdf0e10cSrcweir { 1120cdf0e10cSrcweir implts_readAutoSaveConfig(); 1121cdf0e10cSrcweir 1122cdf0e10cSrcweir css::uno::Reference< css::container::XHierarchicalNameAccess > xCommonRegistry(implts_openConfig(), css::uno::UNO_QUERY); 1123cdf0e10cSrcweir 1124cdf0e10cSrcweir // REENTRANT -> -------------------------------- 1125cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_ADD_REMOVE); 1126cdf0e10cSrcweir 1127cdf0e10cSrcweir // THREADSAFE -> ------------------------------- 1128cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1129cdf0e10cSrcweir // reset current cache load cache 1130cdf0e10cSrcweir m_lDocCache.clear(); 1131cdf0e10cSrcweir m_nIdPool = 0; 1132cdf0e10cSrcweir aWriteLock.unlock(); 1133cdf0e10cSrcweir // <- THREADSAFE ------------------------------- 1134cdf0e10cSrcweir 1135cdf0e10cSrcweir aCacheLock.unlock(); 1136cdf0e10cSrcweir // <- REENTRANT -------------------------------- 1137cdf0e10cSrcweir 1138cdf0e10cSrcweir css::uno::Any aValue; 1139cdf0e10cSrcweir 1140cdf0e10cSrcweir // RecoveryList [set] 1141cdf0e10cSrcweir aValue = xCommonRegistry->getByHierarchicalName(CFG_ENTRY_RECOVERYLIST); 1142cdf0e10cSrcweir css::uno::Reference< css::container::XNameAccess > xList; 1143cdf0e10cSrcweir aValue >>= xList; 1144cdf0e10cSrcweir if (xList.is()) 1145cdf0e10cSrcweir { 1146cdf0e10cSrcweir const css::uno::Sequence< ::rtl::OUString > lItems = xList->getElementNames(); 1147cdf0e10cSrcweir const ::rtl::OUString* pItems = lItems.getConstArray(); 1148cdf0e10cSrcweir sal_Int32 c = lItems.getLength(); 1149cdf0e10cSrcweir sal_Int32 i = 0; 1150cdf0e10cSrcweir 1151cdf0e10cSrcweir // REENTRANT -> -------------------------- 1152cdf0e10cSrcweir aCacheLock.lock(LOCK_FOR_CACHE_ADD_REMOVE); 1153cdf0e10cSrcweir 1154cdf0e10cSrcweir for (i=0; i<c; ++i) 1155cdf0e10cSrcweir { 1156cdf0e10cSrcweir css::uno::Reference< css::beans::XPropertySet > xItem; 1157cdf0e10cSrcweir xList->getByName(pItems[i]) >>= xItem; 1158cdf0e10cSrcweir if (!xItem.is()) 1159cdf0e10cSrcweir continue; 1160cdf0e10cSrcweir 1161cdf0e10cSrcweir AutoRecovery::TDocumentInfo aInfo; 1162cdf0e10cSrcweir aInfo.NewTempURL = ::rtl::OUString(); 1163cdf0e10cSrcweir aInfo.Document = css::uno::Reference< css::frame::XModel >(); 1164cdf0e10cSrcweir xItem->getPropertyValue(CFG_ENTRY_PROP_ORIGINALURL ) >>= aInfo.OrgURL ; 1165cdf0e10cSrcweir xItem->getPropertyValue(CFG_ENTRY_PROP_TEMPURL ) >>= aInfo.OldTempURL ; 1166cdf0e10cSrcweir xItem->getPropertyValue(CFG_ENTRY_PROP_TEMPLATEURL ) >>= aInfo.TemplateURL ; 1167cdf0e10cSrcweir xItem->getPropertyValue(CFG_ENTRY_PROP_FILTER ) >>= aInfo.RealFilter ; 1168cdf0e10cSrcweir xItem->getPropertyValue(CFG_ENTRY_PROP_DOCUMENTSTATE) >>= aInfo.DocumentState; 1169cdf0e10cSrcweir xItem->getPropertyValue(CFG_ENTRY_PROP_MODULE ) >>= aInfo.AppModule ; 1170cdf0e10cSrcweir xItem->getPropertyValue(CFG_ENTRY_PROP_TITLE ) >>= aInfo.Title ; 1171cdf0e10cSrcweir xItem->getPropertyValue(CFG_ENTRY_PROP_VIEWNAMES ) >>= aInfo.ViewNames ; 1172cdf0e10cSrcweir implts_specifyAppModuleAndFactory(aInfo); 1173cdf0e10cSrcweir implts_specifyDefaultFilterAndExtension(aInfo); 1174cdf0e10cSrcweir 1175cdf0e10cSrcweir if (pItems[i].indexOf(RECOVERY_ITEM_BASE_IDENTIFIER)==0) 1176cdf0e10cSrcweir { 1177cdf0e10cSrcweir ::rtl::OUString sID = pItems[i].copy(RECOVERY_ITEM_BASE_IDENTIFIER.getLength()); 1178cdf0e10cSrcweir aInfo.ID = sID.toInt32(); 1179cdf0e10cSrcweir // SAFE -> ---------------------- 1180cdf0e10cSrcweir aWriteLock.lock(); 1181cdf0e10cSrcweir if (aInfo.ID > m_nIdPool) 1182cdf0e10cSrcweir { 1183cdf0e10cSrcweir m_nIdPool = aInfo.ID+1; 1184cdf0e10cSrcweir LOG_ASSERT(m_nIdPool>=0, "AutoRecovery::implts_readConfig()\nOverflow of IDPool detected!") 1185cdf0e10cSrcweir } 1186cdf0e10cSrcweir aWriteLock.unlock(); 1187cdf0e10cSrcweir // <- SAFE ---------------------- 1188cdf0e10cSrcweir } 1189cdf0e10cSrcweir #ifdef ENABLE_WARNINGS 1190cdf0e10cSrcweir else 1191cdf0e10cSrcweir LOG_WARNING("AutoRecovery::implts_readConfig()", "Who changed numbering of recovery items? Cache will be inconsistent then! I do not know, what will happen next time .-)") 1192cdf0e10cSrcweir #endif 1193cdf0e10cSrcweir 1194cdf0e10cSrcweir // THREADSAFE -> -------------------------- 1195cdf0e10cSrcweir aWriteLock.lock(); 1196cdf0e10cSrcweir m_lDocCache.push_back(aInfo); 1197cdf0e10cSrcweir aWriteLock.unlock(); 1198cdf0e10cSrcweir // <- THREADSAFE -------------------------- 1199cdf0e10cSrcweir } 1200cdf0e10cSrcweir 1201cdf0e10cSrcweir aCacheLock.unlock(); 1202cdf0e10cSrcweir // <- REENTRANT -------------------------- 1203cdf0e10cSrcweir } 1204cdf0e10cSrcweir 1205cdf0e10cSrcweir implts_updateTimer(); 1206cdf0e10cSrcweir } 1207cdf0e10cSrcweir 1208cdf0e10cSrcweir //----------------------------------------------- 1209cdf0e10cSrcweir void AutoRecovery::implts_specifyDefaultFilterAndExtension(AutoRecovery::TDocumentInfo& rInfo) 1210cdf0e10cSrcweir { 1211cdf0e10cSrcweir if (!rInfo.AppModule.getLength()) 1212cdf0e10cSrcweir { 1213cdf0e10cSrcweir throw css::uno::RuntimeException( 121407a3d7f1SPedro Giffuni ::rtl::OUString::createFromAscii("Can't find out the default filter and its extension, if no application module is known!"), 1215cdf0e10cSrcweir static_cast< css::frame::XDispatch* >(this)); 1216cdf0e10cSrcweir } 1217cdf0e10cSrcweir 1218cdf0e10cSrcweir // SAFE -> ---------------------------------- 1219cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 1220cdf0e10cSrcweir css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 1221cdf0e10cSrcweir css::uno::Reference< css::container::XNameAccess> xCFG = m_xModuleCFG; 1222cdf0e10cSrcweir aReadLock.unlock(); 1223cdf0e10cSrcweir // <- SAFE ---------------------------------- 1224cdf0e10cSrcweir 1225cdf0e10cSrcweir try 1226cdf0e10cSrcweir { 1227cdf0e10cSrcweir if (! xCFG.is()) 1228cdf0e10cSrcweir { 1229cdf0e10cSrcweir // open module config on demand and cache the update access 1230cdf0e10cSrcweir xCFG = css::uno::Reference< css::container::XNameAccess >( 1231cdf0e10cSrcweir ::comphelper::ConfigurationHelper::openConfig(xSMGR, CFG_PACKAGE_MODULES, ::comphelper::ConfigurationHelper::E_STANDARD), 1232cdf0e10cSrcweir css::uno::UNO_QUERY_THROW); 1233cdf0e10cSrcweir 1234cdf0e10cSrcweir // SAFE -> ---------------------------------- 1235cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1236cdf0e10cSrcweir m_xModuleCFG = xCFG; 1237cdf0e10cSrcweir aWriteLock.unlock(); 1238cdf0e10cSrcweir // <- SAFE ---------------------------------- 1239cdf0e10cSrcweir } 1240cdf0e10cSrcweir 1241cdf0e10cSrcweir css::uno::Reference< css::container::XNameAccess > xModuleProps( 1242cdf0e10cSrcweir xCFG->getByName(rInfo.AppModule), 1243cdf0e10cSrcweir css::uno::UNO_QUERY_THROW); 1244cdf0e10cSrcweir 1245cdf0e10cSrcweir xModuleProps->getByName(CFG_ENTRY_REALDEFAULTFILTER) >>= rInfo.DefaultFilter; 1246cdf0e10cSrcweir 1247cdf0e10cSrcweir css::uno::Reference< css::container::XNameAccess > xFilterCFG(xSMGR->createInstance(SERVICENAME_FILTERFACTORY), css::uno::UNO_QUERY_THROW); 1248cdf0e10cSrcweir css::uno::Reference< css::container::XNameAccess > xTypeCFG (xSMGR->createInstance(SERVICENAME_TYPEDETECTION), css::uno::UNO_QUERY_THROW); 1249cdf0e10cSrcweir 1250cdf0e10cSrcweir ::comphelper::SequenceAsHashMap lFilterProps (xFilterCFG->getByName(rInfo.DefaultFilter)); 1251cdf0e10cSrcweir ::rtl::OUString sTypeRegistration = lFilterProps.getUnpackedValueOrDefault(FILTER_PROP_TYPE, ::rtl::OUString()); 1252cdf0e10cSrcweir ::comphelper::SequenceAsHashMap lTypeProps (xTypeCFG->getByName(sTypeRegistration)); 1253cdf0e10cSrcweir css::uno::Sequence< ::rtl::OUString > lExtensions = lTypeProps.getUnpackedValueOrDefault(TYPE_PROP_EXTENSIONS, css::uno::Sequence< ::rtl::OUString >()); 1254cdf0e10cSrcweir if (lExtensions.getLength()) 1255cdf0e10cSrcweir { 1256cdf0e10cSrcweir rInfo.Extension = ::rtl::OUString::createFromAscii("."); 1257cdf0e10cSrcweir rInfo.Extension += lExtensions[0]; 1258cdf0e10cSrcweir } 1259cdf0e10cSrcweir else 1260cdf0e10cSrcweir rInfo.Extension = ::rtl::OUString::createFromAscii(".unknown"); 1261cdf0e10cSrcweir } 1262cdf0e10cSrcweir catch(const css::uno::Exception&) 1263cdf0e10cSrcweir { 1264cdf0e10cSrcweir rInfo.DefaultFilter = ::rtl::OUString(); 1265cdf0e10cSrcweir rInfo.Extension = ::rtl::OUString(); 1266cdf0e10cSrcweir } 1267cdf0e10cSrcweir } 1268cdf0e10cSrcweir 1269cdf0e10cSrcweir //----------------------------------------------- 1270cdf0e10cSrcweir void AutoRecovery::implts_specifyAppModuleAndFactory(AutoRecovery::TDocumentInfo& rInfo) 1271cdf0e10cSrcweir { 1272cdf0e10cSrcweir ENSURE_OR_THROW2( 1273cdf0e10cSrcweir rInfo.AppModule.getLength() || rInfo.Document.is(), 127407a3d7f1SPedro Giffuni "Can't find out the application module nor its factory URL, if no application module (or a suitable) document is known!", 1275cdf0e10cSrcweir *this ); 1276cdf0e10cSrcweir 1277cdf0e10cSrcweir // SAFE -> ---------------------------------- 1278cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 1279cdf0e10cSrcweir css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 1280cdf0e10cSrcweir aReadLock.unlock(); 1281cdf0e10cSrcweir // <- SAFE ---------------------------------- 1282cdf0e10cSrcweir 1283cdf0e10cSrcweir css::uno::Reference< css::frame::XModuleManager > xManager (xSMGR->createInstance(SERVICENAME_MODULEMANAGER), css::uno::UNO_QUERY_THROW); 1284cdf0e10cSrcweir css::uno::Reference< css::container::XNameAccess > xModuleConfig(xManager , css::uno::UNO_QUERY_THROW); 1285cdf0e10cSrcweir 1286cdf0e10cSrcweir if (!rInfo.AppModule.getLength()) 1287cdf0e10cSrcweir rInfo.AppModule = xManager->identify(rInfo.Document); 1288cdf0e10cSrcweir 1289cdf0e10cSrcweir ::comphelper::SequenceAsHashMap lModuleDescription(xModuleConfig->getByName(rInfo.AppModule)); 1290cdf0e10cSrcweir lModuleDescription[CFG_ENTRY_PROP_EMPTYDOCUMENTURL] >>= rInfo.FactoryURL; 1291cdf0e10cSrcweir lModuleDescription[CFG_ENTRY_PROP_FACTORYSERVICE] >>= rInfo.FactoryService; 1292cdf0e10cSrcweir } 1293cdf0e10cSrcweir 1294cdf0e10cSrcweir //----------------------------------------------- 1295cdf0e10cSrcweir void AutoRecovery::implts_collectActiveViewNames( AutoRecovery::TDocumentInfo& i_rInfo ) 1296cdf0e10cSrcweir { 1297cdf0e10cSrcweir ENSURE_OR_THROW2( i_rInfo.Document.is(), "need at document, at the very least", *this ); 1298cdf0e10cSrcweir 1299cdf0e10cSrcweir i_rInfo.ViewNames.realloc(0); 1300cdf0e10cSrcweir 1301cdf0e10cSrcweir // obtain list of controllers of this document 1302cdf0e10cSrcweir ::std::vector< ::rtl::OUString > aViewNames; 1303cdf0e10cSrcweir const Reference< XModel2 > xModel( i_rInfo.Document, UNO_QUERY ); 1304cdf0e10cSrcweir if ( xModel.is() ) 1305cdf0e10cSrcweir { 1306cdf0e10cSrcweir const Reference< XEnumeration > xEnumControllers( xModel->getControllers() ); 1307cdf0e10cSrcweir while ( xEnumControllers->hasMoreElements() ) 1308cdf0e10cSrcweir { 1309cdf0e10cSrcweir const Reference< XController2 > xController( xEnumControllers->nextElement(), UNO_QUERY ); 1310cdf0e10cSrcweir ::rtl::OUString sViewName; 1311cdf0e10cSrcweir if ( xController.is() ) 1312cdf0e10cSrcweir sViewName = xController->getViewControllerName(); 1313cdf0e10cSrcweir OSL_ENSURE( sViewName.getLength(), "AutoRecovery::implts_collectActiveViewNames: (no XController2 ->) no view name -> no recovery of this view!" ); 1314cdf0e10cSrcweir 1315cdf0e10cSrcweir if ( sViewName.getLength() ) 1316cdf0e10cSrcweir aViewNames.push_back( sViewName ); 1317cdf0e10cSrcweir } 1318cdf0e10cSrcweir } 1319cdf0e10cSrcweir else 1320cdf0e10cSrcweir { 1321cdf0e10cSrcweir const Reference< XController2 > xController( xModel->getCurrentController(), UNO_QUERY ); 1322cdf0e10cSrcweir ::rtl::OUString sViewName; 1323cdf0e10cSrcweir if ( xController.is() ) 1324cdf0e10cSrcweir sViewName = xController->getViewControllerName(); 1325cdf0e10cSrcweir OSL_ENSURE( sViewName.getLength(), "AutoRecovery::implts_collectActiveViewNames: (no XController2 ->) no view name -> no recovery of this view!" ); 1326cdf0e10cSrcweir 1327cdf0e10cSrcweir if ( sViewName.getLength() ) 1328cdf0e10cSrcweir aViewNames.push_back( sViewName ); 1329cdf0e10cSrcweir } 1330cdf0e10cSrcweir 1331cdf0e10cSrcweir i_rInfo.ViewNames.realloc( aViewNames.size() ); 1332cdf0e10cSrcweir ::std::copy( aViewNames.begin(), aViewNames.end(), i_rInfo.ViewNames.getArray() ); 1333cdf0e10cSrcweir } 1334cdf0e10cSrcweir 1335cdf0e10cSrcweir //----------------------------------------------- 1336cdf0e10cSrcweir void AutoRecovery::implts_persistAllActiveViewNames() 1337cdf0e10cSrcweir { 1338cdf0e10cSrcweir // SAFE -> ---------------------------------- 1339cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1340cdf0e10cSrcweir 1341cdf0e10cSrcweir // This list will be filled with every document 1342cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt; 1343cdf0e10cSrcweir for ( pIt = m_lDocCache.begin(); 1344cdf0e10cSrcweir pIt != m_lDocCache.end() ; 1345cdf0e10cSrcweir ++pIt ) 1346cdf0e10cSrcweir { 1347cdf0e10cSrcweir implts_collectActiveViewNames( *pIt ); 1348cdf0e10cSrcweir implts_flushConfigItem( *pIt ); 1349cdf0e10cSrcweir } 1350cdf0e10cSrcweir } 1351cdf0e10cSrcweir 1352cdf0e10cSrcweir //----------------------------------------------- 1353cdf0e10cSrcweir void AutoRecovery::implts_flushConfigItem(const AutoRecovery::TDocumentInfo& rInfo, sal_Bool bRemoveIt) 1354cdf0e10cSrcweir { 1355cdf0e10cSrcweir css::uno::Reference< css::container::XHierarchicalNameAccess > xCFG; 1356cdf0e10cSrcweir 1357cdf0e10cSrcweir try 1358cdf0e10cSrcweir { 1359cdf0e10cSrcweir xCFG = css::uno::Reference< css::container::XHierarchicalNameAccess >(implts_openConfig(), css::uno::UNO_QUERY_THROW); 1360cdf0e10cSrcweir 1361cdf0e10cSrcweir css::uno::Reference< css::container::XNameAccess > xCheck; 1362cdf0e10cSrcweir xCFG->getByHierarchicalName(CFG_ENTRY_RECOVERYLIST) >>= xCheck; 1363cdf0e10cSrcweir 1364cdf0e10cSrcweir css::uno::Reference< css::container::XNameContainer > xModify(xCheck, css::uno::UNO_QUERY_THROW); 1365cdf0e10cSrcweir css::uno::Reference< css::lang::XSingleServiceFactory > xCreate(xCheck, css::uno::UNO_QUERY_THROW); 1366cdf0e10cSrcweir 1367cdf0e10cSrcweir ::rtl::OUStringBuffer sIDBuf; 1368cdf0e10cSrcweir sIDBuf.append(RECOVERY_ITEM_BASE_IDENTIFIER); 1369cdf0e10cSrcweir sIDBuf.append((sal_Int32)rInfo.ID); 1370cdf0e10cSrcweir ::rtl::OUString sID = sIDBuf.makeStringAndClear(); 1371cdf0e10cSrcweir 1372cdf0e10cSrcweir // remove 1373cdf0e10cSrcweir if (bRemoveIt) 1374cdf0e10cSrcweir { 1375cdf0e10cSrcweir // Catch NoSuchElementException. 1376cdf0e10cSrcweir // Its not a good idea inside multithreaded environments to call hasElement - removeElement. 1377cdf0e10cSrcweir // DO IT! 1378cdf0e10cSrcweir try 1379cdf0e10cSrcweir { 1380cdf0e10cSrcweir xModify->removeByName(sID); 1381cdf0e10cSrcweir } 1382cdf0e10cSrcweir catch(const css::container::NoSuchElementException&) 1383cdf0e10cSrcweir { return; } 1384cdf0e10cSrcweir } 1385cdf0e10cSrcweir else 1386cdf0e10cSrcweir { 1387cdf0e10cSrcweir // new/modify 1388cdf0e10cSrcweir css::uno::Reference< css::beans::XPropertySet > xSet; 1389cdf0e10cSrcweir sal_Bool bNew = (!xCheck->hasByName(sID)); 1390cdf0e10cSrcweir if (bNew) 1391cdf0e10cSrcweir xSet = css::uno::Reference< css::beans::XPropertySet >(xCreate->createInstance(), css::uno::UNO_QUERY_THROW); 1392cdf0e10cSrcweir else 1393cdf0e10cSrcweir xCheck->getByName(sID) >>= xSet; 1394cdf0e10cSrcweir 1395cdf0e10cSrcweir xSet->setPropertyValue(CFG_ENTRY_PROP_ORIGINALURL , css::uno::makeAny(rInfo.OrgURL )); 1396cdf0e10cSrcweir xSet->setPropertyValue(CFG_ENTRY_PROP_TEMPURL , css::uno::makeAny(rInfo.OldTempURL )); 1397cdf0e10cSrcweir xSet->setPropertyValue(CFG_ENTRY_PROP_TEMPLATEURL , css::uno::makeAny(rInfo.TemplateURL )); 1398cdf0e10cSrcweir xSet->setPropertyValue(CFG_ENTRY_PROP_FILTER , css::uno::makeAny(rInfo.RealFilter )); 1399cdf0e10cSrcweir xSet->setPropertyValue(CFG_ENTRY_PROP_DOCUMENTSTATE, css::uno::makeAny(rInfo.DocumentState)); 1400cdf0e10cSrcweir xSet->setPropertyValue(CFG_ENTRY_PROP_MODULE , css::uno::makeAny(rInfo.AppModule )); 1401cdf0e10cSrcweir xSet->setPropertyValue(CFG_ENTRY_PROP_TITLE , css::uno::makeAny(rInfo.Title )); 1402cdf0e10cSrcweir xSet->setPropertyValue(CFG_ENTRY_PROP_VIEWNAMES , css::uno::makeAny(rInfo.ViewNames )); 1403cdf0e10cSrcweir 1404cdf0e10cSrcweir if (bNew) 1405cdf0e10cSrcweir xModify->insertByName(sID, css::uno::makeAny(xSet)); 1406cdf0e10cSrcweir } 1407cdf0e10cSrcweir } 1408cdf0e10cSrcweir catch(const css::uno::RuntimeException& exRun) 1409cdf0e10cSrcweir { throw exRun; } 1410cdf0e10cSrcweir catch(const css::uno::Exception&) 1411cdf0e10cSrcweir {} // ??? can it happen that a full disc let these set of operations fail too ??? 1412cdf0e10cSrcweir 1413cdf0e10cSrcweir sal_Int32 nRetry = RETRY_STORE_ON_FULL_DISC_FOREVER; 1414cdf0e10cSrcweir do 1415cdf0e10cSrcweir { 1416cdf0e10cSrcweir try 1417cdf0e10cSrcweir { 1418cdf0e10cSrcweir css::uno::Reference< css::util::XChangesBatch > xFlush(xCFG, css::uno::UNO_QUERY_THROW); 1419cdf0e10cSrcweir xFlush->commitChanges(); 1420cdf0e10cSrcweir 1421cdf0e10cSrcweir #ifdef TRIGGER_FULL_DISC_CHECK 1422cdf0e10cSrcweir throw css::uno::Exception(); 1423cdf0e10cSrcweir #endif 1424cdf0e10cSrcweir 1425cdf0e10cSrcweir nRetry = 0; 1426cdf0e10cSrcweir } 1427cdf0e10cSrcweir catch(const css::uno::Exception& ex) 1428cdf0e10cSrcweir { 1429796b7e2aSmseidel // a) FULL DISC seems to be the problem behind => show error and retry it forever (e.g. retry=300) 143007a3d7f1SPedro Giffuni // b) unknown problem (may be locking problem) => reset RETRY value to more useful value(!) (e.g. retry=3) 1431cdf0e10cSrcweir // c) unknown problem (may be locking problem) + 1..2 repeating operations => throw the original exception to force generation of a stacktrace ! 1432cdf0e10cSrcweir 1433cdf0e10cSrcweir // SAFE -> 1434cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 1435cdf0e10cSrcweir sal_Int32 nMinSpaceConfigSave = m_nMinSpaceConfigSave; 1436cdf0e10cSrcweir aReadLock.unlock(); 1437cdf0e10cSrcweir // <- SAFE 1438cdf0e10cSrcweir 1439cdf0e10cSrcweir if (! impl_enoughDiscSpace(nMinSpaceConfigSave)) 1440cdf0e10cSrcweir AutoRecovery::impl_showFullDiscError(); 1441cdf0e10cSrcweir else 1442cdf0e10cSrcweir if (nRetry > RETRY_STORE_ON_MIGHT_FULL_DISC_USEFULL) 1443cdf0e10cSrcweir nRetry = RETRY_STORE_ON_MIGHT_FULL_DISC_USEFULL; 1444cdf0e10cSrcweir else 1445cdf0e10cSrcweir if (nRetry <= GIVE_UP_RETRY) 1446cdf0e10cSrcweir throw ex; // force stacktrace to know if there exist might other reasons, why an AutoSave can fail !!! 1447cdf0e10cSrcweir 1448cdf0e10cSrcweir --nRetry; 1449cdf0e10cSrcweir } 1450cdf0e10cSrcweir } 1451cdf0e10cSrcweir while(nRetry>0); 1452cdf0e10cSrcweir } 1453cdf0e10cSrcweir 1454cdf0e10cSrcweir //----------------------------------------------- 1455cdf0e10cSrcweir void AutoRecovery::implts_startListening() 1456cdf0e10cSrcweir { 1457cdf0e10cSrcweir // SAFE -> ---------------------------------- 1458cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 1459cdf0e10cSrcweir css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 1460cdf0e10cSrcweir css::uno::Reference< css::util::XChangesNotifier > xCFG (m_xRecoveryCFG, css::uno::UNO_QUERY); 1461cdf0e10cSrcweir css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster = m_xNewDocBroadcaster; 1462cdf0e10cSrcweir sal_Bool bListenForDocEvents = m_bListenForDocEvents; 1463cdf0e10cSrcweir aReadLock.unlock(); 1464cdf0e10cSrcweir // <- SAFE ---------------------------------- 1465cdf0e10cSrcweir 1466cdf0e10cSrcweir if ( 1467cdf0e10cSrcweir ( xCFG.is() ) && 1468cdf0e10cSrcweir (! m_bListenForConfigChanges) 1469cdf0e10cSrcweir ) 1470cdf0e10cSrcweir { 1471cdf0e10cSrcweir xCFG->addChangesListener(static_cast< css::util::XChangesListener* >(this)); 1472cdf0e10cSrcweir m_bListenForConfigChanges = sal_True; 1473cdf0e10cSrcweir } 1474cdf0e10cSrcweir 1475cdf0e10cSrcweir if (!xBroadcaster.is()) 1476cdf0e10cSrcweir { 1477cdf0e10cSrcweir xBroadcaster = css::uno::Reference< css::document::XEventBroadcaster >(xSMGR->createInstance(SERVICENAME_GLOBALEVENTBROADCASTER), css::uno::UNO_QUERY_THROW); 1478cdf0e10cSrcweir // SAFE -> ---------------------------------- 1479cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1480cdf0e10cSrcweir m_xNewDocBroadcaster = xBroadcaster; 1481cdf0e10cSrcweir aWriteLock.unlock(); 1482cdf0e10cSrcweir // <- SAFE ---------------------------------- 1483cdf0e10cSrcweir } 1484cdf0e10cSrcweir 1485cdf0e10cSrcweir if ( 1486cdf0e10cSrcweir ( xBroadcaster.is() ) && 1487cdf0e10cSrcweir (! bListenForDocEvents) 1488cdf0e10cSrcweir ) 1489cdf0e10cSrcweir { 1490cdf0e10cSrcweir xBroadcaster->addEventListener(static_cast< css::document::XEventListener* >(this)); 1491cdf0e10cSrcweir // SAFE -> 1492cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1493cdf0e10cSrcweir m_bListenForDocEvents = sal_True; 1494cdf0e10cSrcweir aWriteLock.unlock(); 1495cdf0e10cSrcweir // <- SAFE 1496cdf0e10cSrcweir } 1497cdf0e10cSrcweir } 1498cdf0e10cSrcweir 1499cdf0e10cSrcweir //----------------------------------------------- 1500cdf0e10cSrcweir void AutoRecovery::implts_stopListening() 1501cdf0e10cSrcweir { 1502cdf0e10cSrcweir // SAFE -> ---------------------------------- 1503cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 1504cdf0e10cSrcweir // Attention: Dont reset our internal members here too. 1505cdf0e10cSrcweir // May be we must work with our configuration, but dont wish to be informed 1506cdf0e10cSrcweir // about changes any longer. Needed e.g. during EMERGENCY_SAVE! 1507cdf0e10cSrcweir css::uno::Reference< css::util::XChangesNotifier > xCFG (m_xRecoveryCFG , css::uno::UNO_QUERY); 1508cdf0e10cSrcweir css::uno::Reference< css::document::XEventBroadcaster > xGlobalEventBroadcaster(m_xNewDocBroadcaster, css::uno::UNO_QUERY); 1509cdf0e10cSrcweir aReadLock.unlock(); 1510cdf0e10cSrcweir // <- SAFE ---------------------------------- 1511cdf0e10cSrcweir 1512cdf0e10cSrcweir if ( 1513cdf0e10cSrcweir (xGlobalEventBroadcaster.is()) && 1514cdf0e10cSrcweir (m_bListenForDocEvents ) 1515cdf0e10cSrcweir ) 1516cdf0e10cSrcweir { 1517cdf0e10cSrcweir xGlobalEventBroadcaster->removeEventListener(static_cast< css::document::XEventListener* >(this)); 1518cdf0e10cSrcweir m_bListenForDocEvents = sal_False; 1519cdf0e10cSrcweir } 1520cdf0e10cSrcweir 1521cdf0e10cSrcweir if ( 1522cdf0e10cSrcweir (xCFG.is() ) && 1523cdf0e10cSrcweir (m_bListenForConfigChanges) 1524cdf0e10cSrcweir ) 1525cdf0e10cSrcweir { 1526cdf0e10cSrcweir xCFG->removeChangesListener(static_cast< css::util::XChangesListener* >(this)); 1527cdf0e10cSrcweir m_bListenForConfigChanges = sal_False; 1528cdf0e10cSrcweir } 1529cdf0e10cSrcweir } 1530cdf0e10cSrcweir 1531cdf0e10cSrcweir //----------------------------------------------- 1532cdf0e10cSrcweir void AutoRecovery::implts_startModifyListeningOnDoc(AutoRecovery::TDocumentInfo& rInfo) 1533cdf0e10cSrcweir { 1534cdf0e10cSrcweir if (rInfo.ListenForModify) 1535cdf0e10cSrcweir return; 1536cdf0e10cSrcweir 1537cdf0e10cSrcweir css::uno::Reference< css::util::XModifyBroadcaster > xBroadcaster(rInfo.Document, css::uno::UNO_QUERY); 1538cdf0e10cSrcweir if (xBroadcaster.is()) 1539cdf0e10cSrcweir { 1540cdf0e10cSrcweir css::uno::Reference< css::util::XModifyListener > xThis(static_cast< css::frame::XDispatch* >(this), css::uno::UNO_QUERY); 1541cdf0e10cSrcweir xBroadcaster->addModifyListener(xThis); 1542cdf0e10cSrcweir rInfo.ListenForModify = sal_True; 1543cdf0e10cSrcweir } 1544cdf0e10cSrcweir } 1545cdf0e10cSrcweir 1546cdf0e10cSrcweir //----------------------------------------------- 1547cdf0e10cSrcweir void AutoRecovery::implts_stopModifyListeningOnDoc(AutoRecovery::TDocumentInfo& rInfo) 1548cdf0e10cSrcweir { 1549cdf0e10cSrcweir if (! rInfo.ListenForModify) 1550cdf0e10cSrcweir return; 1551cdf0e10cSrcweir 1552cdf0e10cSrcweir css::uno::Reference< css::util::XModifyBroadcaster > xBroadcaster(rInfo.Document, css::uno::UNO_QUERY); 1553cdf0e10cSrcweir if (xBroadcaster.is()) 1554cdf0e10cSrcweir { 1555cdf0e10cSrcweir css::uno::Reference< css::util::XModifyListener > xThis(static_cast< css::frame::XDispatch* >(this), css::uno::UNO_QUERY); 1556cdf0e10cSrcweir xBroadcaster->removeModifyListener(xThis); 1557cdf0e10cSrcweir rInfo.ListenForModify = sal_False; 1558cdf0e10cSrcweir } 1559cdf0e10cSrcweir } 1560cdf0e10cSrcweir 1561cdf0e10cSrcweir //----------------------------------------------- 1562cdf0e10cSrcweir void AutoRecovery::implts_updateTimer() 1563cdf0e10cSrcweir { 1564cdf0e10cSrcweir implts_stopTimer(); 1565cdf0e10cSrcweir 1566cdf0e10cSrcweir // SAFE -> ---------------------------------- 1567cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1568cdf0e10cSrcweir 1569cdf0e10cSrcweir if ( 1570cdf0e10cSrcweir (m_eJob == AutoRecovery::E_NO_JOB ) || // TODO may be superflous - E_DONT_START_TIMER should be used only 1571cdf0e10cSrcweir (m_eTimerType == AutoRecovery::E_DONT_START_TIMER) 1572cdf0e10cSrcweir ) 1573cdf0e10cSrcweir return; 1574cdf0e10cSrcweir 1575cdf0e10cSrcweir sal_uLong nMilliSeconds = 0; 1576cdf0e10cSrcweir if (m_eTimerType == AutoRecovery::E_NORMAL_AUTOSAVE_INTERVALL) 1577cdf0e10cSrcweir { 1578cdf0e10cSrcweir nMilliSeconds = (m_nAutoSaveTimeIntervall*60000); // [min] => 60.000 ms 1579cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 1580cdf0e10cSrcweir if (m_dbg_bMakeItFaster) 1581cdf0e10cSrcweir nMilliSeconds = m_nAutoSaveTimeIntervall; // [ms] 1582cdf0e10cSrcweir #endif 1583cdf0e10cSrcweir } 1584cdf0e10cSrcweir else 1585cdf0e10cSrcweir if (m_eTimerType == AutoRecovery::E_POLL_FOR_USER_IDLE) 1586cdf0e10cSrcweir { 1587cdf0e10cSrcweir nMilliSeconds = MIN_TIME_FOR_USER_IDLE; 1588cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 1589cdf0e10cSrcweir if (m_dbg_bMakeItFaster) 1590cdf0e10cSrcweir nMilliSeconds = 300; // let us some time, to finish this method .-) 1591cdf0e10cSrcweir #endif 1592cdf0e10cSrcweir } 1593cdf0e10cSrcweir else 1594cdf0e10cSrcweir if (m_eTimerType == AutoRecovery::E_POLL_TILL_AUTOSAVE_IS_ALLOWED) 1595cdf0e10cSrcweir nMilliSeconds = 300; // there is a minimum time frame, where the user can loose some key input data! 1596cdf0e10cSrcweir 1597cdf0e10cSrcweir m_aTimer.SetTimeout(nMilliSeconds); 1598cdf0e10cSrcweir m_aTimer.Start(); 1599cdf0e10cSrcweir 1600cdf0e10cSrcweir aWriteLock.unlock(); 1601cdf0e10cSrcweir // <- SAFE ---------------------------------- 1602cdf0e10cSrcweir } 1603cdf0e10cSrcweir 1604cdf0e10cSrcweir //----------------------------------------------- 1605cdf0e10cSrcweir void AutoRecovery::implts_stopTimer() 1606cdf0e10cSrcweir { 1607cdf0e10cSrcweir // SAFE -> ---------------------------------- 1608cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1609cdf0e10cSrcweir 1610cdf0e10cSrcweir if (!m_aTimer.IsActive()) 1611cdf0e10cSrcweir return; 1612cdf0e10cSrcweir m_aTimer.Stop(); 1613cdf0e10cSrcweir 1614cdf0e10cSrcweir // <- SAFE ---------------------------------- 1615cdf0e10cSrcweir } 1616cdf0e10cSrcweir 1617cdf0e10cSrcweir //----------------------------------------------- 1618cdf0e10cSrcweir IMPL_LINK(AutoRecovery, implts_timerExpired, void*, EMPTYARG) 1619cdf0e10cSrcweir { 1620cdf0e10cSrcweir try 1621cdf0e10cSrcweir { 1622cdf0e10cSrcweir // This method is called by using a pointer to us. 1623cdf0e10cSrcweir // But we must be aware that we can be destroyed hardly 1624cdf0e10cSrcweir // if our uno reference will be gone! 1625cdf0e10cSrcweir // => Hold this object alive till this method finish its work. 1626cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface > xSelfHold(static_cast< css::lang::XTypeProvider* >(this)); 1627cdf0e10cSrcweir 1628cdf0e10cSrcweir // Needed! Otherwise every reschedule request allow a new triggered timer event :-( 1629cdf0e10cSrcweir implts_stopTimer(); 1630cdf0e10cSrcweir 1631cdf0e10cSrcweir // The timer must be ignored if AutoSave/Recovery was disabled for this 1632cdf0e10cSrcweir // office session. That can happen if e.g. the command line arguments "-norestore" or "-headless" 1633e9faf1d9Smseidel // was set. But normally the timer was disabled if recovery was disabled ... 1634cdf0e10cSrcweir // But so we are more "safe" .-) 1635cdf0e10cSrcweir // SAFE -> ---------------------------------- 1636cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 1637cdf0e10cSrcweir if ((m_eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) == AutoRecovery::E_DISABLE_AUTORECOVERY) 1638cdf0e10cSrcweir return 0; 1639cdf0e10cSrcweir aReadLock.unlock(); 1640cdf0e10cSrcweir // <- SAFE ---------------------------------- 1641cdf0e10cSrcweir 1642cdf0e10cSrcweir // check some "states", where its not allowed (better: not a good idea) to 1643cdf0e10cSrcweir // start an AutoSave. (e.g. if the user makes drag & drop ...) 1644cdf0e10cSrcweir // Then we poll till this "disallowed" state is gone. 1645cdf0e10cSrcweir sal_Bool bAutoSaveNotAllowed = Application::IsUICaptured(); 1646cdf0e10cSrcweir if (bAutoSaveNotAllowed) 1647cdf0e10cSrcweir { 1648cdf0e10cSrcweir // SAFE -> ------------------------------ 1649cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1650cdf0e10cSrcweir m_eTimerType = AutoRecovery::E_POLL_TILL_AUTOSAVE_IS_ALLOWED; 1651cdf0e10cSrcweir aWriteLock.unlock(); 1652cdf0e10cSrcweir // <- SAFE ------------------------------ 1653cdf0e10cSrcweir implts_updateTimer(); 1654cdf0e10cSrcweir return 0; 1655cdf0e10cSrcweir } 1656cdf0e10cSrcweir 1657cdf0e10cSrcweir // analyze timer type. 1658cdf0e10cSrcweir // If we poll for an user idle period, may be we must 1659cdf0e10cSrcweir // do nothing here and start the timer again. 1660cdf0e10cSrcweir // SAFE -> ---------------------------------- 1661cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1662cdf0e10cSrcweir 1663cdf0e10cSrcweir if (m_eTimerType == AutoRecovery::E_POLL_FOR_USER_IDLE) 1664cdf0e10cSrcweir { 1665cdf0e10cSrcweir sal_Bool bUserIdle = (Application::GetLastInputInterval()>MIN_TIME_FOR_USER_IDLE); 1666cdf0e10cSrcweir if (!bUserIdle) 1667cdf0e10cSrcweir { 1668cdf0e10cSrcweir implts_updateTimer(); 1669cdf0e10cSrcweir return 0; 1670cdf0e10cSrcweir } 1671cdf0e10cSrcweir } 1672cdf0e10cSrcweir 1673cdf0e10cSrcweir aWriteLock.unlock(); 1674cdf0e10cSrcweir // <- SAFE ---------------------------------- 1675cdf0e10cSrcweir 1676cdf0e10cSrcweir implts_informListener(AutoRecovery::E_AUTO_SAVE, 1677cdf0e10cSrcweir AutoRecovery::implst_createFeatureStateEvent(AutoRecovery::E_AUTO_SAVE, OPERATION_START, NULL)); 1678cdf0e10cSrcweir 1679cdf0e10cSrcweir // force save of all currently open documents 1680cdf0e10cSrcweir // The called method returns an info, if and how this 1681cdf0e10cSrcweir // timer must be restarted. 1682cdf0e10cSrcweir sal_Bool bAllowUserIdleLoop = sal_True; 1683cdf0e10cSrcweir AutoRecovery::ETimerType eSuggestedTimer = implts_saveDocs(bAllowUserIdleLoop, sal_False); 1684cdf0e10cSrcweir 168507a3d7f1SPedro Giffuni // If timer isn't used for "short callbacks" (means polling 1686cdf0e10cSrcweir // for special states) ... reset the handle state of all 1687cdf0e10cSrcweir // cache items. Such handle state indicates, that a document 1688cdf0e10cSrcweir // was already saved during the THIS(!) AutoSave session. 1689cdf0e10cSrcweir // Of course NEXT AutoSave session must be started without 1690cdf0e10cSrcweir // any "handle" state ... 1691cdf0e10cSrcweir if ( 1692cdf0e10cSrcweir (eSuggestedTimer == AutoRecovery::E_DONT_START_TIMER ) || 1693cdf0e10cSrcweir (eSuggestedTimer == AutoRecovery::E_NORMAL_AUTOSAVE_INTERVALL) 1694cdf0e10cSrcweir ) 1695cdf0e10cSrcweir { 1696cdf0e10cSrcweir implts_resetHandleStates(sal_False); 1697cdf0e10cSrcweir } 1698cdf0e10cSrcweir 1699cdf0e10cSrcweir implts_informListener(AutoRecovery::E_AUTO_SAVE, 1700cdf0e10cSrcweir AutoRecovery::implst_createFeatureStateEvent(AutoRecovery::E_AUTO_SAVE, OPERATION_STOP, NULL)); 1701cdf0e10cSrcweir 1702cdf0e10cSrcweir // restart timer - because it was disabled before ... 1703cdf0e10cSrcweir // SAFE -> ---------------------------------- 1704cdf0e10cSrcweir aWriteLock.lock(); 1705cdf0e10cSrcweir m_eTimerType = eSuggestedTimer; 1706cdf0e10cSrcweir aWriteLock.unlock(); 1707cdf0e10cSrcweir // <- SAFE ---------------------------------- 1708cdf0e10cSrcweir 1709cdf0e10cSrcweir implts_updateTimer(); 1710cdf0e10cSrcweir } 1711cdf0e10cSrcweir catch(const css::uno::Exception&) 1712cdf0e10cSrcweir { 1713cdf0e10cSrcweir LOG_ASSERT(sal_False, "May be you found the reason for bug #125528#. Please report a test scenario to the right developer. THX."); 1714cdf0e10cSrcweir } 1715cdf0e10cSrcweir 1716cdf0e10cSrcweir return 0; 1717cdf0e10cSrcweir } 1718cdf0e10cSrcweir 1719cdf0e10cSrcweir //----------------------------------------------- 1720cdf0e10cSrcweir IMPL_LINK(AutoRecovery, implts_asyncDispatch, void*, EMPTYARG) 1721cdf0e10cSrcweir { 1722cdf0e10cSrcweir // SAFE -> 1723cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1724cdf0e10cSrcweir DispatchParams aParams = m_aDispatchParams; 1725cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface > xHoldRefForMethodAlive = aParams.m_xHoldRefForAsyncOpAlive; 1726cdf0e10cSrcweir m_aDispatchParams.forget(); // clears all members ... including the ref-hold object .-) 1727cdf0e10cSrcweir aWriteLock.unlock(); 1728cdf0e10cSrcweir // <- SAFE 1729cdf0e10cSrcweir 1730cdf0e10cSrcweir implts_dispatch(aParams); 1731cdf0e10cSrcweir return 0; 1732cdf0e10cSrcweir } 1733cdf0e10cSrcweir 1734cdf0e10cSrcweir //----------------------------------------------- 1735cdf0e10cSrcweir void AutoRecovery::implts_registerDocument(const css::uno::Reference< css::frame::XModel >& xDocument) 1736cdf0e10cSrcweir { 1737cdf0e10cSrcweir // ignore corrupted events, where no document is given ... Runtime Error ?! 1738cdf0e10cSrcweir if (!xDocument.is()) 1739cdf0e10cSrcweir return; 1740cdf0e10cSrcweir 1741cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 1742cdf0e10cSrcweir 1743cdf0e10cSrcweir // notification for already existing document ! 1744cdf0e10cSrcweir // Can happen if events came in asynchronous on recovery time. 1745cdf0e10cSrcweir // Then our cache was filled from the configuration ... but now we get some 1746cdf0e10cSrcweir // asynchronous events from the global event broadcaster. We must be sure that 1747cdf0e10cSrcweir // we dont add the same document more then once. 1748cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument); 1749cdf0e10cSrcweir if (pIt != m_lDocCache.end()) 1750cdf0e10cSrcweir { 1751e9faf1d9Smseidel // Normally nothing must be done for this "late" notification. 1752e9faf1d9Smseidel // But maybe the modified state was changed inbetween. 1753cdf0e10cSrcweir // Check it ... 1754cdf0e10cSrcweir implts_updateModifiedState(xDocument); 1755cdf0e10cSrcweir return; 1756cdf0e10cSrcweir } 1757cdf0e10cSrcweir 1758cdf0e10cSrcweir aCacheLock.unlock(); 1759cdf0e10cSrcweir 1760cdf0e10cSrcweir ::comphelper::MediaDescriptor lDescriptor(xDocument->getArgs()); 1761cdf0e10cSrcweir 1762cdf0e10cSrcweir // check if this document must be ignored for recovery ! 1763cdf0e10cSrcweir // Some use cases dont wish support for AutoSave/Recovery ... as e.g. OLE-Server / ActiveX Control etcpp. 1764cdf0e10cSrcweir sal_Bool bNoAutoSave = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_NOAUTOSAVE(), (sal_Bool)(sal_False)); 1765cdf0e10cSrcweir if (bNoAutoSave) 1766cdf0e10cSrcweir return; 1767cdf0e10cSrcweir 17684e7d57d8Smseidel // Check if doc is well known on the desktop. Otherwise ignore it! 1769cdf0e10cSrcweir // Other frames mostly are used from external programs - e.g. the bean ... 1770cdf0e10cSrcweir css::uno::Reference< css::frame::XController > xController = xDocument->getCurrentController(); 1771cdf0e10cSrcweir if (!xController.is()) 1772cdf0e10cSrcweir return; 1773cdf0e10cSrcweir 1774cdf0e10cSrcweir css::uno::Reference< css::frame::XFrame > xFrame = xController->getFrame(); 1775cdf0e10cSrcweir css::uno::Reference< css::frame::XDesktop > xDesktop (xFrame->getCreator(), css::uno::UNO_QUERY); 1776cdf0e10cSrcweir if (!xDesktop.is()) 1777cdf0e10cSrcweir return; 1778cdf0e10cSrcweir 1779cdf0e10cSrcweir // if the document doesn't support the XDocumentRecovery interface, we're not interested in it. 1780cdf0e10cSrcweir Reference< XDocumentRecovery > xDocRecovery( xDocument, UNO_QUERY ); 1781cdf0e10cSrcweir if ( !xDocRecovery.is() ) 1782cdf0e10cSrcweir return; 1783cdf0e10cSrcweir 1784cdf0e10cSrcweir // get all needed informations of this document 1785cdf0e10cSrcweir // We need it to update our cache or to locate already existing elements there! 1786cdf0e10cSrcweir AutoRecovery::TDocumentInfo aNew; 1787cdf0e10cSrcweir aNew.Document = xDocument; 1788cdf0e10cSrcweir 1789cdf0e10cSrcweir // TODO replace getLocation() with getURL() ... its a workaround currently only! 1790cdf0e10cSrcweir css::uno::Reference< css::frame::XStorable > xDoc(aNew.Document, css::uno::UNO_QUERY_THROW); 1791cdf0e10cSrcweir aNew.OrgURL = xDoc->getLocation(); 1792cdf0e10cSrcweir 1793cdf0e10cSrcweir css::uno::Reference< css::frame::XTitle > xTitle(aNew.Document, css::uno::UNO_QUERY_THROW); 1794cdf0e10cSrcweir aNew.Title = xTitle->getTitle (); 1795cdf0e10cSrcweir 1796cdf0e10cSrcweir // SAFE -> ---------------------------------- 1797cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 1798cdf0e10cSrcweir css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 1799cdf0e10cSrcweir aReadLock.unlock(); 1800cdf0e10cSrcweir // <- SAFE ---------------------------------- 1801cdf0e10cSrcweir 1802cdf0e10cSrcweir // classify the used application module, which is used by this document. 1803cdf0e10cSrcweir implts_specifyAppModuleAndFactory(aNew); 1804cdf0e10cSrcweir 1805cdf0e10cSrcweir // Hack! Check for "illegal office documents" ... as e.g. the Basic IDE 180607a3d7f1SPedro Giffuni // Its not really a full featured office document. It doesn't provide an URL, any filter, a factory URL etcpp. 1807cdf0e10cSrcweir // TODO file bug to Basci IDE developers. They must remove the office document API from its service. 1808cdf0e10cSrcweir if ( 1809cdf0e10cSrcweir (!aNew.OrgURL.getLength() ) && 1810cdf0e10cSrcweir (!aNew.FactoryURL.getLength()) 1811cdf0e10cSrcweir ) 1812cdf0e10cSrcweir { 1813cdf0e10cSrcweir OSL_ENSURE( false, "AutoRecovery::implts_registerDocument: this should not happen anymore!" ); 1814cdf0e10cSrcweir // nowadays, the Basic IDE should already die on the "supports XDocumentRecovery" check. And no other known 1815cdf0e10cSrcweir // document type fits in here ... 1816cdf0e10cSrcweir return; 1817cdf0e10cSrcweir } 1818cdf0e10cSrcweir 1819cdf0e10cSrcweir // By the way - get some information about the default format for saving! 1820cdf0e10cSrcweir // and save an information about the real used filter by this document. 1821cdf0e10cSrcweir // We save this document with DefaultFilter ... and load it with the RealFilter. 1822cdf0e10cSrcweir implts_specifyDefaultFilterAndExtension(aNew); 1823cdf0e10cSrcweir aNew.RealFilter = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME() , ::rtl::OUString()); 1824cdf0e10cSrcweir 1825cdf0e10cSrcweir // Further we must know, if this document base on a template. 1826cdf0e10cSrcweir // Then we must load it in a different way. 1827cdf0e10cSrcweir css::uno::Reference< css::document::XDocumentPropertiesSupplier > xSupplier(aNew.Document, css::uno::UNO_QUERY); 1828cdf0e10cSrcweir if (xSupplier.is()) // optional interface! 1829cdf0e10cSrcweir { 1830cdf0e10cSrcweir css::uno::Reference< css::document::XDocumentProperties > xDocProps(xSupplier->getDocumentProperties(), css::uno::UNO_QUERY_THROW); 1831cdf0e10cSrcweir aNew.TemplateURL = xDocProps->getTemplateURL(); 1832cdf0e10cSrcweir } 1833cdf0e10cSrcweir 1834cdf0e10cSrcweir css::uno::Reference< css::util::XModifiable > xModifyCheck(xDocument, css::uno::UNO_QUERY_THROW); 1835cdf0e10cSrcweir if (xModifyCheck->isModified()) 1836cdf0e10cSrcweir { 1837cdf0e10cSrcweir aNew.DocumentState |= AutoRecovery::E_MODIFIED; 1838cdf0e10cSrcweir } 1839cdf0e10cSrcweir 1840cdf0e10cSrcweir aCacheLock.lock(LOCK_FOR_CACHE_ADD_REMOVE); 1841cdf0e10cSrcweir 1842cdf0e10cSrcweir // SAFE -> ---------------------------------- 1843cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1844cdf0e10cSrcweir 1845cdf0e10cSrcweir // create a new cache entry ... this document isn't known. 1846cdf0e10cSrcweir ++m_nIdPool; 1847cdf0e10cSrcweir aNew.ID = m_nIdPool; 1848cdf0e10cSrcweir LOG_ASSERT(m_nIdPool>=0, "AutoRecovery::implts_registerDocument()\nOverflow of ID pool detected.") 1849cdf0e10cSrcweir m_lDocCache.push_back(aNew); 1850cdf0e10cSrcweir 1851cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt1 = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument); 1852cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo = *pIt1; 1853cdf0e10cSrcweir 1854cdf0e10cSrcweir aWriteLock.unlock(); 1855cdf0e10cSrcweir // <- SAFE ---------------------------------- 1856cdf0e10cSrcweir 1857cdf0e10cSrcweir implts_flushConfigItem(rInfo); 1858cdf0e10cSrcweir implts_startModifyListeningOnDoc(rInfo); 1859cdf0e10cSrcweir 1860cdf0e10cSrcweir aCacheLock.unlock(); 1861cdf0e10cSrcweir } 1862cdf0e10cSrcweir 1863cdf0e10cSrcweir //----------------------------------------------- 1864cdf0e10cSrcweir void AutoRecovery::implts_deregisterDocument(const css::uno::Reference< css::frame::XModel >& xDocument , 1865cdf0e10cSrcweir sal_Bool bStopListening) 1866cdf0e10cSrcweir { 1867cdf0e10cSrcweir 1868cdf0e10cSrcweir // SAFE -> ---------------------------------- 1869cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1870cdf0e10cSrcweir 1871cdf0e10cSrcweir // Attention: Dont leave SAFE section, if you work with pIt! 1872cdf0e10cSrcweir // Because it points directly into the m_lDocCache list ... 1873cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 1874cdf0e10cSrcweir 1875cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument); 1876cdf0e10cSrcweir if (pIt == m_lDocCache.end()) 1877cdf0e10cSrcweir return; // unknown document => not a runtime error! Because we register only a few documents. see registration ... 1878cdf0e10cSrcweir 1879cdf0e10cSrcweir AutoRecovery::TDocumentInfo aInfo = *pIt; 1880cdf0e10cSrcweir 1881cdf0e10cSrcweir aCacheLock.unlock(); 1882cdf0e10cSrcweir 1883cdf0e10cSrcweir // Sometimes we close documents by ourself. 188407a3d7f1SPedro Giffuni // And these documents can't be deregistered. 18854e7d57d8Smseidel // Otherwise we lose our configuration data ... but need it ! 1886cdf0e10cSrcweir // see SessionSave ! 1887cdf0e10cSrcweir if (aInfo.IgnoreClosing) 1888cdf0e10cSrcweir return; 1889cdf0e10cSrcweir 1890cdf0e10cSrcweir CacheLockGuard aCacheLock2(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_ADD_REMOVE); 1891cdf0e10cSrcweir pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument); 1892cdf0e10cSrcweir if (pIt != m_lDocCache.end()) 1893cdf0e10cSrcweir m_lDocCache.erase(pIt); 18944e7d57d8Smseidel pIt = m_lDocCache.end(); // otherwise it's not specified what pIt means! 1895cdf0e10cSrcweir aCacheLock2.unlock(); 1896cdf0e10cSrcweir 1897cdf0e10cSrcweir aWriteLock.unlock(); 1898cdf0e10cSrcweir // <- SAFE ---------------------------------- 1899cdf0e10cSrcweir 1900cdf0e10cSrcweir /* This method is called within disposing() of the document too. But there it's not a good idea to 19014e7d57d8Smseidel deregister us as listener. Further it makes no sense - because the broadcaster dies. 190207a3d7f1SPedro Giffuni So we suppress deregistration in such case ... 1903cdf0e10cSrcweir */ 1904cdf0e10cSrcweir if (bStopListening) 1905cdf0e10cSrcweir implts_stopModifyListeningOnDoc(aInfo); 1906cdf0e10cSrcweir 1907cdf0e10cSrcweir AutoRecovery::st_impl_removeFile(aInfo.OldTempURL); 1908cdf0e10cSrcweir AutoRecovery::st_impl_removeFile(aInfo.NewTempURL); 1909cdf0e10cSrcweir implts_flushConfigItem(aInfo, sal_True); // sal_True => remove it from config 1910cdf0e10cSrcweir } 1911cdf0e10cSrcweir 1912cdf0e10cSrcweir //----------------------------------------------- 1913cdf0e10cSrcweir void AutoRecovery::implts_markDocumentModifiedAgainstLastBackup(const css::uno::Reference< css::frame::XModel >& xDocument) 1914cdf0e10cSrcweir { 1915cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 1916cdf0e10cSrcweir 1917cdf0e10cSrcweir // SAFE -> ---------------------------------- 1918cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1919cdf0e10cSrcweir 1920cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument); 1921cdf0e10cSrcweir if (pIt != m_lDocCache.end()) 1922cdf0e10cSrcweir { 1923cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo = *pIt; 1924cdf0e10cSrcweir 1925cdf0e10cSrcweir /* Now we know, that this document was modified again and must be saved next time. 1926cdf0e10cSrcweir But we dont need this information for every e.g. key input of the user. 1927cdf0e10cSrcweir So we stop listening here. 1928cdf0e10cSrcweir But if the document was saved as temp. file we start listening for this event again. 1929cdf0e10cSrcweir */ 1930cdf0e10cSrcweir implts_stopModifyListeningOnDoc(rInfo); 1931cdf0e10cSrcweir } 1932cdf0e10cSrcweir 1933cdf0e10cSrcweir aWriteLock.unlock(); 1934cdf0e10cSrcweir // <- SAFE ---------------------------------- 1935cdf0e10cSrcweir } 1936cdf0e10cSrcweir 1937cdf0e10cSrcweir //----------------------------------------------- 1938cdf0e10cSrcweir void AutoRecovery::implts_updateModifiedState(const css::uno::Reference< css::frame::XModel >& xDocument) 1939cdf0e10cSrcweir { 1940cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 1941cdf0e10cSrcweir 1942cdf0e10cSrcweir // SAFE -> ---------------------------------- 1943cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1944cdf0e10cSrcweir 1945cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument); 1946cdf0e10cSrcweir if (pIt != m_lDocCache.end()) 1947cdf0e10cSrcweir { 1948cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo = *pIt; 1949cdf0e10cSrcweir 1950cdf0e10cSrcweir // use sal_True as fallback ... so we recognize every document on EmergencySave/AutoRecovery! 1951cdf0e10cSrcweir sal_Bool bModified = sal_True; 1952cdf0e10cSrcweir css::uno::Reference< css::util::XModifiable > xModify(xDocument, css::uno::UNO_QUERY); 1953cdf0e10cSrcweir if (xModify.is()) 1954cdf0e10cSrcweir bModified = xModify->isModified(); 1955cdf0e10cSrcweir if (bModified) 1956cdf0e10cSrcweir { 1957cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_MODIFIED; 1958cdf0e10cSrcweir } 1959cdf0e10cSrcweir else 1960cdf0e10cSrcweir { 1961cdf0e10cSrcweir rInfo.DocumentState &= ~AutoRecovery::E_MODIFIED; 1962cdf0e10cSrcweir } 1963cdf0e10cSrcweir } 1964cdf0e10cSrcweir 1965cdf0e10cSrcweir aWriteLock.unlock(); 1966cdf0e10cSrcweir // <- SAFE ---------------------------------- 1967cdf0e10cSrcweir } 1968cdf0e10cSrcweir 1969cdf0e10cSrcweir //----------------------------------------------- 1970cdf0e10cSrcweir void AutoRecovery::implts_updateDocumentUsedForSavingState(const css::uno::Reference< css::frame::XModel >& xDocument , 1971cdf0e10cSrcweir sal_Bool bSaveInProgress) 1972cdf0e10cSrcweir { 1973cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 1974cdf0e10cSrcweir 1975cdf0e10cSrcweir // SAFE -> ---------------------------------- 1976cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1977cdf0e10cSrcweir 1978cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument); 1979cdf0e10cSrcweir if (pIt == m_lDocCache.end()) 1980cdf0e10cSrcweir return; 1981cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo = *pIt; 1982cdf0e10cSrcweir rInfo.UsedForSaving = bSaveInProgress; 1983cdf0e10cSrcweir 1984cdf0e10cSrcweir aWriteLock.unlock(); 1985cdf0e10cSrcweir // <- SAFE ---------------------------------- 1986cdf0e10cSrcweir } 1987cdf0e10cSrcweir 1988cdf0e10cSrcweir //----------------------------------------------- 1989cdf0e10cSrcweir void AutoRecovery::implts_markDocumentAsSaved(const css::uno::Reference< css::frame::XModel >& xDocument) 1990cdf0e10cSrcweir { 1991cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 1992cdf0e10cSrcweir 1993cdf0e10cSrcweir // SAFE -> ---------------------------------- 1994cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 1995cdf0e10cSrcweir 1996cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt = AutoRecovery::impl_searchDocument(m_lDocCache, xDocument); 1997cdf0e10cSrcweir if (pIt == m_lDocCache.end()) 1998cdf0e10cSrcweir return; 1999cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo = *pIt; 2000cdf0e10cSrcweir 2001cdf0e10cSrcweir rInfo.DocumentState = AutoRecovery::E_UNKNOWN; 2002cdf0e10cSrcweir // TODO replace getLocation() with getURL() ... its a workaround currently only! 2003cdf0e10cSrcweir css::uno::Reference< css::frame::XStorable > xDoc(rInfo.Document, css::uno::UNO_QUERY); 2004cdf0e10cSrcweir rInfo.OrgURL = xDoc->getLocation(); 2005cdf0e10cSrcweir 2006cdf0e10cSrcweir ::rtl::OUString sRemoveURL1 = rInfo.OldTempURL; 2007cdf0e10cSrcweir ::rtl::OUString sRemoveURL2 = rInfo.NewTempURL; 2008cdf0e10cSrcweir rInfo.OldTempURL = ::rtl::OUString(); 2009cdf0e10cSrcweir rInfo.NewTempURL = ::rtl::OUString(); 2010cdf0e10cSrcweir 2011cdf0e10cSrcweir ::comphelper::MediaDescriptor lDescriptor(rInfo.Document->getArgs()); 2012cdf0e10cSrcweir rInfo.RealFilter = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME(), ::rtl::OUString()); 2013cdf0e10cSrcweir 2014cdf0e10cSrcweir css::uno::Reference< css::frame::XTitle > xDocTitle(xDocument, css::uno::UNO_QUERY); 2015cdf0e10cSrcweir if (xDocTitle.is ()) 2016cdf0e10cSrcweir rInfo.Title = xDocTitle->getTitle (); 2017cdf0e10cSrcweir else 2018cdf0e10cSrcweir { 2019cdf0e10cSrcweir rInfo.Title = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TITLE() , ::rtl::OUString()); 2020cdf0e10cSrcweir if (!rInfo.Title.getLength()) 2021cdf0e10cSrcweir rInfo.Title = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_DOCUMENTTITLE(), ::rtl::OUString()); 2022cdf0e10cSrcweir } 2023cdf0e10cSrcweir 2024cdf0e10cSrcweir rInfo.UsedForSaving = sal_False; 2025cdf0e10cSrcweir 2026cdf0e10cSrcweir aWriteLock.unlock(); 2027cdf0e10cSrcweir // <- SAFE ---------------------------------- 2028cdf0e10cSrcweir 2029cdf0e10cSrcweir implts_flushConfigItem(rInfo); 2030cdf0e10cSrcweir 2031cdf0e10cSrcweir aCacheLock.unlock(); 2032cdf0e10cSrcweir 2033cdf0e10cSrcweir AutoRecovery::st_impl_removeFile(sRemoveURL1); 2034cdf0e10cSrcweir AutoRecovery::st_impl_removeFile(sRemoveURL2); 2035cdf0e10cSrcweir } 2036cdf0e10cSrcweir 2037cdf0e10cSrcweir //----------------------------------------------- 2038cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator AutoRecovery::impl_searchDocument( AutoRecovery::TDocumentList& rList , 2039cdf0e10cSrcweir const css::uno::Reference< css::frame::XModel >& xDocument) 2040cdf0e10cSrcweir { 2041cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt; 2042cdf0e10cSrcweir for ( pIt = rList.begin(); 2043cdf0e10cSrcweir pIt != rList.end() ; 2044cdf0e10cSrcweir ++pIt ) 2045cdf0e10cSrcweir { 2046cdf0e10cSrcweir const AutoRecovery::TDocumentInfo& rInfo = *pIt; 2047cdf0e10cSrcweir if (rInfo.Document == xDocument) 2048cdf0e10cSrcweir break; 2049cdf0e10cSrcweir } 2050cdf0e10cSrcweir return pIt; 2051cdf0e10cSrcweir } 2052cdf0e10cSrcweir 2053cdf0e10cSrcweir //----------------------------------------------- 2054cdf0e10cSrcweir namespace 2055cdf0e10cSrcweir { 2056cdf0e10cSrcweir void lcl_changeVisibility( const css::uno::Reference< css::frame::XFramesSupplier >& i_rFrames, sal_Bool i_bVisible ) 2057cdf0e10cSrcweir { 2058cdf0e10cSrcweir css::uno::Reference< css::container::XIndexAccess > xFramesContainer( i_rFrames->getFrames(), css::uno::UNO_QUERY ); 2059cdf0e10cSrcweir const sal_Int32 count = xFramesContainer->getCount(); 2060cdf0e10cSrcweir 2061cdf0e10cSrcweir Any aElement; 2062cdf0e10cSrcweir for ( sal_Int32 i=0; i < count; ++i ) 2063cdf0e10cSrcweir { 2064cdf0e10cSrcweir aElement = xFramesContainer->getByIndex(i); 2065cdf0e10cSrcweir // check for sub frames 2066cdf0e10cSrcweir css::uno::Reference< css::frame::XFramesSupplier > xFramesSupp( aElement, css::uno::UNO_QUERY ); 2067cdf0e10cSrcweir if ( xFramesSupp.is() ) 2068cdf0e10cSrcweir lcl_changeVisibility( xFramesSupp, i_bVisible ); 2069cdf0e10cSrcweir 2070cdf0e10cSrcweir css::uno::Reference< css::frame::XFrame > xFrame( aElement, css::uno::UNO_QUERY ); 2071cdf0e10cSrcweir if ( !xFrame.is() ) 2072cdf0e10cSrcweir continue; 2073cdf0e10cSrcweir 2074cdf0e10cSrcweir css::uno::Reference< css::awt::XWindow > xWindow( xFrame->getContainerWindow(), UNO_SET_THROW ); 2075cdf0e10cSrcweir xWindow->setVisible( i_bVisible ); 2076cdf0e10cSrcweir } 2077cdf0e10cSrcweir } 2078cdf0e10cSrcweir } 2079cdf0e10cSrcweir 2080cdf0e10cSrcweir //----------------------------------------------- 2081cdf0e10cSrcweir void AutoRecovery::implts_changeAllDocVisibility(sal_Bool bVisible) 2082cdf0e10cSrcweir { 2083cdf0e10cSrcweir // SAFE -> ---------------------------------- 2084cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 2085cdf0e10cSrcweir css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 2086cdf0e10cSrcweir aReadLock.unlock(); 2087cdf0e10cSrcweir // <- SAFE ---------------------------------- 2088cdf0e10cSrcweir 2089cdf0e10cSrcweir css::uno::Reference< css::frame::XFramesSupplier > xDesktop(xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY); 2090cdf0e10cSrcweir lcl_changeVisibility( xDesktop, bVisible ); 2091cdf0e10cSrcweir 2092cdf0e10cSrcweir aReadLock.unlock(); 2093cdf0e10cSrcweir // <- SAFE ---------------------------------- 2094cdf0e10cSrcweir } 2095cdf0e10cSrcweir 2096cdf0e10cSrcweir //----------------------------------------------- 2097cdf0e10cSrcweir /* Currently the document is not closed in case of crash, 2098cdf0e10cSrcweir so the lock file must be removed explicitly 2099cdf0e10cSrcweir */ 2100cdf0e10cSrcweir void lc_removeLockFile(AutoRecovery::TDocumentInfo& rInfo) 2101cdf0e10cSrcweir { 2102cdf0e10cSrcweir if ( rInfo.Document.is() ) 2103cdf0e10cSrcweir { 2104cdf0e10cSrcweir try 2105cdf0e10cSrcweir { 2106cdf0e10cSrcweir css::uno::Reference< css::frame::XStorable > xStore(rInfo.Document, css::uno::UNO_QUERY_THROW); 2107cdf0e10cSrcweir ::rtl::OUString aURL = xStore->getLocation(); 2108cdf0e10cSrcweir if ( aURL.getLength() ) 2109cdf0e10cSrcweir { 2110cdf0e10cSrcweir ::svt::DocumentLockFile aLockFile( aURL ); 2111cdf0e10cSrcweir aLockFile.RemoveFile(); 2112cdf0e10cSrcweir } 2113cdf0e10cSrcweir } 2114cdf0e10cSrcweir catch( const css::uno::Exception& ) 2115cdf0e10cSrcweir {} 2116cdf0e10cSrcweir } 2117cdf0e10cSrcweir } 2118cdf0e10cSrcweir 2119cdf0e10cSrcweir 2120cdf0e10cSrcweir //----------------------------------------------- 2121cdf0e10cSrcweir void AutoRecovery::implts_prepareSessionShutdown() 2122cdf0e10cSrcweir { 2123cdf0e10cSrcweir LOG_RECOVERY("AutoRecovery::implts_prepareSessionShutdown() starts ...") 2124cdf0e10cSrcweir 2125cdf0e10cSrcweir // a) reset modified documents (of course the must be saved before this method is called!) 2126cdf0e10cSrcweir // b) close it without showing any UI! 2127cdf0e10cSrcweir 2128cdf0e10cSrcweir // SAFE -> 2129cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 2130cdf0e10cSrcweir 2131cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt; 2132cdf0e10cSrcweir for ( pIt = m_lDocCache.begin(); 2133cdf0e10cSrcweir pIt != m_lDocCache.end() ; 2134cdf0e10cSrcweir ++pIt ) 2135cdf0e10cSrcweir { 2136cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo = *pIt; 2137cdf0e10cSrcweir 2138cdf0e10cSrcweir // WORKAROUND... Since the documents are not closed the lock file must be removed explicitly 2139cdf0e10cSrcweir // it is not done on documents saving since shutdown can be cancelled 2140cdf0e10cSrcweir lc_removeLockFile( rInfo ); 2141cdf0e10cSrcweir 2142cdf0e10cSrcweir // Prevent us from deregistration of these documents. 2143cdf0e10cSrcweir // Because we close these documents by ourself (see XClosable below) ... 2144cdf0e10cSrcweir // it's fact, that we reach our deregistration method. There we 21454e7d57d8Smseidel // must not(!) update our configuration ... Otherwise all 2146cdf0e10cSrcweir // session data are lost !!! 2147cdf0e10cSrcweir rInfo.IgnoreClosing = sal_True; 2148cdf0e10cSrcweir 2149cdf0e10cSrcweir // reset modified flag of these documents (ignoring the notification about it!) 2150cdf0e10cSrcweir // Otherwise a message box is shown on closing these models. 2151cdf0e10cSrcweir implts_stopModifyListeningOnDoc(rInfo); 2152cdf0e10cSrcweir 2153cdf0e10cSrcweir // if the session save is still running the documents should not be thrown away, 2154cdf0e10cSrcweir // actually that would be a bad sign, that means that the SessionManager tryes 2155cdf0e10cSrcweir // to kill the session before the saving is ready 2156cdf0e10cSrcweir if ((m_eJob & AutoRecovery::E_SESSION_SAVE) != AutoRecovery::E_SESSION_SAVE) 2157cdf0e10cSrcweir { 2158cdf0e10cSrcweir css::uno::Reference< css::util::XModifiable > xModify(rInfo.Document, css::uno::UNO_QUERY); 2159cdf0e10cSrcweir if (xModify.is()) 2160cdf0e10cSrcweir xModify->setModified(sal_False); 2161cdf0e10cSrcweir 2162cdf0e10cSrcweir // close the model. 2163cdf0e10cSrcweir css::uno::Reference< css::util::XCloseable > xClose(rInfo.Document, css::uno::UNO_QUERY); 2164cdf0e10cSrcweir if (xClose.is()) 2165cdf0e10cSrcweir { 2166cdf0e10cSrcweir try 2167cdf0e10cSrcweir { 2168cdf0e10cSrcweir xClose->close(sal_False); 2169cdf0e10cSrcweir } 2170cdf0e10cSrcweir /* 2171cdf0e10cSrcweir catch(const css::lang::DisposedException&) 2172cdf0e10cSrcweir { 2173cdf0e10cSrcweir // closed ... disposed ... always the same .-) 2174cdf0e10cSrcweir } 2175cdf0e10cSrcweir */ 2176cdf0e10cSrcweir catch(const css::uno::Exception&) 2177cdf0e10cSrcweir { 2178cdf0e10cSrcweir // At least it's only a try to close these documents before anybody else it does. 2179796b7e2aSmseidel // So it seems to be possible to ignore any error here .-) 2180cdf0e10cSrcweir } 2181cdf0e10cSrcweir 2182cdf0e10cSrcweir rInfo.Document.clear(); 2183cdf0e10cSrcweir } 2184cdf0e10cSrcweir } 2185cdf0e10cSrcweir } 2186cdf0e10cSrcweir 2187cdf0e10cSrcweir aCacheLock.unlock(); 2188cdf0e10cSrcweir // <- SAFE 2189cdf0e10cSrcweir } 2190cdf0e10cSrcweir 2191cdf0e10cSrcweir //----------------------------------------------- 2192cdf0e10cSrcweir /* TODO WORKAROUND: 2193cdf0e10cSrcweir 2194cdf0e10cSrcweir #i64599# 2195cdf0e10cSrcweir 2196e9faf1d9Smseidel Normally the MediaDescriptor argument NoAutoSave indicates, 2197cdf0e10cSrcweir that a document must be ignored for AutoSave and Recovery. 2198cdf0e10cSrcweir But sometimes XModel->getArgs() does not contained this information 2199cdf0e10cSrcweir if implts_registerDocument() was called. 2200cdf0e10cSrcweir So we have to check a second time, if this property is set .... 2201cdf0e10cSrcweir Best place doing so is to check it immeditaly before saving 2202cdf0e10cSrcweir and supressingd saving the document then. 220307a3d7f1SPedro Giffuni Of course removing the corresponding cache entry isn't an option. 2204cdf0e10cSrcweir Because it would disturb iteration over the cache ! 2205cdf0e10cSrcweir So we ignore such documents only ... 2206cdf0e10cSrcweir Hopefully next time they are not inserted in our cache. 2207cdf0e10cSrcweir */ 2208cdf0e10cSrcweir sal_Bool lc_checkIfSaveForbiddenByArguments(AutoRecovery::TDocumentInfo& rInfo) 2209cdf0e10cSrcweir { 2210cdf0e10cSrcweir if (! rInfo.Document.is()) 2211cdf0e10cSrcweir return sal_True; 2212cdf0e10cSrcweir 2213cdf0e10cSrcweir ::comphelper::MediaDescriptor lDescriptor(rInfo.Document->getArgs()); 2214cdf0e10cSrcweir sal_Bool bNoAutoSave = lDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_NOAUTOSAVE(), (sal_Bool)(sal_False)); 2215cdf0e10cSrcweir 2216cdf0e10cSrcweir return bNoAutoSave; 2217cdf0e10cSrcweir } 2218cdf0e10cSrcweir 2219cdf0e10cSrcweir //----------------------------------------------- 2220cdf0e10cSrcweir AutoRecovery::ETimerType AutoRecovery::implts_saveDocs( sal_Bool bAllowUserIdleLoop, 2221cdf0e10cSrcweir sal_Bool bRemoveLockFiles, 2222cdf0e10cSrcweir const DispatchParams* pParams ) 2223cdf0e10cSrcweir { 2224cdf0e10cSrcweir // SAFE -> ---------------------------------- 2225cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 2226cdf0e10cSrcweir css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 2227cdf0e10cSrcweir aReadLock.unlock(); 2228cdf0e10cSrcweir // <- SAFE ---------------------------------- 2229cdf0e10cSrcweir 2230cdf0e10cSrcweir css::uno::Reference< css::task::XStatusIndicator > xExternalProgress; 2231cdf0e10cSrcweir if (pParams) 2232cdf0e10cSrcweir xExternalProgress = pParams->m_xProgress; 2233cdf0e10cSrcweir 2234cdf0e10cSrcweir css::uno::Reference< css::frame::XFramesSupplier > xDesktop (xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY); 2235cdf0e10cSrcweir ::rtl::OUString sBackupPath (SvtPathOptions().GetBackupPath()); 2236cdf0e10cSrcweir 2237cdf0e10cSrcweir css::uno::Reference< css::frame::XController > xActiveController; 2238cdf0e10cSrcweir css::uno::Reference< css::frame::XModel > xActiveModel ; 2239cdf0e10cSrcweir css::uno::Reference< css::frame::XFrame > xActiveFrame = xDesktop->getActiveFrame(); 2240cdf0e10cSrcweir if (xActiveFrame.is()) 2241cdf0e10cSrcweir xActiveController = xActiveFrame->getController(); 2242cdf0e10cSrcweir if (xActiveController.is()) 2243cdf0e10cSrcweir xActiveModel = xActiveController->getModel(); 2244cdf0e10cSrcweir 2245cdf0e10cSrcweir // Set the default timer action for our calli. 2246cdf0e10cSrcweir // Default = NORMAL_AUTOSAVE 2247cdf0e10cSrcweir // We return a suggestion for an active timer only. 2248cdf0e10cSrcweir // It will be ignored if the timer was disabled by the user ... 2249cdf0e10cSrcweir // Further this state can be set to USER_IDLE only later in this method. 2250cdf0e10cSrcweir // Its not allowed to reset such state then. Because we must know, if 2251cdf0e10cSrcweir // there exists POSTPONED documents. see below ... 2252cdf0e10cSrcweir AutoRecovery::ETimerType eTimer = AutoRecovery::E_NORMAL_AUTOSAVE_INTERVALL; 2253cdf0e10cSrcweir 2254cdf0e10cSrcweir sal_Int32 eJob = m_eJob; 2255cdf0e10cSrcweir 2256cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 2257cdf0e10cSrcweir 2258cdf0e10cSrcweir // SAFE -> ---------------------------------- 2259cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 2260cdf0e10cSrcweir 2261cdf0e10cSrcweir // This list will be filled with every document 2262cdf0e10cSrcweir // which should be saved as last one. E.g. if it was used 2263cdf0e10cSrcweir // already for an UI save operation => crashed ... and 2264cdf0e10cSrcweir // now we try to save it again ... which can fail again ( of course .-) ). 2265cdf0e10cSrcweir ::std::vector< AutoRecovery::TDocumentList::iterator > lDangerousDocs; 2266cdf0e10cSrcweir 2267cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt; 2268cdf0e10cSrcweir for ( pIt = m_lDocCache.begin(); 2269cdf0e10cSrcweir pIt != m_lDocCache.end() ; 2270cdf0e10cSrcweir ++pIt ) 2271cdf0e10cSrcweir { 2272cdf0e10cSrcweir AutoRecovery::TDocumentInfo aInfo = *pIt; 2273cdf0e10cSrcweir 2274cdf0e10cSrcweir // WORKAROUND... Since the documents are not closed the lock file must be removed explicitly 2275cdf0e10cSrcweir if ( bRemoveLockFiles ) 2276cdf0e10cSrcweir lc_removeLockFile( aInfo ); 2277cdf0e10cSrcweir 2278cdf0e10cSrcweir // WORKAROUND ... see comment of this method 2279cdf0e10cSrcweir if (lc_checkIfSaveForbiddenByArguments(aInfo)) 2280cdf0e10cSrcweir continue; 2281cdf0e10cSrcweir 2282cdf0e10cSrcweir // already auto saved during this session :-) 2283cdf0e10cSrcweir // This state must be reset for all documents 2284cdf0e10cSrcweir // if timer is started with normnal AutoSaveTimerIntervall! 2285cdf0e10cSrcweir if ((aInfo.DocumentState & AutoRecovery::E_HANDLED) == AutoRecovery::E_HANDLED) 2286cdf0e10cSrcweir continue; 2287cdf0e10cSrcweir 2288cdf0e10cSrcweir // Not modified documents are not saved. 2289cdf0e10cSrcweir // We safe an information about the URL only! 2290cdf0e10cSrcweir Reference< XDocumentRecovery > xDocRecover( aInfo.Document, UNO_QUERY_THROW ); 2291cdf0e10cSrcweir if ( !xDocRecover->wasModifiedSinceLastSave() ) 2292cdf0e10cSrcweir { 2293cdf0e10cSrcweir aInfo.DocumentState |= AutoRecovery::E_HANDLED; 2294cdf0e10cSrcweir continue; 2295cdf0e10cSrcweir } 2296cdf0e10cSrcweir 2297cdf0e10cSrcweir // check if this document is still used by a concurrent save operation 2298cdf0e10cSrcweir // e.g. if the user tried to save via UI. 2299cdf0e10cSrcweir // Handle it in the following way: 2300cdf0e10cSrcweir // i) For an AutoSave ... ignore this document! It will be saved and next time we will (hopefully) 2301cdf0e10cSrcweir // get a notification about the state of this operation. 2302cdf0e10cSrcweir // And if a document was saved by the user we can remove our temp. file. But that will be done inside 2303cdf0e10cSrcweir // our callback for SaveDone notification. 2304cdf0e10cSrcweir // ii) For a CrashSave ... add it to the list of dangerous documents and 2305cdf0e10cSrcweir // save it after all other documents was saved successfully. That decrease 2306cdf0e10cSrcweir // the chance for a crash inside a crash. 230707a3d7f1SPedro Giffuni // On the other side it's not necessary for documents, which are not modified. 2308e9faf1d9Smseidel // They can be handled normally - means we patch the corresponding configuration entry only. 2309cdf0e10cSrcweir // iii) For a SessionSave ... ignore it! There is no time to wait for this save operation. 231007a3d7f1SPedro Giffuni // Because the WindowManager will kill the process if it doesn't react immediately. 231107a3d7f1SPedro Giffuni // On the other side we can't risk a concurrent save request ... because we know 2312cdf0e10cSrcweir // that it will produce a crash. 2313cdf0e10cSrcweir 2314cdf0e10cSrcweir // Attention: Because eJob is used as a flag field, you have to check for the worst case first. 2315cdf0e10cSrcweir // E.g. a CrashSave can overwrite an AutoSave. So you have to check for a CrashSave before an AutoSave! 2316cdf0e10cSrcweir if (aInfo.UsedForSaving) 2317cdf0e10cSrcweir { 2318cdf0e10cSrcweir if ((eJob & AutoRecovery::E_EMERGENCY_SAVE) == AutoRecovery::E_EMERGENCY_SAVE) 2319cdf0e10cSrcweir { 2320cdf0e10cSrcweir lDangerousDocs.push_back(pIt); 2321cdf0e10cSrcweir continue; 2322cdf0e10cSrcweir } 2323cdf0e10cSrcweir else 2324cdf0e10cSrcweir if ((eJob & AutoRecovery::E_SESSION_SAVE) == AutoRecovery::E_SESSION_SAVE) 2325cdf0e10cSrcweir { 2326cdf0e10cSrcweir continue; 2327cdf0e10cSrcweir } 2328cdf0e10cSrcweir else 2329cdf0e10cSrcweir if ((eJob & AutoRecovery::E_AUTO_SAVE) == AutoRecovery::E_AUTO_SAVE) 2330cdf0e10cSrcweir { 2331cdf0e10cSrcweir eTimer = AutoRecovery::E_POLL_TILL_AUTOSAVE_IS_ALLOWED; 2332cdf0e10cSrcweir aInfo.DocumentState |= AutoRecovery::E_POSTPONED; 2333cdf0e10cSrcweir continue; 2334cdf0e10cSrcweir } 2335cdf0e10cSrcweir } 2336cdf0e10cSrcweir 2337cdf0e10cSrcweir // a) Document was not postponed - and is active now. => postpone it (restart timer, restart loop) 2338cdf0e10cSrcweir // b) Document was not postponed - and is not active now. => save it 2339cdf0e10cSrcweir // c) Document was postponed - and is not active now. => save it 2340cdf0e10cSrcweir // d) Document was postponed - and is active now. => save it (because user idle was checked already) 2341cdf0e10cSrcweir sal_Bool bActive = (xActiveModel == aInfo.Document); 2342cdf0e10cSrcweir sal_Bool bWasPostponed = ((aInfo.DocumentState & AutoRecovery::E_POSTPONED) == AutoRecovery::E_POSTPONED); 2343cdf0e10cSrcweir 2344cdf0e10cSrcweir if ( 2345cdf0e10cSrcweir ! bWasPostponed && 2346cdf0e10cSrcweir bActive 2347cdf0e10cSrcweir ) 2348cdf0e10cSrcweir { 2349cdf0e10cSrcweir aInfo.DocumentState |= AutoRecovery::E_POSTPONED; 2350cdf0e10cSrcweir *pIt = aInfo; 2351cdf0e10cSrcweir // postponed documents will be saved if this method is called again! 2352cdf0e10cSrcweir // That can be done by an outside started timer => E_POLL_FOR_USER_IDLE (if normal AutoSave is active) 2353cdf0e10cSrcweir // or it must be done directly without starting any timer => E_CALL_ME_BACK (if Emergency- or SessionSave is active and must be finished ASAP!) 2354cdf0e10cSrcweir eTimer = AutoRecovery::E_POLL_FOR_USER_IDLE; 2355cdf0e10cSrcweir if (!bAllowUserIdleLoop) 2356cdf0e10cSrcweir eTimer = AutoRecovery::E_CALL_ME_BACK; 2357cdf0e10cSrcweir continue; 2358cdf0e10cSrcweir } 2359cdf0e10cSrcweir 2360cdf0e10cSrcweir // b, c, d) 2361cdf0e10cSrcweir // <- SAFE -------------------------- 2362cdf0e10cSrcweir aWriteLock.unlock(); 2363cdf0e10cSrcweir // changing of aInfo and flushing it is done inside implts_saveOneDoc! 2364cdf0e10cSrcweir implts_saveOneDoc(sBackupPath, aInfo, xExternalProgress); 2365cdf0e10cSrcweir implts_informListener(eJob, AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &aInfo)); 2366cdf0e10cSrcweir aWriteLock.lock(); 2367cdf0e10cSrcweir // SAFE -> -------------------------- 2368cdf0e10cSrcweir 2369cdf0e10cSrcweir *pIt = aInfo; 2370cdf0e10cSrcweir } 2371cdf0e10cSrcweir 2372cdf0e10cSrcweir // Did we have some "dangerous candidates" ? 2373cdf0e10cSrcweir // Try to save it ... but may be it will fail ! 2374cdf0e10cSrcweir ::std::vector< AutoRecovery::TDocumentList::iterator >::iterator pIt2; 2375cdf0e10cSrcweir for ( pIt2 = lDangerousDocs.begin(); 2376cdf0e10cSrcweir pIt2 != lDangerousDocs.end() ; 2377cdf0e10cSrcweir ++pIt2 ) 2378cdf0e10cSrcweir { 2379cdf0e10cSrcweir pIt = *pIt2; 2380cdf0e10cSrcweir AutoRecovery::TDocumentInfo aInfo = *pIt; 2381cdf0e10cSrcweir 2382cdf0e10cSrcweir // <- SAFE -------------------------- 2383cdf0e10cSrcweir aWriteLock.unlock(); 2384cdf0e10cSrcweir // changing of aInfo and flushing it is done inside implts_saveOneDoc! 2385cdf0e10cSrcweir implts_saveOneDoc(sBackupPath, aInfo, xExternalProgress); 2386cdf0e10cSrcweir implts_informListener(eJob, AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &aInfo)); 2387cdf0e10cSrcweir aWriteLock.lock(); 2388cdf0e10cSrcweir // SAFE -> -------------------------- 2389cdf0e10cSrcweir 2390cdf0e10cSrcweir *pIt = aInfo; 2391cdf0e10cSrcweir } 2392cdf0e10cSrcweir 2393cdf0e10cSrcweir return eTimer; 2394cdf0e10cSrcweir } 2395cdf0e10cSrcweir 2396cdf0e10cSrcweir //----------------------------------------------- 2397cdf0e10cSrcweir void AutoRecovery::implts_saveOneDoc(const ::rtl::OUString& sBackupPath , 2398cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo , 2399cdf0e10cSrcweir const css::uno::Reference< css::task::XStatusIndicator >& xExternalProgress) 2400cdf0e10cSrcweir { 240130acf5e8Spfg // no document? => can occur if we loaded our configuration with files, 2402*7a164331Smseidel // which couldn't be recovered successfully. In such case we have all needed informations 2403*7a164331Smseidel // except the real document instance! 2404cdf0e10cSrcweir 2405cdf0e10cSrcweir // TODO: search right place, where such "dead files" can be removed from the configuration! 2406cdf0e10cSrcweir if (!rInfo.Document.is()) 2407cdf0e10cSrcweir return; 2408cdf0e10cSrcweir 2409cdf0e10cSrcweir ::comphelper::MediaDescriptor lOldArgs(rInfo.Document->getArgs()); 2410cdf0e10cSrcweir implts_generateNewTempURL(sBackupPath, lOldArgs, rInfo); 2411cdf0e10cSrcweir 2412cdf0e10cSrcweir // if the document was loaded with a password, it should be 2413cdf0e10cSrcweir // stored with password 2414cdf0e10cSrcweir ::comphelper::MediaDescriptor lNewArgs; 2415cdf0e10cSrcweir ::rtl::OUString sPassword = lOldArgs.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_PASSWORD(), ::rtl::OUString()); 2416cdf0e10cSrcweir if (sPassword.getLength()) 2417cdf0e10cSrcweir lNewArgs[::comphelper::MediaDescriptor::PROP_PASSWORD()] <<= sPassword; 2418cdf0e10cSrcweir 2419cdf0e10cSrcweir // Further it must be saved using the default file format of that application. 24204e7d57d8Smseidel // Otherwise we will lose some data. 2421cdf0e10cSrcweir if (rInfo.DefaultFilter.getLength()) 2422cdf0e10cSrcweir lNewArgs[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= rInfo.DefaultFilter; 2423cdf0e10cSrcweir 2424cdf0e10cSrcweir // prepare frame/document/mediadescriptor in a way, that it uses OUR progress .-) 2425cdf0e10cSrcweir if (xExternalProgress.is()) 2426cdf0e10cSrcweir lNewArgs[::comphelper::MediaDescriptor::PROP_STATUSINDICATOR()] <<= xExternalProgress; 2427cdf0e10cSrcweir impl_establishProgress(rInfo, lNewArgs, css::uno::Reference< css::frame::XFrame >()); 2428cdf0e10cSrcweir 2429cdf0e10cSrcweir // #i66598# use special handling of property "DocumentBaseURL" (it must be an empty string!) 2430cdf0e10cSrcweir // for make hyperlinks working 2431cdf0e10cSrcweir lNewArgs[::comphelper::MediaDescriptor::PROP_DOCUMENTBASEURL()] <<= ::rtl::OUString(); 2432cdf0e10cSrcweir 2433cdf0e10cSrcweir // try to save this document as a new temp file everytimes. 2434cdf0e10cSrcweir // Mark AutoSave state as "INCOMPLETE" if it failed. 2435cdf0e10cSrcweir // Because the last temp file is to old and does not include all changes. 2436cdf0e10cSrcweir Reference< XDocumentRecovery > xDocRecover(rInfo.Document, css::uno::UNO_QUERY_THROW); 2437cdf0e10cSrcweir 2438cdf0e10cSrcweir // safe the state about "trying to save" 243930acf5e8Spfg // ... we need it for recovery if e.g. a crash occurs inside next line! 2440cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_TRY_SAVE; 2441cdf0e10cSrcweir implts_flushConfigItem(rInfo); 2442cdf0e10cSrcweir 2443cdf0e10cSrcweir sal_Int32 nRetry = RETRY_STORE_ON_FULL_DISC_FOREVER; 2444cdf0e10cSrcweir sal_Bool bError = sal_False; 2445cdf0e10cSrcweir do 2446cdf0e10cSrcweir { 2447cdf0e10cSrcweir try 2448cdf0e10cSrcweir { 2449cdf0e10cSrcweir xDocRecover->storeToRecoveryFile( rInfo.NewTempURL, lNewArgs.getAsConstPropertyValueList() ); 2450cdf0e10cSrcweir 2451cdf0e10cSrcweir #ifdef TRIGGER_FULL_DISC_CHECK 2452cdf0e10cSrcweir throw css::uno::Exception(); 2453cdf0e10cSrcweir #endif 2454cdf0e10cSrcweir 2455cdf0e10cSrcweir bError = sal_False; 2456cdf0e10cSrcweir nRetry = 0; 2457cdf0e10cSrcweir } 2458cdf0e10cSrcweir catch(const css::uno::Exception& ex) 2459cdf0e10cSrcweir { 2460cdf0e10cSrcweir bError = sal_True; 2461cdf0e10cSrcweir 2462796b7e2aSmseidel // a) FULL DISC seems to be the problem behind => show error and retry it forever (e.g. retry=300) 246307a3d7f1SPedro Giffuni // b) unknown problem (may be locking problem) => reset RETRY value to more useful value(!) (e.g. retry=3) 2464cdf0e10cSrcweir // c) unknown problem (may be locking problem) + 1..2 repeating operations => throw the original exception to force generation of a stacktrace ! 2465cdf0e10cSrcweir 2466cdf0e10cSrcweir // SAFE -> 2467cdf0e10cSrcweir ReadGuard aReadLock2(m_aLock); 2468cdf0e10cSrcweir sal_Int32 nMinSpaceDocSave = m_nMinSpaceDocSave; 2469cdf0e10cSrcweir aReadLock2.unlock(); 2470cdf0e10cSrcweir // <- SAFE 2471cdf0e10cSrcweir 2472cdf0e10cSrcweir if (! impl_enoughDiscSpace(nMinSpaceDocSave)) 2473cdf0e10cSrcweir AutoRecovery::impl_showFullDiscError(); 2474cdf0e10cSrcweir else 2475cdf0e10cSrcweir if (nRetry > RETRY_STORE_ON_MIGHT_FULL_DISC_USEFULL) 2476cdf0e10cSrcweir nRetry = RETRY_STORE_ON_MIGHT_FULL_DISC_USEFULL; 2477cdf0e10cSrcweir else 2478cdf0e10cSrcweir if (nRetry <= GIVE_UP_RETRY) 2479cdf0e10cSrcweir throw ex; // force stacktrace to know if there exist might other reasons, why an AutoSave can fail !!! 2480cdf0e10cSrcweir 2481cdf0e10cSrcweir --nRetry; 2482cdf0e10cSrcweir } 2483cdf0e10cSrcweir } 2484cdf0e10cSrcweir while(nRetry>0); 2485cdf0e10cSrcweir 2486cdf0e10cSrcweir if (! bError) 2487cdf0e10cSrcweir { 2488cdf0e10cSrcweir // safe the state about success 2489cdf0e10cSrcweir // ... you know the reason: to know it on recovery time if next line crash .-) 2490cdf0e10cSrcweir rInfo.DocumentState &= ~AutoRecovery::E_TRY_SAVE; 2491cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_HANDLED; 2492cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_SUCCEDED; 2493cdf0e10cSrcweir } 2494cdf0e10cSrcweir else 2495cdf0e10cSrcweir { 2496cdf0e10cSrcweir // safe the state about error ... 2497cdf0e10cSrcweir rInfo.NewTempURL = ::rtl::OUString(); 2498cdf0e10cSrcweir rInfo.DocumentState &= ~AutoRecovery::E_TRY_SAVE; 2499cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_HANDLED; 2500cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_INCOMPLETE; 2501cdf0e10cSrcweir } 2502cdf0e10cSrcweir 250307a3d7f1SPedro Giffuni // make sure the progress isn't referred any longer 2504cdf0e10cSrcweir impl_forgetProgress(rInfo, lNewArgs, css::uno::Reference< css::frame::XFrame >()); 2505cdf0e10cSrcweir 2506cdf0e10cSrcweir // try to remove the old temp file. 2507cdf0e10cSrcweir // Ignore any error here. We have a new temp file, which is up to date. 250807a3d7f1SPedro Giffuni // The only thing is: we fill the disk with temp files, if we can't remove old ones :-) 2509cdf0e10cSrcweir ::rtl::OUString sRemoveFile = rInfo.OldTempURL; 2510cdf0e10cSrcweir rInfo.OldTempURL = rInfo.NewTempURL; 2511cdf0e10cSrcweir rInfo.NewTempURL = ::rtl::OUString(); 2512cdf0e10cSrcweir 2513cdf0e10cSrcweir implts_flushConfigItem(rInfo); 2514cdf0e10cSrcweir 2515cdf0e10cSrcweir // We must know if the user modifies the document again ... 2516cdf0e10cSrcweir implts_startModifyListeningOnDoc(rInfo); 2517cdf0e10cSrcweir 2518cdf0e10cSrcweir AutoRecovery::st_impl_removeFile(sRemoveFile); 2519cdf0e10cSrcweir } 2520cdf0e10cSrcweir 2521cdf0e10cSrcweir //----------------------------------------------- 2522cdf0e10cSrcweir AutoRecovery::ETimerType AutoRecovery::implts_openDocs(const DispatchParams& aParams) 2523cdf0e10cSrcweir { 2524cdf0e10cSrcweir AutoRecovery::ETimerType eTimer = AutoRecovery::E_DONT_START_TIMER; 2525cdf0e10cSrcweir 2526cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 2527cdf0e10cSrcweir 2528cdf0e10cSrcweir // SAFE -> ---------------------------------- 2529cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 2530cdf0e10cSrcweir 2531cdf0e10cSrcweir sal_Int32 eJob = m_eJob; 2532cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt; 2533cdf0e10cSrcweir for ( pIt = m_lDocCache.begin(); 2534cdf0e10cSrcweir pIt != m_lDocCache.end() ; 2535cdf0e10cSrcweir ++pIt ) 2536cdf0e10cSrcweir { 2537cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo = *pIt; 2538cdf0e10cSrcweir 2539cdf0e10cSrcweir // Such documents are already loaded by the last loop. 2540cdf0e10cSrcweir // Dont check E_SUCCEDED here! Its may be the final state of an AutoSave 2541cdf0e10cSrcweir // operation before!!! 2542cdf0e10cSrcweir if ((rInfo.DocumentState & AutoRecovery::E_HANDLED) == AutoRecovery::E_HANDLED) 2543cdf0e10cSrcweir continue; 2544cdf0e10cSrcweir 2545cdf0e10cSrcweir // a1,b1,c1,d2,e2,f2) 2546cdf0e10cSrcweir if ((rInfo.DocumentState & AutoRecovery::E_DAMAGED) == AutoRecovery::E_DAMAGED) 2547cdf0e10cSrcweir { 2548cdf0e10cSrcweir // dont forget to inform listener! May be this document was 2549cdf0e10cSrcweir // damaged on last saving time ... 2550cdf0e10cSrcweir // Then our listener need this notification. 2551cdf0e10cSrcweir // If it was damaged during last "try to open" ... 2552cdf0e10cSrcweir // it will be notified more then once. SH.. HAPPENS ... 2553cdf0e10cSrcweir // <- SAFE -------------------------- 2554cdf0e10cSrcweir aWriteLock.unlock(); 2555cdf0e10cSrcweir implts_informListener(eJob, 2556cdf0e10cSrcweir AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &rInfo)); 2557cdf0e10cSrcweir aWriteLock.lock(); 2558cdf0e10cSrcweir // SAFE -> -------------------------- 2559cdf0e10cSrcweir continue; 2560cdf0e10cSrcweir } 2561cdf0e10cSrcweir 2562cdf0e10cSrcweir ::comphelper::MediaDescriptor lDescriptor; 2563cdf0e10cSrcweir 2564cdf0e10cSrcweir // its an UI feature - so the "USER" itself must be set as referer 2565cdf0e10cSrcweir lDescriptor[::comphelper::MediaDescriptor::PROP_REFERRER()] <<= REFERRER_USER; 2566cdf0e10cSrcweir lDescriptor[::comphelper::MediaDescriptor::PROP_SALVAGEDFILE()] <<= ::rtl::OUString(); 2567cdf0e10cSrcweir 2568cdf0e10cSrcweir // recovered documents are loaded hidden, and shown all at once, later 2569cdf0e10cSrcweir lDescriptor[::comphelper::MediaDescriptor::PROP_HIDDEN()] <<= true; 2570cdf0e10cSrcweir 2571cdf0e10cSrcweir if (aParams.m_xProgress.is()) 2572cdf0e10cSrcweir lDescriptor[::comphelper::MediaDescriptor::PROP_STATUSINDICATOR()] <<= aParams.m_xProgress; 2573cdf0e10cSrcweir 2574cdf0e10cSrcweir sal_Bool bBackupWasTried = ( 2575cdf0e10cSrcweir ((rInfo.DocumentState & AutoRecovery::E_TRY_LOAD_BACKUP ) == AutoRecovery::E_TRY_LOAD_BACKUP) || // temp. state! 2576cdf0e10cSrcweir ((rInfo.DocumentState & AutoRecovery::E_INCOMPLETE ) == AutoRecovery::E_INCOMPLETE ) // transport TRY_LOAD_BACKUP from last loop to this new one! 2577cdf0e10cSrcweir ); 2578cdf0e10cSrcweir sal_Bool bOriginalWasTried = ((rInfo.DocumentState & AutoRecovery::E_TRY_LOAD_ORIGINAL) == AutoRecovery::E_TRY_LOAD_ORIGINAL); 2579cdf0e10cSrcweir 2580cdf0e10cSrcweir if (bBackupWasTried) 2581cdf0e10cSrcweir { 2582cdf0e10cSrcweir if (!bOriginalWasTried) 2583cdf0e10cSrcweir { 2584cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_INCOMPLETE; 2585cdf0e10cSrcweir // try original URL ... ! dont continue with next item here ... 2586cdf0e10cSrcweir } 2587cdf0e10cSrcweir else 2588cdf0e10cSrcweir { 2589cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_DAMAGED; 2590cdf0e10cSrcweir continue; 2591cdf0e10cSrcweir } 2592cdf0e10cSrcweir } 2593cdf0e10cSrcweir 2594cdf0e10cSrcweir ::rtl::OUString sLoadOriginalURL; 2595cdf0e10cSrcweir ::rtl::OUString sLoadBackupURL ; 2596cdf0e10cSrcweir 2597cdf0e10cSrcweir if (!bBackupWasTried) 2598cdf0e10cSrcweir sLoadBackupURL = rInfo.OldTempURL; 2599cdf0e10cSrcweir 2600cdf0e10cSrcweir if (rInfo.OrgURL.getLength()) 2601cdf0e10cSrcweir { 2602cdf0e10cSrcweir sLoadOriginalURL = rInfo.OrgURL; 2603cdf0e10cSrcweir } 2604cdf0e10cSrcweir else 2605cdf0e10cSrcweir if (rInfo.TemplateURL.getLength()) 2606cdf0e10cSrcweir { 2607cdf0e10cSrcweir sLoadOriginalURL = rInfo.TemplateURL; 2608cdf0e10cSrcweir lDescriptor[::comphelper::MediaDescriptor::PROP_ASTEMPLATE()] <<= sal_True; 2609cdf0e10cSrcweir lDescriptor[::comphelper::MediaDescriptor::PROP_TEMPLATENAME()] <<= rInfo.TemplateURL; 2610cdf0e10cSrcweir } 2611cdf0e10cSrcweir else 2612cdf0e10cSrcweir if (rInfo.FactoryURL.getLength()) 2613cdf0e10cSrcweir { 2614cdf0e10cSrcweir sLoadOriginalURL = rInfo.FactoryURL; 2615cdf0e10cSrcweir lDescriptor[::comphelper::MediaDescriptor::PROP_ASTEMPLATE()] <<= sal_True; 2616cdf0e10cSrcweir } 2617cdf0e10cSrcweir 2618cdf0e10cSrcweir // A "Salvaged" item must exists every time. The core can make something special then for recovery. 2619cdf0e10cSrcweir // Of course it should be the real file name of the original file, in case we load the temp. backup here. 2620cdf0e10cSrcweir ::rtl::OUString sURL; 2621cdf0e10cSrcweir if (sLoadBackupURL.getLength()) 2622cdf0e10cSrcweir { 2623cdf0e10cSrcweir sURL = sLoadBackupURL; 2624cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_TRY_LOAD_BACKUP; 2625cdf0e10cSrcweir lDescriptor[::comphelper::MediaDescriptor::PROP_SALVAGEDFILE()] <<= sLoadOriginalURL; 2626cdf0e10cSrcweir } 2627cdf0e10cSrcweir else 2628cdf0e10cSrcweir if (sLoadOriginalURL.getLength()) 2629cdf0e10cSrcweir { 2630cdf0e10cSrcweir sURL = sLoadOriginalURL; 2631cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_TRY_LOAD_ORIGINAL; 2632cdf0e10cSrcweir } 2633cdf0e10cSrcweir else 2634cdf0e10cSrcweir continue; // TODO ERROR! 2635cdf0e10cSrcweir 2636cdf0e10cSrcweir LoadEnv::initializeUIDefaults( m_xSMGR, lDescriptor, true, NULL ); 2637cdf0e10cSrcweir 2638cdf0e10cSrcweir // <- SAFE ------------------------------ 2639cdf0e10cSrcweir aWriteLock.unlock(); 2640cdf0e10cSrcweir 2641cdf0e10cSrcweir implts_flushConfigItem(rInfo); 2642cdf0e10cSrcweir implts_informListener(eJob, 2643cdf0e10cSrcweir AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &rInfo)); 2644cdf0e10cSrcweir 2645cdf0e10cSrcweir try 2646cdf0e10cSrcweir { 2647cdf0e10cSrcweir implts_openOneDoc(sURL, lDescriptor, rInfo); 2648cdf0e10cSrcweir } 2649cdf0e10cSrcweir catch(const css::uno::Exception&) 2650cdf0e10cSrcweir { 2651cdf0e10cSrcweir rInfo.DocumentState &= ~AutoRecovery::E_TRY_LOAD_BACKUP; 2652cdf0e10cSrcweir rInfo.DocumentState &= ~AutoRecovery::E_TRY_LOAD_ORIGINAL; 2653cdf0e10cSrcweir if (sLoadBackupURL.getLength()) 2654cdf0e10cSrcweir { 2655cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_INCOMPLETE; 2656cdf0e10cSrcweir eTimer = AutoRecovery::E_CALL_ME_BACK; 2657cdf0e10cSrcweir } 2658cdf0e10cSrcweir else 2659cdf0e10cSrcweir { 2660cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_HANDLED; 2661cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_DAMAGED; 2662cdf0e10cSrcweir } 2663cdf0e10cSrcweir 2664cdf0e10cSrcweir implts_flushConfigItem(rInfo, sal_True); 2665cdf0e10cSrcweir implts_informListener(eJob, 2666cdf0e10cSrcweir AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &rInfo)); 2667cdf0e10cSrcweir 2668cdf0e10cSrcweir // SAFE -> ------------------------------ 2669cdf0e10cSrcweir // Needed for next loop! 2670cdf0e10cSrcweir aWriteLock.lock(); 2671cdf0e10cSrcweir continue; 2672cdf0e10cSrcweir } 2673cdf0e10cSrcweir 2674cdf0e10cSrcweir if (rInfo.RealFilter.getLength()) 2675cdf0e10cSrcweir { 2676cdf0e10cSrcweir ::comphelper::MediaDescriptor lPatchDescriptor(rInfo.Document->getArgs()); 2677cdf0e10cSrcweir lPatchDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= rInfo.RealFilter; 2678cdf0e10cSrcweir rInfo.Document->attachResource(rInfo.Document->getURL(), lPatchDescriptor.getAsConstPropertyValueList()); 2679cdf0e10cSrcweir // do *not* use sURL here. In case this points to the recovery file, it has already been passed 2680cdf0e10cSrcweir // to recoverFromFile. Also, passing it here is logically wrong, as attachResource is intended 2681cdf0e10cSrcweir // to take the logical file URL. 2682cdf0e10cSrcweir } 2683cdf0e10cSrcweir 2684cdf0e10cSrcweir css::uno::Reference< css::util::XModifiable > xModify(rInfo.Document, css::uno::UNO_QUERY); 2685cdf0e10cSrcweir if ( xModify.is() ) 2686cdf0e10cSrcweir { 2687cdf0e10cSrcweir sal_Bool bModified = ((rInfo.DocumentState & AutoRecovery::E_MODIFIED) == AutoRecovery::E_MODIFIED); 2688cdf0e10cSrcweir xModify->setModified(bModified); 2689cdf0e10cSrcweir } 2690cdf0e10cSrcweir 2691cdf0e10cSrcweir rInfo.DocumentState &= ~AutoRecovery::E_TRY_LOAD_BACKUP; 2692cdf0e10cSrcweir rInfo.DocumentState &= ~AutoRecovery::E_TRY_LOAD_ORIGINAL; 2693cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_HANDLED; 2694cdf0e10cSrcweir rInfo.DocumentState |= AutoRecovery::E_SUCCEDED; 2695cdf0e10cSrcweir 2696cdf0e10cSrcweir implts_flushConfigItem(rInfo); 2697cdf0e10cSrcweir implts_informListener(eJob, 2698cdf0e10cSrcweir AutoRecovery::implst_createFeatureStateEvent(eJob, OPERATION_UPDATE, &rInfo)); 2699cdf0e10cSrcweir 2700e9faf1d9Smseidel /* Normally we listen as XModifyListener on a document to know if a document was changed 2701cdf0e10cSrcweir since our last AutoSave. And we deregister us in case we know this state. 2702cdf0e10cSrcweir But directly after one document as recovered ... we must start listening. 270307a3d7f1SPedro Giffuni Otherwise the first "modify" doesn't reach us. Because we ourselves called setModified() 2704e9faf1d9Smseidel on the document via API. And currently we don't listen for any events (not at the GlobalEventBroadcaster 2705cdf0e10cSrcweir nor at any document!). 2706cdf0e10cSrcweir */ 2707cdf0e10cSrcweir implts_startModifyListeningOnDoc(rInfo); 2708cdf0e10cSrcweir 2709cdf0e10cSrcweir // SAFE -> ------------------------------ 2710cdf0e10cSrcweir // Needed for next loop. Dont unlock it again! 2711cdf0e10cSrcweir aWriteLock.lock(); 2712cdf0e10cSrcweir } 2713cdf0e10cSrcweir 2714cdf0e10cSrcweir aWriteLock.unlock(); 2715cdf0e10cSrcweir // <- SAFE ---------------------------------- 2716cdf0e10cSrcweir 2717cdf0e10cSrcweir return eTimer; 2718cdf0e10cSrcweir } 2719cdf0e10cSrcweir 2720cdf0e10cSrcweir //----------------------------------------------- 2721cdf0e10cSrcweir void AutoRecovery::implts_openOneDoc(const ::rtl::OUString& sURL , 2722cdf0e10cSrcweir ::comphelper::MediaDescriptor& lDescriptor, 2723cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo ) 2724cdf0e10cSrcweir { 2725cdf0e10cSrcweir // SAFE -> ---------------------------------- 2726cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 2727cdf0e10cSrcweir css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 2728cdf0e10cSrcweir aReadLock.unlock(); 2729cdf0e10cSrcweir // <- SAFE ---------------------------------- 2730cdf0e10cSrcweir 2731cdf0e10cSrcweir css::uno::Reference< css::frame::XFrame > xDesktop( xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW ); 2732cdf0e10cSrcweir 2733cdf0e10cSrcweir ::std::vector< Reference< XComponent > > aCleanup; 2734cdf0e10cSrcweir try 2735cdf0e10cSrcweir { 2736cdf0e10cSrcweir // create a new document of the desired type 2737cdf0e10cSrcweir Reference< XModel2 > xModel( xSMGR->createInstance( rInfo.FactoryService ), UNO_QUERY_THROW ); 2738cdf0e10cSrcweir aCleanup.push_back( xModel.get() ); 2739cdf0e10cSrcweir 2740cdf0e10cSrcweir // put the filter name into the descriptor - we're not going to involve any type detection, so 2741cdf0e10cSrcweir // the document might be lost without the FilterName property 2742cdf0e10cSrcweir lDescriptor[ ::comphelper::MediaDescriptor::PROP_FILTERNAME() ] <<= rInfo.RealFilter; 2743cdf0e10cSrcweir 2744cdf0e10cSrcweir if ( sURL == rInfo.FactoryURL ) 2745cdf0e10cSrcweir { 2746cdf0e10cSrcweir // if the document was a new, unmodified document, then there's nothing to recover, just to init 2747cdf0e10cSrcweir ENSURE_OR_THROW( ( rInfo.DocumentState & AutoRecovery::E_MODIFIED ) == 0, 2748cdf0e10cSrcweir "unexpected document state" ); 2749cdf0e10cSrcweir Reference< XLoadable > xModelLoad( xModel, UNO_QUERY_THROW ); 2750cdf0e10cSrcweir xModelLoad->initNew(); 2751cdf0e10cSrcweir 2752cdf0e10cSrcweir // TODO: remove load-process specific arguments from the descriptor, e.g. the status indicator 2753cdf0e10cSrcweir xModel->attachResource( sURL, lDescriptor.getAsConstPropertyValueList() ); 2754cdf0e10cSrcweir } 2755cdf0e10cSrcweir else 2756cdf0e10cSrcweir { 2757cdf0e10cSrcweir // let it recover itself 2758cdf0e10cSrcweir Reference< XDocumentRecovery > xDocRecover( xModel, UNO_QUERY_THROW ); 2759cdf0e10cSrcweir xDocRecover->recoverFromFile( 2760cdf0e10cSrcweir sURL, 2761cdf0e10cSrcweir lDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_SALVAGEDFILE(), ::rtl::OUString() ), 2762cdf0e10cSrcweir lDescriptor.getAsConstPropertyValueList() 2763cdf0e10cSrcweir ); 2764cdf0e10cSrcweir 2765cdf0e10cSrcweir // No attachResource needed here. By definition (of XDocumentRecovery), the implementation is responsible 2766cdf0e10cSrcweir // for completely initializing the model, which includes attachResource (or equivalent), if required. 2767cdf0e10cSrcweir } 2768cdf0e10cSrcweir 2769cdf0e10cSrcweir // re-create all the views 2770cdf0e10cSrcweir ::std::vector< ::rtl::OUString > aViewsToRestore( rInfo.ViewNames.getLength() ); 2771cdf0e10cSrcweir if ( rInfo.ViewNames.getLength() ) 2772cdf0e10cSrcweir ::std::copy( rInfo.ViewNames.getConstArray(), rInfo.ViewNames.getConstArray() + rInfo.ViewNames.getLength(), aViewsToRestore.begin() ); 2773cdf0e10cSrcweir // if we don't have views for whatever reason, then create a default-view, at least 2774cdf0e10cSrcweir if ( aViewsToRestore.empty() ) 2775cdf0e10cSrcweir aViewsToRestore.push_back( ::rtl::OUString() ); 2776cdf0e10cSrcweir 2777cdf0e10cSrcweir for ( ::std::vector< ::rtl::OUString >::const_iterator viewName = aViewsToRestore.begin(); 2778cdf0e10cSrcweir viewName != aViewsToRestore.end(); 2779cdf0e10cSrcweir ++viewName 2780cdf0e10cSrcweir ) 2781cdf0e10cSrcweir { 2782cdf0e10cSrcweir // create a frame 2783cdf0e10cSrcweir Reference< XFrame > xTargetFrame = xDesktop->findFrame( SPECIALTARGET_BLANK, 0 ); 2784cdf0e10cSrcweir aCleanup.push_back( xTargetFrame.get() ); 2785cdf0e10cSrcweir 2786cdf0e10cSrcweir // create a view to the document 2787cdf0e10cSrcweir Reference< XController2 > xController; 2788cdf0e10cSrcweir if ( viewName->getLength() ) 2789cdf0e10cSrcweir { 2790cdf0e10cSrcweir xController.set( xModel->createViewController( *viewName, Sequence< PropertyValue >(), xTargetFrame ), UNO_SET_THROW ); 2791cdf0e10cSrcweir } 2792cdf0e10cSrcweir else 2793cdf0e10cSrcweir { 2794cdf0e10cSrcweir xController.set( xModel->createDefaultViewController( xTargetFrame ), UNO_SET_THROW ); 2795cdf0e10cSrcweir } 2796cdf0e10cSrcweir 2797cdf0e10cSrcweir // introduce model/view/controller to each other 2798cdf0e10cSrcweir xController->attachModel( xModel.get() ); 2799cdf0e10cSrcweir xModel->connectController( xController.get() ); 2800cdf0e10cSrcweir xTargetFrame->setComponent( xController->getComponentWindow(), xController.get() ); 2801cdf0e10cSrcweir xController->attachFrame( xTargetFrame ); 2802cdf0e10cSrcweir xModel->setCurrentController( xController.get() ); 2803cdf0e10cSrcweir } 2804cdf0e10cSrcweir 2805cdf0e10cSrcweir rInfo.Document = xModel.get(); 2806cdf0e10cSrcweir } 2807cdf0e10cSrcweir catch(const css::uno::RuntimeException&) 2808cdf0e10cSrcweir { throw; } 2809cdf0e10cSrcweir catch(const css::uno::Exception&) 2810cdf0e10cSrcweir { 2811cdf0e10cSrcweir Any aCaughtException( ::cppu::getCaughtException() ); 2812cdf0e10cSrcweir 2813cdf0e10cSrcweir // clean up 2814cdf0e10cSrcweir for ( ::std::vector< Reference< XComponent > >::const_iterator component = aCleanup.begin(); 2815cdf0e10cSrcweir component != aCleanup.end(); 2816cdf0e10cSrcweir ++component 2817cdf0e10cSrcweir ) 2818cdf0e10cSrcweir { 2819cdf0e10cSrcweir css::uno::Reference< css::util::XCloseable > xClose( *component, css::uno::UNO_QUERY ); 2820cdf0e10cSrcweir if ( xClose.is() ) 2821cdf0e10cSrcweir xClose->close( sal_True ); 2822cdf0e10cSrcweir else 2823cdf0e10cSrcweir (*component)->dispose(); 2824cdf0e10cSrcweir } 2825cdf0e10cSrcweir 2826cdf0e10cSrcweir // re-throw 2827cdf0e10cSrcweir ::rtl::OUStringBuffer sMsg(256); 2828cdf0e10cSrcweir sMsg.appendAscii("Recovery of \""); 2829cdf0e10cSrcweir sMsg.append (sURL ); 2830cdf0e10cSrcweir sMsg.appendAscii("\" failed." ); 2831cdf0e10cSrcweir 2832cdf0e10cSrcweir throw css::lang::WrappedTargetException( 2833cdf0e10cSrcweir sMsg.makeStringAndClear(), 2834cdf0e10cSrcweir static_cast< css::frame::XDispatch* >(this), 2835cdf0e10cSrcweir aCaughtException 2836cdf0e10cSrcweir ); 2837cdf0e10cSrcweir } 2838cdf0e10cSrcweir } 2839cdf0e10cSrcweir 2840cdf0e10cSrcweir //----------------------------------------------- 2841cdf0e10cSrcweir void AutoRecovery::implts_generateNewTempURL(const ::rtl::OUString& sBackupPath , 2842cdf0e10cSrcweir ::comphelper::MediaDescriptor& /*rMediaDescriptor*/, 2843cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo ) 2844cdf0e10cSrcweir { 2845cdf0e10cSrcweir // SAFE -> ---------------------------------- 2846cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 2847cdf0e10cSrcweir css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 2848cdf0e10cSrcweir aReadLock.unlock(); 2849cdf0e10cSrcweir // <- SAFE ---------------------------------- 2850cdf0e10cSrcweir 2851cdf0e10cSrcweir // specify URL for saving (which points to a temp file inside backup directory) 2852cdf0e10cSrcweir // and define an unique name, so we can locate it later. 2853cdf0e10cSrcweir // This unique name must solve an optimization problem too! 2854cdf0e10cSrcweir // In case we are asked to save unmodified documents too - and one of them 2855cdf0e10cSrcweir // is an empty one (because it was new created using e.g. an URL private:factory/...) 285607a3d7f1SPedro Giffuni // we should not save it really. Then we put the information about such "empty document" 2857cdf0e10cSrcweir // into the configuration and dont create any recovery file on disk. 2858cdf0e10cSrcweir // We use the title of the document to make it unique. 2859cdf0e10cSrcweir ::rtl::OUStringBuffer sUniqueName; 2860cdf0e10cSrcweir if (rInfo.OrgURL.getLength()) 2861cdf0e10cSrcweir { 2862cdf0e10cSrcweir css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY); 2863cdf0e10cSrcweir css::util::URL aURL; 2864cdf0e10cSrcweir aURL.Complete = rInfo.OrgURL; 2865cdf0e10cSrcweir xParser->parseStrict(aURL); 2866cdf0e10cSrcweir sUniqueName.append(aURL.Name); 2867cdf0e10cSrcweir } 2868cdf0e10cSrcweir else 2869cdf0e10cSrcweir if (rInfo.FactoryURL.getLength()) 2870cdf0e10cSrcweir sUniqueName.appendAscii("untitled"); 2871cdf0e10cSrcweir sUniqueName.appendAscii("_"); 2872cdf0e10cSrcweir 2873cdf0e10cSrcweir // TODO: Must we strip some illegal signes - if we use the title? 2874cdf0e10cSrcweir 2875cdf0e10cSrcweir String sName (sUniqueName.makeStringAndClear()); 2876cdf0e10cSrcweir String sExtension(rInfo.Extension ); 2877cdf0e10cSrcweir String sPath (sBackupPath ); 2878cdf0e10cSrcweir ::utl::TempFile aTempFile(sName, &sExtension, &sPath); 2879cdf0e10cSrcweir 2880cdf0e10cSrcweir rInfo.NewTempURL = aTempFile.GetURL(); 2881cdf0e10cSrcweir } 2882cdf0e10cSrcweir 2883cdf0e10cSrcweir //----------------------------------------------- 2884cdf0e10cSrcweir void AutoRecovery::implts_informListener( sal_Int32 eJob , 2885cdf0e10cSrcweir const css::frame::FeatureStateEvent& aEvent) 2886cdf0e10cSrcweir { 2887cdf0e10cSrcweir // Helper shares mutex with us -> threadsafe! 2888cdf0e10cSrcweir ::cppu::OInterfaceContainerHelper* pListenerForURL = 0; 2889cdf0e10cSrcweir ::rtl::OUString sJob = AutoRecovery::implst_getJobDescription(eJob); 2890cdf0e10cSrcweir 2891cdf0e10cSrcweir // inform listener, which are registered for any URLs(!) 2892cdf0e10cSrcweir pListenerForURL = m_lListener.getContainer(sJob); 2893cdf0e10cSrcweir if(pListenerForURL != 0) 2894cdf0e10cSrcweir { 2895cdf0e10cSrcweir ::cppu::OInterfaceIteratorHelper pIt(*pListenerForURL); 2896cdf0e10cSrcweir while(pIt.hasMoreElements()) 2897cdf0e10cSrcweir { 2898cdf0e10cSrcweir try 2899cdf0e10cSrcweir { 2900cdf0e10cSrcweir css::uno::Reference< css::frame::XStatusListener > xListener(((css::frame::XStatusListener*)pIt.next()), css::uno::UNO_QUERY); 2901cdf0e10cSrcweir xListener->statusChanged(aEvent); 2902cdf0e10cSrcweir } 2903cdf0e10cSrcweir catch(const css::uno::RuntimeException&) 2904cdf0e10cSrcweir { pIt.remove(); } 2905cdf0e10cSrcweir } 2906cdf0e10cSrcweir } 2907cdf0e10cSrcweir } 2908cdf0e10cSrcweir 2909cdf0e10cSrcweir //----------------------------------------------- 2910cdf0e10cSrcweir ::rtl::OUString AutoRecovery::implst_getJobDescription(sal_Int32 eJob) 2911cdf0e10cSrcweir { 2912cdf0e10cSrcweir // describe the current running operation 2913cdf0e10cSrcweir ::rtl::OUStringBuffer sFeature(256); 2914cdf0e10cSrcweir sFeature.append(CMD_PROTOCOL); 2915cdf0e10cSrcweir 2916cdf0e10cSrcweir // Attention: Because "eJob" is used as a flag field the order of checking these 2917cdf0e10cSrcweir // flags is importent. We must preferr job with higher priorities! 2918cdf0e10cSrcweir // E.g. EmergencySave has an higher prio then AutoSave ... 2919cdf0e10cSrcweir // On the other side there exist a well defined order between two different jobs. 2920cdf0e10cSrcweir // e.g. PrepareEmergencySave must be done before EmergencySave is started of course. 2921cdf0e10cSrcweir 2922cdf0e10cSrcweir if ((eJob & AutoRecovery::E_PREPARE_EMERGENCY_SAVE) == AutoRecovery::E_PREPARE_EMERGENCY_SAVE) 2923cdf0e10cSrcweir sFeature.append(CMD_DO_PREPARE_EMERGENCY_SAVE); 2924cdf0e10cSrcweir else 2925cdf0e10cSrcweir if ((eJob & AutoRecovery::E_EMERGENCY_SAVE) == AutoRecovery::E_EMERGENCY_SAVE) 2926cdf0e10cSrcweir sFeature.append(CMD_DO_EMERGENCY_SAVE); 2927cdf0e10cSrcweir else 2928cdf0e10cSrcweir if ((eJob & AutoRecovery::E_RECOVERY) == AutoRecovery::E_RECOVERY) 2929cdf0e10cSrcweir sFeature.append(CMD_DO_RECOVERY); 2930cdf0e10cSrcweir else 2931cdf0e10cSrcweir if ((eJob & AutoRecovery::E_SESSION_SAVE) == AutoRecovery::E_SESSION_SAVE) 2932cdf0e10cSrcweir sFeature.append(CMD_DO_SESSION_SAVE); 2933cdf0e10cSrcweir else 2934cdf0e10cSrcweir if ((eJob & AutoRecovery::E_SESSION_QUIET_QUIT) == AutoRecovery::E_SESSION_QUIET_QUIT) 2935cdf0e10cSrcweir sFeature.append(CMD_DO_SESSION_QUIET_QUIT); 2936cdf0e10cSrcweir else 2937cdf0e10cSrcweir if ((eJob & AutoRecovery::E_SESSION_RESTORE) == AutoRecovery::E_SESSION_RESTORE) 2938cdf0e10cSrcweir sFeature.append(CMD_DO_SESSION_RESTORE); 2939cdf0e10cSrcweir else 2940cdf0e10cSrcweir if ((eJob & AutoRecovery::E_ENTRY_BACKUP) == AutoRecovery::E_ENTRY_BACKUP) 2941cdf0e10cSrcweir sFeature.append(CMD_DO_ENTRY_BACKUP); 2942cdf0e10cSrcweir else 2943cdf0e10cSrcweir if ((eJob & AutoRecovery::E_ENTRY_CLEANUP) == AutoRecovery::E_ENTRY_CLEANUP) 2944cdf0e10cSrcweir sFeature.append(CMD_DO_ENTRY_CLEANUP); 2945cdf0e10cSrcweir else 2946cdf0e10cSrcweir if ((eJob & AutoRecovery::E_AUTO_SAVE) == AutoRecovery::E_AUTO_SAVE) 2947cdf0e10cSrcweir sFeature.append(CMD_DO_AUTO_SAVE); 2948cdf0e10cSrcweir #ifdef ENABLE_WARNINGS 2949cdf0e10cSrcweir else if ( eJob != AutoRecovery::E_NO_JOB ) 2950cdf0e10cSrcweir LOG_WARNING("AutoRecovery::implst_getJobDescription()", "Invalid job identifier detected.") 2951cdf0e10cSrcweir #endif 2952cdf0e10cSrcweir 2953cdf0e10cSrcweir return sFeature.makeStringAndClear(); 2954cdf0e10cSrcweir } 2955cdf0e10cSrcweir 2956cdf0e10cSrcweir //----------------------------------------------- 2957cdf0e10cSrcweir sal_Int32 AutoRecovery::implst_classifyJob(const css::util::URL& aURL) 2958cdf0e10cSrcweir { 2959cdf0e10cSrcweir if (aURL.Protocol.equals(CMD_PROTOCOL)) 2960cdf0e10cSrcweir { 2961cdf0e10cSrcweir if (aURL.Path.equals(CMD_DO_PREPARE_EMERGENCY_SAVE)) 2962cdf0e10cSrcweir return AutoRecovery::E_PREPARE_EMERGENCY_SAVE; 2963cdf0e10cSrcweir else 2964cdf0e10cSrcweir if (aURL.Path.equals(CMD_DO_EMERGENCY_SAVE)) 2965cdf0e10cSrcweir return AutoRecovery::E_EMERGENCY_SAVE; 2966cdf0e10cSrcweir else 2967cdf0e10cSrcweir if (aURL.Path.equals(CMD_DO_RECOVERY)) 2968cdf0e10cSrcweir return AutoRecovery::E_RECOVERY; 2969cdf0e10cSrcweir else 2970cdf0e10cSrcweir if (aURL.Path.equals(CMD_DO_ENTRY_BACKUP)) 2971cdf0e10cSrcweir return AutoRecovery::E_ENTRY_BACKUP; 2972cdf0e10cSrcweir else 2973cdf0e10cSrcweir if (aURL.Path.equals(CMD_DO_ENTRY_CLEANUP)) 2974cdf0e10cSrcweir return AutoRecovery::E_ENTRY_CLEANUP; 2975cdf0e10cSrcweir else 2976cdf0e10cSrcweir if (aURL.Path.equals(CMD_DO_SESSION_SAVE)) 2977cdf0e10cSrcweir return AutoRecovery::E_SESSION_SAVE; 2978cdf0e10cSrcweir else 2979cdf0e10cSrcweir if (aURL.Path.equals(CMD_DO_SESSION_QUIET_QUIT)) 2980cdf0e10cSrcweir return AutoRecovery::E_SESSION_QUIET_QUIT; 2981cdf0e10cSrcweir else 2982cdf0e10cSrcweir if (aURL.Path.equals(CMD_DO_SESSION_RESTORE)) 2983cdf0e10cSrcweir return AutoRecovery::E_SESSION_RESTORE; 2984cdf0e10cSrcweir else 2985cdf0e10cSrcweir if (aURL.Path.equals(CMD_DO_DISABLE_RECOVERY)) 2986cdf0e10cSrcweir return AutoRecovery::E_DISABLE_AUTORECOVERY; 2987cdf0e10cSrcweir else 2988cdf0e10cSrcweir if (aURL.Path.equals(CMD_DO_SET_AUTOSAVE_STATE)) 2989cdf0e10cSrcweir return AutoRecovery::E_SET_AUTOSAVE_STATE; 2990cdf0e10cSrcweir } 2991cdf0e10cSrcweir 2992cdf0e10cSrcweir LOG_WARNING("AutoRecovery::implts_classifyJob()", "Invalid URL (protocol).") 2993cdf0e10cSrcweir return AutoRecovery::E_NO_JOB; 2994cdf0e10cSrcweir } 2995cdf0e10cSrcweir 2996cdf0e10cSrcweir //----------------------------------------------- 2997cdf0e10cSrcweir css::frame::FeatureStateEvent AutoRecovery::implst_createFeatureStateEvent( sal_Int32 eJob , 2998cdf0e10cSrcweir const ::rtl::OUString& sEventType, 2999cdf0e10cSrcweir AutoRecovery::TDocumentInfo* pInfo ) 3000cdf0e10cSrcweir { 3001cdf0e10cSrcweir css::frame::FeatureStateEvent aEvent; 3002cdf0e10cSrcweir aEvent.FeatureURL.Complete = AutoRecovery::implst_getJobDescription(eJob); 3003cdf0e10cSrcweir aEvent.FeatureDescriptor = sEventType; 3004cdf0e10cSrcweir 3005cdf0e10cSrcweir if (sEventType.equals(OPERATION_UPDATE) && pInfo) 3006cdf0e10cSrcweir { 3007cdf0e10cSrcweir // pack rInfo for transport via UNO 3008cdf0e10cSrcweir ::comphelper::NamedValueCollection aInfo; 3009cdf0e10cSrcweir aInfo.put( CFG_ENTRY_PROP_ID, pInfo->ID ); 3010cdf0e10cSrcweir aInfo.put( CFG_ENTRY_PROP_ORIGINALURL, pInfo->OrgURL ); 3011cdf0e10cSrcweir aInfo.put( CFG_ENTRY_PROP_FACTORYURL, pInfo->FactoryURL ); 3012cdf0e10cSrcweir aInfo.put( CFG_ENTRY_PROP_TEMPLATEURL, pInfo->TemplateURL ); 3013cdf0e10cSrcweir aInfo.put( CFG_ENTRY_PROP_TEMPURL, pInfo->OldTempURL.getLength() ? pInfo->OldTempURL : pInfo->NewTempURL ); 3014cdf0e10cSrcweir aInfo.put( CFG_ENTRY_PROP_MODULE, pInfo->AppModule ); 3015cdf0e10cSrcweir aInfo.put( CFG_ENTRY_PROP_TITLE, pInfo->Title ); 3016cdf0e10cSrcweir aInfo.put( CFG_ENTRY_PROP_VIEWNAMES, pInfo->ViewNames ); 3017cdf0e10cSrcweir aInfo.put( CFG_ENTRY_PROP_DOCUMENTSTATE, pInfo->DocumentState ); 3018cdf0e10cSrcweir 3019cdf0e10cSrcweir aEvent.State <<= aInfo.getPropertyValues(); 3020cdf0e10cSrcweir } 3021cdf0e10cSrcweir 3022cdf0e10cSrcweir return aEvent; 3023cdf0e10cSrcweir } 3024cdf0e10cSrcweir 3025cdf0e10cSrcweir //----------------------------------------------- 3026cdf0e10cSrcweir void AutoRecovery::implts_resetHandleStates(sal_Bool /*bLoadCache*/) 3027cdf0e10cSrcweir { 3028cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 3029cdf0e10cSrcweir 3030cdf0e10cSrcweir // SAFE -> ------------------------------ 3031cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 3032cdf0e10cSrcweir 3033cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt; 3034cdf0e10cSrcweir for ( pIt = m_lDocCache.begin(); 3035cdf0e10cSrcweir pIt != m_lDocCache.end() ; 3036cdf0e10cSrcweir ++pIt ) 3037cdf0e10cSrcweir { 3038cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo = *pIt; 3039cdf0e10cSrcweir rInfo.DocumentState &= ~AutoRecovery::E_HANDLED ; 3040cdf0e10cSrcweir rInfo.DocumentState &= ~AutoRecovery::E_POSTPONED; 3041cdf0e10cSrcweir 3042cdf0e10cSrcweir // SAFE -> ------------------------------ 3043cdf0e10cSrcweir aWriteLock.unlock(); 3044cdf0e10cSrcweir implts_flushConfigItem(rInfo); 3045cdf0e10cSrcweir aWriteLock.lock(); 3046cdf0e10cSrcweir // <- SAFE ------------------------------ 3047cdf0e10cSrcweir } 3048cdf0e10cSrcweir 3049cdf0e10cSrcweir aWriteLock.unlock(); 3050cdf0e10cSrcweir // <- SAFE ---------------------------------- 3051cdf0e10cSrcweir } 3052cdf0e10cSrcweir 3053cdf0e10cSrcweir //----------------------------------------------- 3054cdf0e10cSrcweir void AutoRecovery::implts_prepareEmergencySave() 3055cdf0e10cSrcweir { 305607a3d7f1SPedro Giffuni // Be sure to know all open documents really .-) 3057cdf0e10cSrcweir implts_verifyCacheAgainstDesktopDocumentList(); 3058cdf0e10cSrcweir 305907a3d7f1SPedro Giffuni // hide all docs, so the user can't disturb our emergency save .-) 3060cdf0e10cSrcweir implts_changeAllDocVisibility(sal_False); 3061cdf0e10cSrcweir } 3062cdf0e10cSrcweir 3063cdf0e10cSrcweir //----------------------------------------------- 3064cdf0e10cSrcweir void AutoRecovery::implts_doEmergencySave(const DispatchParams& aParams) 3065cdf0e10cSrcweir { 3066cdf0e10cSrcweir // Write a hint "we chrashed" into the configuration, so 3067cdf0e10cSrcweir // the error report tool is started too in case no recovery 3068cdf0e10cSrcweir // documents exists and was saved. 3069cdf0e10cSrcweir ::comphelper::ConfigurationHelper::writeDirectKey( 3070cdf0e10cSrcweir m_xSMGR, 3071cdf0e10cSrcweir CFG_PACKAGE_RECOVERY, 3072cdf0e10cSrcweir CFG_PATH_RECOVERYINFO, 3073cdf0e10cSrcweir CFG_ENTRY_CRASHED, 3074cdf0e10cSrcweir css::uno::makeAny(sal_True), 3075cdf0e10cSrcweir ::comphelper::ConfigurationHelper::E_STANDARD); 3076cdf0e10cSrcweir 3077cdf0e10cSrcweir // for all docs, store their current view/names in the configurtion 3078cdf0e10cSrcweir implts_persistAllActiveViewNames(); 3079cdf0e10cSrcweir 3080cdf0e10cSrcweir // The called method for saving documents runs 3081cdf0e10cSrcweir // during normal AutoSave more then once. Because 3082cdf0e10cSrcweir // it postpone active documents and save it later. 3083e9faf1d9Smseidel // That is normally done by recalling it from a timer. 308407a3d7f1SPedro Giffuni // Here we must do it immediately! 3085cdf0e10cSrcweir // Of course this method returns the right state - 3086cdf0e10cSrcweir // because it knows, that we are running in ERMERGENCY SAVE mode .-) 3087cdf0e10cSrcweir 3088cdf0e10cSrcweir sal_Bool bAllowUserIdleLoop = sal_False; // not allowed to change that .-) 3089cdf0e10cSrcweir AutoRecovery::ETimerType eSuggestedTimer = AutoRecovery::E_DONT_START_TIMER; 3090cdf0e10cSrcweir do 3091cdf0e10cSrcweir { 3092cdf0e10cSrcweir eSuggestedTimer = implts_saveDocs(bAllowUserIdleLoop, sal_True, &aParams); 3093cdf0e10cSrcweir } 3094cdf0e10cSrcweir while(eSuggestedTimer == AutoRecovery::E_CALL_ME_BACK); 3095cdf0e10cSrcweir 3096cdf0e10cSrcweir // reset the handle state of all 3097cdf0e10cSrcweir // cache items. Such handle state indicates, that a document 3098cdf0e10cSrcweir // was already saved during the THIS(!) EmergencySave session. 3099cdf0e10cSrcweir // Of course following recovery session must be started without 3100cdf0e10cSrcweir // any "handle" state ... 3101cdf0e10cSrcweir implts_resetHandleStates(sal_False); 3102cdf0e10cSrcweir 3103cdf0e10cSrcweir // flush config cached back to disc. 3104cdf0e10cSrcweir impl_flushALLConfigChanges(); 3105cdf0e10cSrcweir 3106*7a164331Smseidel // try to make sure next time office will be started user won't be 3107cdf0e10cSrcweir // notified about any other might be running office instance 3108cdf0e10cSrcweir // remove ".lock" file from disc ! 3109cdf0e10cSrcweir AutoRecovery::st_impl_removeLockFile(); 3110cdf0e10cSrcweir } 3111cdf0e10cSrcweir 3112cdf0e10cSrcweir //----------------------------------------------- 3113cdf0e10cSrcweir void AutoRecovery::implts_doRecovery(const DispatchParams& aParams) 3114cdf0e10cSrcweir { 3115cdf0e10cSrcweir AutoRecovery::ETimerType eSuggestedTimer = AutoRecovery::E_DONT_START_TIMER; 3116cdf0e10cSrcweir do 3117cdf0e10cSrcweir { 3118cdf0e10cSrcweir eSuggestedTimer = implts_openDocs(aParams); 3119cdf0e10cSrcweir } 3120cdf0e10cSrcweir while(eSuggestedTimer == AutoRecovery::E_CALL_ME_BACK); 3121cdf0e10cSrcweir 3122cdf0e10cSrcweir // reset the handle state of all 3123cdf0e10cSrcweir // cache items. Such handle state indicates, that a document 3124cdf0e10cSrcweir // was already saved during the THIS(!) Recovery session. 3125cdf0e10cSrcweir // Of course a may be following EmergencySave session must be started without 3126cdf0e10cSrcweir // any "handle" state ... 3127cdf0e10cSrcweir implts_resetHandleStates(sal_True); 3128cdf0e10cSrcweir 3129cdf0e10cSrcweir // Reset the configuration hint "we was crashed"! 3130cdf0e10cSrcweir ::comphelper::ConfigurationHelper::writeDirectKey( 3131cdf0e10cSrcweir m_xSMGR, 3132cdf0e10cSrcweir CFG_PACKAGE_RECOVERY, 3133cdf0e10cSrcweir CFG_PATH_RECOVERYINFO, 3134cdf0e10cSrcweir CFG_ENTRY_CRASHED, 3135cdf0e10cSrcweir css::uno::makeAny(sal_False), 3136cdf0e10cSrcweir ::comphelper::ConfigurationHelper::E_STANDARD); 3137cdf0e10cSrcweir } 3138cdf0e10cSrcweir 3139cdf0e10cSrcweir //----------------------------------------------- 3140cdf0e10cSrcweir void AutoRecovery::implts_doSessionSave(const DispatchParams& aParams) 3141cdf0e10cSrcweir { 3142cdf0e10cSrcweir LOG_RECOVERY("AutoRecovery::implts_doSessionSave()") 3143cdf0e10cSrcweir 314407a3d7f1SPedro Giffuni // Be sure to know all open documents really .-) 3145cdf0e10cSrcweir implts_verifyCacheAgainstDesktopDocumentList(); 3146cdf0e10cSrcweir 3147cdf0e10cSrcweir // for all docs, store their current view/names in the configurtion 3148cdf0e10cSrcweir implts_persistAllActiveViewNames(); 3149cdf0e10cSrcweir 3150cdf0e10cSrcweir // The called method for saving documents runs 3151cdf0e10cSrcweir // during normal AutoSave more then once. Because 3152cdf0e10cSrcweir // it postpone active documents and save it later. 3153e9faf1d9Smseidel // That is normally done by recalling it from a timer. 315407a3d7f1SPedro Giffuni // Here we must do it immediately! 3155cdf0e10cSrcweir // Of course this method returns the right state - 3156cdf0e10cSrcweir // because it knows, that we are running in SESSION SAVE mode .-) 3157cdf0e10cSrcweir 3158cdf0e10cSrcweir sal_Bool bAllowUserIdleLoop = sal_False; // not allowed to change that .-) 3159cdf0e10cSrcweir AutoRecovery::ETimerType eSuggestedTimer = AutoRecovery::E_DONT_START_TIMER; 3160cdf0e10cSrcweir do 3161cdf0e10cSrcweir { 3162cdf0e10cSrcweir // do not remove lock files of the documents, it will be done on session quit 3163cdf0e10cSrcweir eSuggestedTimer = implts_saveDocs(bAllowUserIdleLoop, sal_False, &aParams); 3164cdf0e10cSrcweir } 3165cdf0e10cSrcweir while(eSuggestedTimer == AutoRecovery::E_CALL_ME_BACK); 3166cdf0e10cSrcweir 3167cdf0e10cSrcweir // reset the handle state of all 3168cdf0e10cSrcweir // cache items. Such handle state indicates, that a document 3169cdf0e10cSrcweir // was already saved during the THIS(!) save session. 3170cdf0e10cSrcweir // Of course following restore session must be started without 3171cdf0e10cSrcweir // any "handle" state ... 3172cdf0e10cSrcweir implts_resetHandleStates(sal_False); 3173cdf0e10cSrcweir 3174cdf0e10cSrcweir // flush config cached back to disc. 3175cdf0e10cSrcweir impl_flushALLConfigChanges(); 3176cdf0e10cSrcweir } 3177cdf0e10cSrcweir 3178cdf0e10cSrcweir //----------------------------------------------- 3179cdf0e10cSrcweir void AutoRecovery::implts_doSessionQuietQuit(const DispatchParams& /*aParams*/) 3180cdf0e10cSrcweir { 3181cdf0e10cSrcweir LOG_RECOVERY("AutoRecovery::implts_doSessionQuietQuit()") 3182cdf0e10cSrcweir 3183*7a164331Smseidel // try to make sure next time office will be started user won't be 3184cdf0e10cSrcweir // notified about any other might be running office instance 3185cdf0e10cSrcweir // remove ".lock" file from disc ! 3186cdf0e10cSrcweir // it is done as a first action for session save since Gnome sessions 3187cdf0e10cSrcweir // do not provide enough time for shutdown, and the dialog looks to be 3188cdf0e10cSrcweir // confusing for the user 3189cdf0e10cSrcweir AutoRecovery::st_impl_removeLockFile(); 3190cdf0e10cSrcweir 3191cdf0e10cSrcweir // reset all modified documents, so the dont show any UI on closing ... 3192cdf0e10cSrcweir // and close all documents, so we can shutdown the OS! 3193cdf0e10cSrcweir implts_prepareSessionShutdown(); 3194cdf0e10cSrcweir 3195cdf0e10cSrcweir // Write a hint for "stored session data" into the configuration, so 3196cdf0e10cSrcweir // the on next startup we know what's happen last time 3197cdf0e10cSrcweir ::comphelper::ConfigurationHelper::writeDirectKey( 3198cdf0e10cSrcweir m_xSMGR, 3199cdf0e10cSrcweir CFG_PACKAGE_RECOVERY, 3200cdf0e10cSrcweir CFG_PATH_RECOVERYINFO, 3201cdf0e10cSrcweir CFG_ENTRY_SESSIONDATA, 3202cdf0e10cSrcweir css::uno::makeAny(sal_True), 3203cdf0e10cSrcweir ::comphelper::ConfigurationHelper::E_STANDARD); 3204cdf0e10cSrcweir 3205cdf0e10cSrcweir // flush config cached back to disc. 3206cdf0e10cSrcweir impl_flushALLConfigChanges(); 3207cdf0e10cSrcweir } 3208cdf0e10cSrcweir 3209cdf0e10cSrcweir 3210cdf0e10cSrcweir //----------------------------------------------- 3211cdf0e10cSrcweir void AutoRecovery::implts_doSessionRestore(const DispatchParams& aParams) 3212cdf0e10cSrcweir { 3213cdf0e10cSrcweir LOG_RECOVERY("AutoRecovery::implts_doSessionRestore() ...") 3214cdf0e10cSrcweir 3215cdf0e10cSrcweir AutoRecovery::ETimerType eSuggestedTimer = AutoRecovery::E_DONT_START_TIMER; 3216cdf0e10cSrcweir do 3217cdf0e10cSrcweir { 3218cdf0e10cSrcweir eSuggestedTimer = implts_openDocs(aParams); 3219cdf0e10cSrcweir } 3220cdf0e10cSrcweir while(eSuggestedTimer == AutoRecovery::E_CALL_ME_BACK); 3221cdf0e10cSrcweir 3222cdf0e10cSrcweir // reset the handle state of all 3223cdf0e10cSrcweir // cache items. Such handle state indicates, that a document 3224cdf0e10cSrcweir // was already saved during the THIS(!) Restore session. 3225cdf0e10cSrcweir // Of course a may be following save session must be started without 3226cdf0e10cSrcweir // any "handle" state ... 3227cdf0e10cSrcweir implts_resetHandleStates(sal_True); 3228cdf0e10cSrcweir 3229cdf0e10cSrcweir // make all opened documents visible 3230cdf0e10cSrcweir implts_changeAllDocVisibility(sal_True); 3231cdf0e10cSrcweir 3232cdf0e10cSrcweir // Reset the configuration hint for "session save"! 3233cdf0e10cSrcweir LOG_RECOVERY("... reset config key 'SessionData'") 3234cdf0e10cSrcweir ::comphelper::ConfigurationHelper::writeDirectKey( 3235cdf0e10cSrcweir m_xSMGR, 3236cdf0e10cSrcweir CFG_PACKAGE_RECOVERY, 3237cdf0e10cSrcweir CFG_PATH_RECOVERYINFO, 3238cdf0e10cSrcweir CFG_ENTRY_SESSIONDATA, 3239cdf0e10cSrcweir css::uno::makeAny(sal_False), 3240cdf0e10cSrcweir ::comphelper::ConfigurationHelper::E_STANDARD); 3241cdf0e10cSrcweir 3242cdf0e10cSrcweir LOG_RECOVERY("... AutoRecovery::implts_doSessionRestore()") 3243cdf0e10cSrcweir } 3244cdf0e10cSrcweir 3245cdf0e10cSrcweir //----------------------------------------------- 3246cdf0e10cSrcweir void AutoRecovery::implts_backupWorkingEntry(const DispatchParams& aParams) 3247cdf0e10cSrcweir { 3248cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_USE); 3249cdf0e10cSrcweir 3250cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt; 3251cdf0e10cSrcweir for ( pIt = m_lDocCache.begin(); 3252cdf0e10cSrcweir pIt != m_lDocCache.end() ; 3253cdf0e10cSrcweir ++pIt ) 3254cdf0e10cSrcweir { 3255cdf0e10cSrcweir const AutoRecovery::TDocumentInfo& rInfo = *pIt; 3256cdf0e10cSrcweir if (rInfo.ID != aParams.m_nWorkingEntryID) 3257cdf0e10cSrcweir continue; 3258cdf0e10cSrcweir 3259cdf0e10cSrcweir ::rtl::OUString sSourceURL; 3260cdf0e10cSrcweir // Prefer temp file. It contains the changes against the original document! 3261cdf0e10cSrcweir if (rInfo.OldTempURL.getLength()) 3262cdf0e10cSrcweir sSourceURL = rInfo.OldTempURL; 3263cdf0e10cSrcweir else 3264cdf0e10cSrcweir if (rInfo.NewTempURL.getLength()) 3265cdf0e10cSrcweir sSourceURL = rInfo.NewTempURL; 3266cdf0e10cSrcweir else 3267cdf0e10cSrcweir if (rInfo.OrgURL.getLength()) 3268cdf0e10cSrcweir sSourceURL = rInfo.OrgURL; 3269cdf0e10cSrcweir else 3270cdf0e10cSrcweir continue; // nothing real to save! An unmodified but new created document. 3271cdf0e10cSrcweir 3272cdf0e10cSrcweir INetURLObject aParser(sSourceURL); 3273cdf0e10cSrcweir // AutoRecovery::EFailureSafeResult eResult = 3274cdf0e10cSrcweir implts_copyFile(sSourceURL, aParams.m_sSavePath, aParser.getName()); 3275cdf0e10cSrcweir 3276cdf0e10cSrcweir // TODO: Check eResult and react for errors (InteractionHandler!?) 3277cdf0e10cSrcweir // Currently we ignore it ... 3278cdf0e10cSrcweir // DONT UPDATE THE CACHE OR REMOVE ANY TEMP. FILES FROM DISK. 3279cdf0e10cSrcweir // That has to be forced from outside explicitly. 3280cdf0e10cSrcweir // See implts_cleanUpWorkingEntry() for further details. 3281cdf0e10cSrcweir } 3282cdf0e10cSrcweir } 3283cdf0e10cSrcweir 3284cdf0e10cSrcweir //----------------------------------------------- 3285cdf0e10cSrcweir void AutoRecovery::implts_cleanUpWorkingEntry(const DispatchParams& aParams) 3286cdf0e10cSrcweir { 3287cdf0e10cSrcweir CacheLockGuard aCacheLock(this, m_aLock, m_nDocCacheLock, LOCK_FOR_CACHE_ADD_REMOVE); 3288cdf0e10cSrcweir 3289cdf0e10cSrcweir AutoRecovery::TDocumentList::iterator pIt; 3290cdf0e10cSrcweir for ( pIt = m_lDocCache.begin(); 3291cdf0e10cSrcweir pIt != m_lDocCache.end() ; 3292cdf0e10cSrcweir ++pIt ) 3293cdf0e10cSrcweir { 3294cdf0e10cSrcweir AutoRecovery::TDocumentInfo& rInfo = *pIt; 3295cdf0e10cSrcweir if (rInfo.ID != aParams.m_nWorkingEntryID) 3296cdf0e10cSrcweir continue; 3297cdf0e10cSrcweir 3298cdf0e10cSrcweir AutoRecovery::st_impl_removeFile(rInfo.OldTempURL); 3299cdf0e10cSrcweir AutoRecovery::st_impl_removeFile(rInfo.NewTempURL); 3300cdf0e10cSrcweir implts_flushConfigItem(rInfo, sal_True); // sal_True => remove it from xml config! 3301cdf0e10cSrcweir 3302cdf0e10cSrcweir m_lDocCache.erase(pIt); 3303cdf0e10cSrcweir break; /// !!! pIt is not defined any longer ... further this function has finished it's work 3304cdf0e10cSrcweir } 3305cdf0e10cSrcweir } 3306cdf0e10cSrcweir 3307cdf0e10cSrcweir //----------------------------------------------- 3308cdf0e10cSrcweir AutoRecovery::EFailureSafeResult AutoRecovery::implts_copyFile(const ::rtl::OUString& sSource , 3309cdf0e10cSrcweir const ::rtl::OUString& sTargetPath, 3310cdf0e10cSrcweir const ::rtl::OUString& sTargetName) 3311cdf0e10cSrcweir { 3312cdf0e10cSrcweir // create content for the parent folder and call transfer on that content with the source content 3313cdf0e10cSrcweir // and the destination file name as parameters 3314cdf0e10cSrcweir 3315cdf0e10cSrcweir css::uno::Reference< css::ucb::XCommandEnvironment > xEnvironment; 3316cdf0e10cSrcweir 3317cdf0e10cSrcweir ::ucbhelper::Content aSourceContent; 3318cdf0e10cSrcweir ::ucbhelper::Content aTargetContent; 3319cdf0e10cSrcweir 3320cdf0e10cSrcweir try 3321cdf0e10cSrcweir { 3322cdf0e10cSrcweir aTargetContent = ::ucbhelper::Content(sTargetPath, xEnvironment); 3323cdf0e10cSrcweir } 3324cdf0e10cSrcweir catch(const css::uno::Exception&) 3325cdf0e10cSrcweir { return AutoRecovery::E_WRONG_TARGET_PATH; } 3326cdf0e10cSrcweir 3327cdf0e10cSrcweir sal_Int32 nNameClash; 3328cdf0e10cSrcweir // nNameClash = css::ucb::NameClash::ERROR; 3329cdf0e10cSrcweir nNameClash = css::ucb::NameClash::RENAME; 3330cdf0e10cSrcweir // nNameClash = css::ucb::NameClash::OVERWRITE; 3331cdf0e10cSrcweir 3332cdf0e10cSrcweir try 3333cdf0e10cSrcweir { 3334cdf0e10cSrcweir ::ucbhelper::Content::create(sSource, xEnvironment, aSourceContent); 3335cdf0e10cSrcweir aTargetContent.transferContent(aSourceContent, ::ucbhelper::InsertOperation_COPY, sTargetName, nNameClash); 3336cdf0e10cSrcweir } 3337cdf0e10cSrcweir catch(const css::uno::Exception&) 3338cdf0e10cSrcweir { return AutoRecovery::E_ORIGINAL_FILE_MISSING; } 3339cdf0e10cSrcweir 3340cdf0e10cSrcweir return AutoRecovery::E_COPIED; 3341cdf0e10cSrcweir } 3342cdf0e10cSrcweir 3343cdf0e10cSrcweir //----------------------------------------------- 3344cdf0e10cSrcweir sal_Bool SAL_CALL AutoRecovery::convertFastPropertyValue( css::uno::Any& /*aConvertedValue*/, 3345cdf0e10cSrcweir css::uno::Any& /*aOldValue*/ , 3346cdf0e10cSrcweir sal_Int32 /*nHandle*/ , 3347cdf0e10cSrcweir const css::uno::Any& /*aValue*/ ) 3348cdf0e10cSrcweir throw(css::lang::IllegalArgumentException) 3349cdf0e10cSrcweir { 3350cdf0e10cSrcweir // not needed currently 3351cdf0e10cSrcweir return sal_False; 3352cdf0e10cSrcweir } 3353cdf0e10cSrcweir 3354cdf0e10cSrcweir //----------------------------------------------- 3355cdf0e10cSrcweir void SAL_CALL AutoRecovery::setFastPropertyValue_NoBroadcast( sal_Int32 /*nHandle*/, 3356cdf0e10cSrcweir const css::uno::Any& /*aValue*/ ) 3357cdf0e10cSrcweir throw(css::uno::Exception) 3358cdf0e10cSrcweir { 3359cdf0e10cSrcweir // not needed currently 3360cdf0e10cSrcweir } 3361cdf0e10cSrcweir 3362cdf0e10cSrcweir //----------------------------------------------- 3363cdf0e10cSrcweir void SAL_CALL AutoRecovery::getFastPropertyValue(css::uno::Any& aValue , 3364cdf0e10cSrcweir sal_Int32 nHandle) const 3365cdf0e10cSrcweir { 3366cdf0e10cSrcweir switch(nHandle) 3367cdf0e10cSrcweir { 3368cdf0e10cSrcweir case AUTORECOVERY_PROPHANDLE_EXISTS_RECOVERYDATA : 3369cdf0e10cSrcweir { 3370cdf0e10cSrcweir sal_Bool bSessionData = sal_False; 3371cdf0e10cSrcweir ::comphelper::ConfigurationHelper::readDirectKey( 3372cdf0e10cSrcweir m_xSMGR, 3373cdf0e10cSrcweir CFG_PACKAGE_RECOVERY, 3374cdf0e10cSrcweir CFG_PATH_RECOVERYINFO, 3375cdf0e10cSrcweir CFG_ENTRY_SESSIONDATA, 3376cdf0e10cSrcweir ::comphelper::ConfigurationHelper::E_READONLY) >>= bSessionData; 3377cdf0e10cSrcweir 3378cdf0e10cSrcweir sal_Bool bRecoveryData = ((sal_Bool)(m_lDocCache.size()>0)); 3379cdf0e10cSrcweir 338007a3d7f1SPedro Giffuni // exists session data ... => then we can't say, that these 3381cdf0e10cSrcweir // data are valid for recovery. So we have to return sal_False then! 3382cdf0e10cSrcweir if (bSessionData) 3383cdf0e10cSrcweir bRecoveryData = sal_False; 3384cdf0e10cSrcweir 3385cdf0e10cSrcweir aValue <<= bRecoveryData; 3386cdf0e10cSrcweir } 3387cdf0e10cSrcweir break; 3388cdf0e10cSrcweir 3389cdf0e10cSrcweir case AUTORECOVERY_PROPHANDLE_CRASHED : 3390cdf0e10cSrcweir aValue = ::comphelper::ConfigurationHelper::readDirectKey( 3391cdf0e10cSrcweir m_xSMGR, 3392cdf0e10cSrcweir CFG_PACKAGE_RECOVERY, 3393cdf0e10cSrcweir CFG_PATH_RECOVERYINFO, 3394cdf0e10cSrcweir CFG_ENTRY_CRASHED, 3395cdf0e10cSrcweir ::comphelper::ConfigurationHelper::E_READONLY); 3396cdf0e10cSrcweir break; 3397cdf0e10cSrcweir 3398cdf0e10cSrcweir case AUTORECOVERY_PROPHANDLE_EXISTS_SESSIONDATA : 3399cdf0e10cSrcweir aValue = ::comphelper::ConfigurationHelper::readDirectKey( 3400cdf0e10cSrcweir m_xSMGR, 3401cdf0e10cSrcweir CFG_PACKAGE_RECOVERY, 3402cdf0e10cSrcweir CFG_PATH_RECOVERYINFO, 3403cdf0e10cSrcweir CFG_ENTRY_SESSIONDATA, 3404cdf0e10cSrcweir ::comphelper::ConfigurationHelper::E_READONLY); 3405cdf0e10cSrcweir break; 3406cdf0e10cSrcweir } 3407cdf0e10cSrcweir } 3408cdf0e10cSrcweir 3409cdf0e10cSrcweir //----------------------------------------------- 3410cdf0e10cSrcweir const css::uno::Sequence< css::beans::Property > impl_getStaticPropertyDescriptor() 3411cdf0e10cSrcweir { 3412cdf0e10cSrcweir static const css::beans::Property pPropertys[] = 3413cdf0e10cSrcweir { 3414cdf0e10cSrcweir css::beans::Property( AUTORECOVERY_PROPNAME_CRASHED , AUTORECOVERY_PROPHANDLE_CRASHED , ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ), 3415cdf0e10cSrcweir css::beans::Property( AUTORECOVERY_PROPNAME_EXISTS_RECOVERYDATA, AUTORECOVERY_PROPHANDLE_EXISTS_RECOVERYDATA, ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ), 3416cdf0e10cSrcweir css::beans::Property( AUTORECOVERY_PROPNAME_EXISTS_SESSIONDATA , AUTORECOVERY_PROPHANDLE_EXISTS_SESSIONDATA , ::getBooleanCppuType() , css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ), 3417cdf0e10cSrcweir }; 3418cdf0e10cSrcweir static const css::uno::Sequence< css::beans::Property > lPropertyDescriptor(pPropertys, AUTORECOVERY_PROPCOUNT); 3419cdf0e10cSrcweir return lPropertyDescriptor; 3420cdf0e10cSrcweir } 3421cdf0e10cSrcweir 3422cdf0e10cSrcweir //----------------------------------------------- 3423cdf0e10cSrcweir ::cppu::IPropertyArrayHelper& SAL_CALL AutoRecovery::getInfoHelper() 3424cdf0e10cSrcweir { 3425cdf0e10cSrcweir static ::cppu::OPropertyArrayHelper* pInfoHelper = 0; 3426cdf0e10cSrcweir if(!pInfoHelper) 3427cdf0e10cSrcweir { 3428cdf0e10cSrcweir ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); 3429cdf0e10cSrcweir if(!pInfoHelper) 3430cdf0e10cSrcweir { 3431cdf0e10cSrcweir static ::cppu::OPropertyArrayHelper aInfoHelper(impl_getStaticPropertyDescriptor(), sal_True); 3432cdf0e10cSrcweir pInfoHelper = &aInfoHelper; 3433cdf0e10cSrcweir } 3434cdf0e10cSrcweir } 3435cdf0e10cSrcweir 3436cdf0e10cSrcweir return (*pInfoHelper); 3437cdf0e10cSrcweir } 3438cdf0e10cSrcweir 3439cdf0e10cSrcweir //----------------------------------------------- 3440cdf0e10cSrcweir css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL AutoRecovery::getPropertySetInfo() 3441cdf0e10cSrcweir throw(css::uno::RuntimeException) 3442cdf0e10cSrcweir { 3443cdf0e10cSrcweir static css::uno::Reference< css::beans::XPropertySetInfo >* pInfo = 0; 3444cdf0e10cSrcweir if(!pInfo) 3445cdf0e10cSrcweir { 3446cdf0e10cSrcweir ::osl::MutexGuard aGuard( LockHelper::getGlobalLock().getShareableOslMutex() ); 3447cdf0e10cSrcweir if(!pInfo) 3448cdf0e10cSrcweir { 3449cdf0e10cSrcweir static css::uno::Reference< css::beans::XPropertySetInfo > xInfo(createPropertySetInfo(getInfoHelper())); 3450cdf0e10cSrcweir pInfo = &xInfo; 3451cdf0e10cSrcweir } 3452cdf0e10cSrcweir } 3453cdf0e10cSrcweir 3454cdf0e10cSrcweir return (*pInfo); 3455cdf0e10cSrcweir } 3456cdf0e10cSrcweir 3457cdf0e10cSrcweir //----------------------------------------------- 3458cdf0e10cSrcweir void AutoRecovery::implts_verifyCacheAgainstDesktopDocumentList() 3459cdf0e10cSrcweir { 3460cdf0e10cSrcweir LOG_RECOVERY("AutoRecovery::implts_verifyCacheAgainstDesktopDocumentList() ...") 3461cdf0e10cSrcweir 3462cdf0e10cSrcweir // SAFE -> ---------------------------------- 3463cdf0e10cSrcweir WriteGuard aWriteLock(m_aLock); 3464cdf0e10cSrcweir css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; 3465cdf0e10cSrcweir aWriteLock.unlock(); 3466cdf0e10cSrcweir // <- SAFE ---------------------------------- 3467cdf0e10cSrcweir 3468cdf0e10cSrcweir try 3469cdf0e10cSrcweir { 3470cdf0e10cSrcweir css::uno::Reference< css::frame::XFramesSupplier > xDesktop( 3471cdf0e10cSrcweir xSMGR->createInstance(SERVICENAME_DESKTOP), 3472cdf0e10cSrcweir css::uno::UNO_QUERY_THROW); 3473cdf0e10cSrcweir 3474cdf0e10cSrcweir css::uno::Reference< css::container::XIndexAccess > xContainer( 3475cdf0e10cSrcweir xDesktop->getFrames(), 3476cdf0e10cSrcweir css::uno::UNO_QUERY_THROW); 3477cdf0e10cSrcweir 3478cdf0e10cSrcweir sal_Int32 i = 0; 3479cdf0e10cSrcweir sal_Int32 c = xContainer->getCount(); 3480cdf0e10cSrcweir 3481cdf0e10cSrcweir for (i=0; i<c; ++i) 3482cdf0e10cSrcweir { 3483cdf0e10cSrcweir css::uno::Reference< css::frame::XFrame > xFrame; 3484cdf0e10cSrcweir try 3485cdf0e10cSrcweir { 3486cdf0e10cSrcweir xContainer->getByIndex(i) >>= xFrame; 3487cdf0e10cSrcweir if (!xFrame.is()) 3488cdf0e10cSrcweir continue; 3489cdf0e10cSrcweir } 3490cdf0e10cSrcweir // can happen in multithreaded environments, that frames was removed from the container during this loop runs! 3491cdf0e10cSrcweir // Ignore it. 3492cdf0e10cSrcweir catch(const css::lang::IndexOutOfBoundsException&) 3493cdf0e10cSrcweir { continue; } 3494cdf0e10cSrcweir 3495cdf0e10cSrcweir // We are interested on visible documents only. 3496cdf0e10cSrcweir // Note: It's n optional interface .-( 3497cdf0e10cSrcweir css::uno::Reference< css::awt::XWindow2 > xVisibleCheck( 3498cdf0e10cSrcweir xFrame->getContainerWindow(), 3499cdf0e10cSrcweir css::uno::UNO_QUERY); 3500cdf0e10cSrcweir if ( 3501cdf0e10cSrcweir (!xVisibleCheck.is() ) || 3502cdf0e10cSrcweir (!xVisibleCheck->isVisible()) 3503cdf0e10cSrcweir ) 3504cdf0e10cSrcweir { 3505cdf0e10cSrcweir continue; 3506cdf0e10cSrcweir } 3507cdf0e10cSrcweir 3508cdf0e10cSrcweir // extract the model from the frame. 3509cdf0e10cSrcweir // Ignore "view only" frames, which does not have a model. 3510cdf0e10cSrcweir css::uno::Reference< css::frame::XController > xController; 3511cdf0e10cSrcweir css::uno::Reference< css::frame::XModel > xModel; 3512cdf0e10cSrcweir 3513cdf0e10cSrcweir xController = xFrame->getController(); 3514cdf0e10cSrcweir if (xController.is()) 3515cdf0e10cSrcweir xModel = xController->getModel(); 3516cdf0e10cSrcweir if (!xModel.is()) 3517cdf0e10cSrcweir continue; 3518cdf0e10cSrcweir 3519cdf0e10cSrcweir // insert model into cache ... 3520cdf0e10cSrcweir // If the model is already well known inside cache 3521cdf0e10cSrcweir // it's information set will be updated by asking the 3522cdf0e10cSrcweir // model again for it's new states. 3523cdf0e10cSrcweir implts_registerDocument(xModel); 3524cdf0e10cSrcweir } 3525cdf0e10cSrcweir } 3526cdf0e10cSrcweir catch(const css::uno::RuntimeException& exRun) 3527cdf0e10cSrcweir { throw exRun; } 3528cdf0e10cSrcweir catch(const css::uno::Exception&) 3529cdf0e10cSrcweir {} 3530cdf0e10cSrcweir 3531cdf0e10cSrcweir LOG_RECOVERY("... AutoRecovery::implts_verifyCacheAgainstDesktopDocumentList()") 3532cdf0e10cSrcweir } 3533cdf0e10cSrcweir 3534cdf0e10cSrcweir //----------------------------------------------- 3535cdf0e10cSrcweir sal_Bool AutoRecovery::impl_enoughDiscSpace(sal_Int32 nRequiredSpace) 3536cdf0e10cSrcweir { 3537cdf0e10cSrcweir #ifdef SIMULATE_FULL_DISC 3538cdf0e10cSrcweir return sal_False; 3539cdf0e10cSrcweir #endif 3540cdf0e10cSrcweir 354130acf5e8Spfg // In case an error occurs and we are not able to retrieve the needed information 3542cdf0e10cSrcweir // it's better to "disable" the feature ShowErrorOnFullDisc ! 35434e7d57d8Smseidel // Otherwise we start a confusing process of error handling ... 3544cdf0e10cSrcweir 3545cdf0e10cSrcweir sal_uInt64 nFreeSpace = SAL_MAX_UINT64; 3546cdf0e10cSrcweir 3547cdf0e10cSrcweir ::rtl::OUString sBackupPath(SvtPathOptions().GetBackupPath()); 3548cdf0e10cSrcweir ::osl::VolumeInfo aInfo (VolumeInfoMask_FreeSpace); 3549cdf0e10cSrcweir ::osl::FileBase::RC aRC = ::osl::Directory::getVolumeInfo(sBackupPath, aInfo); 3550cdf0e10cSrcweir 3551cdf0e10cSrcweir if ( 3552cdf0e10cSrcweir (aInfo.isValid(VolumeInfoMask_FreeSpace)) && 3553cdf0e10cSrcweir (aRC == ::osl::FileBase::E_None ) 3554cdf0e10cSrcweir ) 3555cdf0e10cSrcweir { 3556cdf0e10cSrcweir nFreeSpace = aInfo.getFreeSpace(); 3557cdf0e10cSrcweir } 3558cdf0e10cSrcweir 3559cdf0e10cSrcweir sal_uInt64 nFreeMB = (nFreeSpace/1048576); 3560cdf0e10cSrcweir return (nFreeMB >= (sal_uInt64)nRequiredSpace); 3561cdf0e10cSrcweir } 3562cdf0e10cSrcweir 3563cdf0e10cSrcweir //----------------------------------------------- 3564cdf0e10cSrcweir void AutoRecovery::impl_showFullDiscError() 3565cdf0e10cSrcweir { 3566cdf0e10cSrcweir static String PLACEHOLDER_PATH = String::CreateFromAscii("%PATH"); 3567cdf0e10cSrcweir 3568cdf0e10cSrcweir String sBtn(FwkResId(STR_FULL_DISC_RETRY_BUTTON)); 3569cdf0e10cSrcweir String sMsg(FwkResId(STR_FULL_DISC_MSG )); 3570cdf0e10cSrcweir 3571cdf0e10cSrcweir String sBackupURL(SvtPathOptions().GetBackupPath()); 3572cdf0e10cSrcweir INetURLObject aConverter(sBackupURL); 3573cdf0e10cSrcweir sal_Unicode aDelimiter; 3574cdf0e10cSrcweir String sBackupPath = aConverter.getFSysPath(INetURLObject::FSYS_DETECT, &aDelimiter); 3575cdf0e10cSrcweir if (sBackupPath.Len()<1) 3576cdf0e10cSrcweir sBackupPath = sBackupURL; 3577cdf0e10cSrcweir sMsg.SearchAndReplace(PLACEHOLDER_PATH, sBackupPath); 3578cdf0e10cSrcweir 3579cdf0e10cSrcweir ErrorBox dlgError(0, WB_OK, sMsg); 3580cdf0e10cSrcweir dlgError.SetButtonText(dlgError.GetButtonId(0), sBtn); 3581cdf0e10cSrcweir dlgError.Execute(); 3582cdf0e10cSrcweir } 3583cdf0e10cSrcweir 3584cdf0e10cSrcweir //----------------------------------------------- 3585cdf0e10cSrcweir void AutoRecovery::impl_establishProgress(const AutoRecovery::TDocumentInfo& rInfo , 3586cdf0e10cSrcweir ::comphelper::MediaDescriptor& rArgs , 3587cdf0e10cSrcweir const css::uno::Reference< css::frame::XFrame >& xNewFrame) 3588cdf0e10cSrcweir { 3589cdf0e10cSrcweir // external well known frame must be preferred (because it was created by ourself 3590cdf0e10cSrcweir // for loading documents into this frame)! 3591cdf0e10cSrcweir // But if no frame exists ... we can try to locate it using any frame bound to the provided 3592cdf0e10cSrcweir // document. Of course we must live without any frame in case the document does not exists at this 359330acf5e8Spfg // point. But this state shouldn't occur. In such case xNewFrame should be valid ... hopefully .-) 3594cdf0e10cSrcweir css::uno::Reference< css::frame::XFrame > xFrame = xNewFrame; 3595cdf0e10cSrcweir if ( 3596cdf0e10cSrcweir (!xFrame.is() ) && 3597cdf0e10cSrcweir (rInfo.Document.is()) 3598cdf0e10cSrcweir ) 3599cdf0e10cSrcweir { 3600cdf0e10cSrcweir css::uno::Reference< css::frame::XController > xController = rInfo.Document->getCurrentController(); 3601cdf0e10cSrcweir if (xController.is()) 3602cdf0e10cSrcweir xFrame = xController->getFrame(); 3603cdf0e10cSrcweir } 3604cdf0e10cSrcweir 3605cdf0e10cSrcweir // Any outside progress must be used ... 3606cdf0e10cSrcweir // Only if there is no progress, we can create our own one. 3607cdf0e10cSrcweir css::uno::Reference< css::task::XStatusIndicator > xInternalProgress; 3608cdf0e10cSrcweir css::uno::Reference< css::task::XStatusIndicator > xExternalProgress = rArgs.getUnpackedValueOrDefault( 3609cdf0e10cSrcweir ::comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), 3610cdf0e10cSrcweir css::uno::Reference< css::task::XStatusIndicator >() ); 3611cdf0e10cSrcweir 3612e9faf1d9Smseidel // Normally a progress is set from outside (e.g. by the CrashSave/Recovery dialog, which uses our dispatch API). 3613cdf0e10cSrcweir // But for a normal auto save we dont have such "external progress"... because this function is triggered by our own timer then. 3614cdf0e10cSrcweir // In such case we must create our own progress ! 3615cdf0e10cSrcweir if ( 3616cdf0e10cSrcweir (! xExternalProgress.is()) && 3617cdf0e10cSrcweir (xFrame.is() ) 3618cdf0e10cSrcweir ) 3619cdf0e10cSrcweir { 3620cdf0e10cSrcweir css::uno::Reference< css::task::XStatusIndicatorFactory > xProgressFactory(xFrame, css::uno::UNO_QUERY); 3621cdf0e10cSrcweir if (xProgressFactory.is()) 3622cdf0e10cSrcweir xInternalProgress = xProgressFactory->createStatusIndicator(); 3623cdf0e10cSrcweir } 3624cdf0e10cSrcweir 3625cdf0e10cSrcweir // HACK 3626cdf0e10cSrcweir // An external provided progress (most given by the CrashSave/Recovery dialog) 3627cdf0e10cSrcweir // must be preferred. But we know that some application filters query it's own progress instance 3628cdf0e10cSrcweir // at the frame method Frame::createStatusIndicator(). 3629cdf0e10cSrcweir // So we use a two step mechanism: 3630cdf0e10cSrcweir // 1) we set the progress inside the MediaDescriptor, which will be provided to the filter 3631cdf0e10cSrcweir // 2) and we set a special Frame property, which overwrites the normal behaviour of Frame::createStatusIndicator .-) 363207a3d7f1SPedro Giffuni // But we suppress 2) in case we uses an internal progress. Because then it doesn't matter 3633cdf0e10cSrcweir // if our applications make it wrong. In such case the internal progress resists at the same frame 3634cdf0e10cSrcweir // and there is no need to forward progress activities to e.g. an outside dialog .-) 3635cdf0e10cSrcweir if ( 3636cdf0e10cSrcweir (xExternalProgress.is()) && 3637cdf0e10cSrcweir (xFrame.is() ) 3638cdf0e10cSrcweir ) 3639cdf0e10cSrcweir { 3640cdf0e10cSrcweir css::uno::Reference< css::beans::XPropertySet > xFrameProps(xFrame, css::uno::UNO_QUERY); 3641cdf0e10cSrcweir if (xFrameProps.is()) 3642cdf0e10cSrcweir xFrameProps->setPropertyValue(FRAME_PROPNAME_INDICATORINTERCEPTION, css::uno::makeAny(xExternalProgress)); 3643cdf0e10cSrcweir } 3644cdf0e10cSrcweir 3645cdf0e10cSrcweir // But inside the MediaDescriptor we must set our own create progress ... 3646cdf0e10cSrcweir // in case there is not already anothe rprogress set. 3647cdf0e10cSrcweir rArgs.createItemIfMissing(::comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), xInternalProgress); 3648cdf0e10cSrcweir } 3649cdf0e10cSrcweir 3650cdf0e10cSrcweir //----------------------------------------------- 3651cdf0e10cSrcweir void AutoRecovery::impl_forgetProgress(const AutoRecovery::TDocumentInfo& rInfo , 3652cdf0e10cSrcweir ::comphelper::MediaDescriptor& rArgs , 3653cdf0e10cSrcweir const css::uno::Reference< css::frame::XFrame >& xNewFrame) 3654cdf0e10cSrcweir { 3655cdf0e10cSrcweir // external well known frame must be preferred (because it was created by ourself 3656cdf0e10cSrcweir // for loading documents into this frame)! 3657cdf0e10cSrcweir // But if no frame exists ... we can try to locate it using any frame bound to the provided 3658cdf0e10cSrcweir // document. Of course we must live without any frame in case the document does not exists at this 365930acf5e8Spfg // point. But this state shouldn't occur. In such case xNewFrame should be valid ... hopefully .-) 3660cdf0e10cSrcweir css::uno::Reference< css::frame::XFrame > xFrame = xNewFrame; 3661cdf0e10cSrcweir if ( 3662cdf0e10cSrcweir (!xFrame.is() ) && 3663cdf0e10cSrcweir (rInfo.Document.is()) 3664cdf0e10cSrcweir ) 3665cdf0e10cSrcweir { 3666cdf0e10cSrcweir css::uno::Reference< css::frame::XController > xController = rInfo.Document->getCurrentController(); 3667cdf0e10cSrcweir if (xController.is()) 3668cdf0e10cSrcweir xFrame = xController->getFrame(); 3669cdf0e10cSrcweir } 3670cdf0e10cSrcweir 3671cdf0e10cSrcweir // stop progress interception on corresponding frame. 3672cdf0e10cSrcweir css::uno::Reference< css::beans::XPropertySet > xFrameProps(xFrame, css::uno::UNO_QUERY); 3673cdf0e10cSrcweir if (xFrameProps.is()) 3674cdf0e10cSrcweir xFrameProps->setPropertyValue(FRAME_PROPNAME_INDICATORINTERCEPTION, css::uno::makeAny(css::uno::Reference< css::task::XStatusIndicator >())); 3675cdf0e10cSrcweir 3676cdf0e10cSrcweir // forget progress inside list of arguments. 3677cdf0e10cSrcweir ::comphelper::MediaDescriptor::iterator pArg = rArgs.find(::comphelper::MediaDescriptor::PROP_STATUSINDICATOR()); 3678cdf0e10cSrcweir if (pArg != rArgs.end()) 3679cdf0e10cSrcweir { 3680cdf0e10cSrcweir rArgs.erase(pArg); 3681cdf0e10cSrcweir pArg = rArgs.end(); 3682cdf0e10cSrcweir } 3683cdf0e10cSrcweir } 3684cdf0e10cSrcweir 3685cdf0e10cSrcweir //----------------------------------------------- 3686cdf0e10cSrcweir void AutoRecovery::impl_flushALLConfigChanges() 3687cdf0e10cSrcweir { 3688cdf0e10cSrcweir try 3689cdf0e10cSrcweir { 3690cdf0e10cSrcweir // SAFE -> 3691cdf0e10cSrcweir ReadGuard aReadLock(m_aLock); 3692cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface > xRecoveryCfg(m_xRecoveryCFG, css::uno::UNO_QUERY); 3693cdf0e10cSrcweir aReadLock.unlock(); 3694cdf0e10cSrcweir // <- SAFE 3695cdf0e10cSrcweir 3696cdf0e10cSrcweir if (xRecoveryCfg.is()) 3697cdf0e10cSrcweir ::comphelper::ConfigurationHelper::flush(xRecoveryCfg); 3698cdf0e10cSrcweir 3699cdf0e10cSrcweir // SOLAR SAFE -> 3700cdf0e10cSrcweir ::vos::OGuard aGuard( Application::GetSolarMutex() ); 3701cdf0e10cSrcweir ::utl::ConfigManager* pCfgMgr = ::utl::ConfigManager::GetConfigManager(); 3702cdf0e10cSrcweir if (pCfgMgr) 3703cdf0e10cSrcweir pCfgMgr->StoreConfigItems(); 3704cdf0e10cSrcweir } 3705cdf0e10cSrcweir catch(const css::uno::Exception&) 3706cdf0e10cSrcweir {} 3707cdf0e10cSrcweir } 3708cdf0e10cSrcweir 3709cdf0e10cSrcweir //----------------------------------------------- 3710cdf0e10cSrcweir void AutoRecovery::st_impl_removeFile(const ::rtl::OUString& sURL) 3711cdf0e10cSrcweir { 3712cdf0e10cSrcweir if ( ! sURL.getLength()) 3713cdf0e10cSrcweir return; 3714cdf0e10cSrcweir 3715cdf0e10cSrcweir try 3716cdf0e10cSrcweir { 3717cdf0e10cSrcweir ::ucbhelper::Content aContent = ::ucbhelper::Content(sURL, css::uno::Reference< css::ucb::XCommandEnvironment >()); 3718cdf0e10cSrcweir aContent.executeCommand(::rtl::OUString::createFromAscii("delete"), css::uno::makeAny(sal_True)); 3719cdf0e10cSrcweir } 3720cdf0e10cSrcweir catch(const css::uno::Exception&) 3721cdf0e10cSrcweir {} 3722cdf0e10cSrcweir } 3723cdf0e10cSrcweir 3724cdf0e10cSrcweir //----------------------------------------------- 3725cdf0e10cSrcweir void AutoRecovery::st_impl_removeLockFile() 3726cdf0e10cSrcweir { 3727cdf0e10cSrcweir try 3728cdf0e10cSrcweir { 3729cdf0e10cSrcweir ::rtl::OUString sUserURL; 3730cdf0e10cSrcweir ::utl::Bootstrap::locateUserInstallation( sUserURL ); 3731cdf0e10cSrcweir 3732cdf0e10cSrcweir ::rtl::OUStringBuffer sLockURLBuf; 3733cdf0e10cSrcweir sLockURLBuf.append (sUserURL); 3734cdf0e10cSrcweir sLockURLBuf.appendAscii("/.lock"); 3735cdf0e10cSrcweir ::rtl::OUString sLockURL = sLockURLBuf.makeStringAndClear(); 3736cdf0e10cSrcweir 3737cdf0e10cSrcweir AutoRecovery::st_impl_removeFile(sLockURL); 3738cdf0e10cSrcweir } 3739cdf0e10cSrcweir catch(const css::uno::Exception&) 3740cdf0e10cSrcweir {} 3741cdf0e10cSrcweir } 3742cdf0e10cSrcweir 3743cdf0e10cSrcweir } // namespace framework 3744