LCOV - code coverage report
Current view: top level - framework/source/services - autorecovery.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 182 1420 12.8 %
Date: 2012-08-25 Functions: 26 99 26.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 185 3036 6.1 %

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

Generated by: LCOV version 1.10