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