xref: /AOO41X/main/framework/source/services/autorecovery.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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