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