1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#ifndef __FRAMEWORK_SERVICES_AUTORECOVERY_HXX_
#define __FRAMEWORK_SERVICES_AUTORECOVERY_HXX_
//_______________________________________________
// own includes
#include <threadhelp/threadhelpbase.hxx>
#include <macros/xinterface.hxx>
#include <macros/xtypeprovider.hxx>
#include <macros/xserviceinfo.hxx>
#include <general.h>
#include <stdtypes.h>
//_______________________________________________
// interface includes
#include <com/sun/star/uno/XInterface.hpp>
#include <com/sun/star/lang/XTypeProvider.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/frame/XDispatch.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/document/XEventListener.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/util/XChangesListener.hpp>
#include <com/sun/star/task/XStatusIndicator.hpp>
#include <com/sun/star/util/XModifyListener.hpp>
//_______________________________________________
// other includes
#include <comphelper/mediadescriptor.hxx>
#include <vcl/timer.hxx>
#include <vcl/evntpost.hxx>
#include <cppuhelper/interfacecontainer.hxx>
#include <cppuhelper/propshlp.hxx>
#include <cppuhelper/weak.hxx>
//_______________________________________________
// definition
#ifndef css
namespace css = ::com::sun::star;
#endif
namespace framework
{
//---------------------------------------
/** @short hold all needed informations for an asynchronous dispatch alive.
@descr Because some operations are forced to be executed asynchronously
(e.g. requested by our CreashSave/Recovery dialog) ... we must make sure
that these informations wont be set as "normal" members of our AtoRecovery
instance. Otherwise they can disturb our normal AutoSave-timer handling.
e.g. it can be unclear then, which progress has to be used for storing documents ...
*/
struct DispatchParams
{
public:
DispatchParams();
DispatchParams(const ::comphelper::SequenceAsHashMap& lArgs ,
const css::uno::Reference< css::uno::XInterface >& xOwner);
DispatchParams(const DispatchParams& rCopy);
~DispatchParams();
DispatchParams& operator=(const DispatchParams& rCopy);
void forget();
public:
//---------------------------------------
/** @short can be set from outside and is provided to
our internal started operations.
@descr Normaly we use the normal status indicator
of the document windows to show a progress.
But in case we are used by any special UI,
it can provide its own status indicator object
to us - so we use it instead of the normal one.
*/
css::uno::Reference< css::task::XStatusIndicator > m_xProgress;
//---------------------------------------
/** TODO document me */
::rtl::OUString m_sSavePath;
//---------------------------------------
/** @short define the current cache entry, which should be used for current
backup or cleanUp operation ... which is may be done asynchronous */
sal_Int32 m_nWorkingEntryID;
//---------------------------------------
/** @short used for asyncoperations, to prevent us from dying.
@descr If our dispatch() method was forced to start the
internal operation asynchronous ... we send an event
to start and return immediatly. But we must be shure that
our instance live if the event callback reach us.
So we hold an uno reference to ourself.
*/
css::uno::Reference< css::uno::XInterface > m_xHoldRefForAsyncOpAlive;
};
//_______________________________________________
/**
implements the functionality of AutoSave and AutoRecovery
of documents - including features of an EmergencySave in
case a GPF occures.
*/
class AutoRecovery : public css::lang::XTypeProvider
, public css::lang::XServiceInfo
, public css::frame::XDispatch
, public css::document::XEventListener // => css.lang.XEventListener
, public css::util::XChangesListener // => css.lang.XEventListener
, public css::util::XModifyListener // => css.lang.XEventListener
// attention! Must be the first base class to guarentee right initialize lock ...
, private ThreadHelpBase
, public ::cppu::OBroadcastHelper
, public ::cppu::OPropertySetHelper // => XPropertySet, XFastPropertySet, XMultiPropertySet
, public ::cppu::OWeakObject
{
//___________________________________________
// types
public:
/** These values are used as flags and represent the current state of a document.
Every state of the life time of a document has to be recognized here.
@attention Do not change (means reorganize) already used numbers.
There exists some code inside SVX, which uses the same numbers,
to analyze such document states.
Not the best design ... but may be it will be changed later .-)
*/
enum EDocStates
{
/* TEMP STATES */
/// default state, if a document was new created or loaded
E_UNKNOWN = 0,
/// modified against the original file
E_MODIFIED = 1,
/// an active document can be postponed to be saved later.
E_POSTPONED = 2,
/// was already handled during one AutoSave/Recovery session.
E_HANDLED = 4,
/** an action was started (saving/loading) ... Can be interesting later if the process may be was interrupted by an exception. */
E_TRY_SAVE = 8,
E_TRY_LOAD_BACKUP = 16,
E_TRY_LOAD_ORIGINAL = 32,
/* FINAL STATES */
/// the Auto/Emergency saved document isnt useable any longer
E_DAMAGED = 64,
/// the Auto/Emergency saved document isnt realy up-to-date (some changes can be missing)
E_INCOMPLETE = 128,
/// the Auto/Emergency saved document was processed successfully
E_SUCCEDED = 512
};
/** @short indicates the results of a FAILURE_SAFE operation
@descr We must know, which reason was the real one in case
we couldnt copy a "failure document" to a user specified path.
We must know, if we can forget our cache entry or not.
*/
enum EFailureSafeResult
{
E_COPIED,
E_ORIGINAL_FILE_MISSING,
E_WRONG_TARGET_PATH
};
// TODO document me
enum ETimerType
{
/** the timer shouldnt be used next time */
E_DONT_START_TIMER,
/** timer (was/must be) started with normal AutoSaveTimeIntervall */
E_NORMAL_AUTOSAVE_INTERVALL,
/** timer must be started with special short time intervall,
to poll for an user idle period */
E_POLL_FOR_USER_IDLE,
/** timer mst be started with a very(!) short time intervall,
to poll for the end of an user action, which does not allow saving documents in general */
E_POLL_TILL_AUTOSAVE_IS_ALLOWED,
/** dont start the timer - but calls the same action then before immediatly again! */
E_CALL_ME_BACK
};
// TODO document me ... flag field
// Emergency_Save and Recovery overwrites Auto_Save!
enum EJob
{
E_NO_JOB = 0,
E_AUTO_SAVE = 1,
E_EMERGENCY_SAVE = 2,
E_RECOVERY = 4,
E_ENTRY_BACKUP = 8,
E_ENTRY_CLEANUP = 16,
E_PREPARE_EMERGENCY_SAVE = 32,
E_SESSION_SAVE = 64,
E_SESSION_RESTORE = 128,
E_DISABLE_AUTORECOVERY = 256,
E_SET_AUTOSAVE_STATE = 512,
E_SESSION_QUIET_QUIT = 1024
};
//---------------------------------------
/** @short combine different informations about one office document. */
struct TDocumentInfo
{
public:
//-------------------------------
TDocumentInfo()
: DocumentState (E_UNKNOWN)
, UsedForSaving (sal_False)
, ListenForModify (sal_False)
, IgnoreClosing (sal_False)
, ID (-1 )
{}
//-------------------------------
/** @short points to the document. */
css::uno::Reference< css::frame::XModel > Document;
//-------------------------------
/** @short knows, if the document is realy modified since the last autosave,
or was postponed, because it was an active one etcpp...
@descr Because we have no CHANGE TRACKING mechanism, based on office document,
we implements it by ourself. We listen for MODIFIED events
of each document and update this state flag here.
Further we postpone saving of active documents, e.g. if the user
works currently on it. We wait for an idle period then ...
*/
sal_Int32 DocumentState;
//-------------------------------
/** Because our applications not ready for concurrent save requests at the same time,
we have supress our own AutoSave for the moment, a document will be already saved
by others.
*/
sal_Bool UsedForSaving;
//-------------------------------
/** For every user action, which modifies a document (e.g. key input) we get
a notification as XModifyListener. That seams to be a "performance issue" .-)
So we decided to listen for such modify events only for the time in which the document
was stored as temp. file and was not modified again by the user.
*/
sal_Bool ListenForModify;
//-------------------------------
/** For SessionSave we must close all open documents by ourself.
But because we are listen for documents events, we get some ...
and deregister these documents from our configuration.
That's why we mark these documents as "Closed by ourself" so we can
ignore these "OnUnload" or disposing() events .-)
*/
sal_Bool IgnoreClosing;
//-------------------------------
/** TODO: document me */
::rtl::OUString OrgURL;
::rtl::OUString FactoryURL;
::rtl::OUString TemplateURL;
::rtl::OUString OldTempURL;
::rtl::OUString NewTempURL;
::rtl::OUString AppModule; // e.g. com.sun.star.text.TextDocument - used to identify app module
::rtl::OUString FactoryService; // the service to create a document of the module
::rtl::OUString RealFilter; // real filter, which was used at loading time
::rtl::OUString DefaultFilter; // supports saving of the default format without loosing data
::rtl::OUString Extension; // file extension of the default filter
::rtl::OUString Title; // can be used as "DisplayName" on every recovery UI!
::com::sun::star::uno::Sequence< ::rtl::OUString >
ViewNames; // names of the view which were active at emergency-save time
sal_Int32 ID;
};
//---------------------------------------
/** @short used to know every currently open document. */
typedef ::std::vector< TDocumentInfo > TDocumentList;
//___________________________________________
// member
private:
//---------------------------------------
/** @short the global uno service manager.
@descr Must be used to create own needed services.
*/
css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR;
//---------------------------------------
/** @short points to the underlying recovery configuration.
@descr This instance does not cache - it calls directly the
configuration API!
*/
css::uno::Reference< css::container::XNameAccess > m_xRecoveryCFG;
//---------------------------------------
/** @short proxy weak binding to forward Events to ourself without
an ownership cycle
*/
css::uno::Reference< css::util::XChangesListener > m_xRecoveryCFGListener;
//---------------------------------------
/** @short points to the used configuration package or.openoffice.Setup
@descr This instance does not cache - it calls directly the
configuration API!
*/
css::uno::Reference< css::container::XNameAccess > m_xModuleCFG;
//---------------------------------------
/** @short holds the global event broadcaster alive,
where we listen for new created documents.
*/
css::uno::Reference< css::document::XEventBroadcaster > m_xNewDocBroadcaster;
//---------------------------------------
/** @short proxy weak binding to forward Events to ourself without
an ownership cycle
*/
css::uno::Reference< css::document::XEventListener > m_xNewDocBroadcasterListener;
//---------------------------------------
/** @short because we stop/restart listening sometimes, it's a good idea to know
if we already registered as listener .-)
*/
sal_Bool m_bListenForDocEvents;
sal_Bool m_bListenForConfigChanges;
//---------------------------------------
/** @short specify the time intervall between two save actions.
@descr Time is measured in [min].
*/
sal_Int32 m_nAutoSaveTimeIntervall;
//---------------------------------------
/** @short for an asynchronous operation we must know, if there is
at least one running job (may be asynchronous!).
*/
sal_Int32 m_eJob;
//---------------------------------------
/** @short the timer, which is used to be informed about the next
saving time ...
*/
Timer m_aTimer;
//---------------------------------------
/** @short make our dispatch asynchronous ... if required to do so! */
::vcl::EventPoster m_aAsyncDispatcher;
//---------------------------------------
/** @see DispatchParams
*/
DispatchParams m_aDispatchParams;
//---------------------------------------
/** @short indicates, which time period is currently used by the
internal timer.
*/
ETimerType m_eTimerType;
//---------------------------------------
/** @short this cache is used to hold all informations about
recovery/emergency save documents alive.
*/
TDocumentList m_lDocCache;
//---------------------------------------
// TODO document me
sal_Int32 m_nIdPool;
//---------------------------------------
/** @short contains all status listener registered at this instance.
*/
ListenerHash m_lListener;
/** @descr This member is used to prevent us against re-entrance problems.
A mutex cant help to prevent us from concurrent using of members
inside the same thread. But e.g. our internaly used stl structures
are not threadsafe ... and furthermore they cant be used at the same time
for iteration and add/remove requests!
So we have to detect such states and ... show a warning.
May be there will be a better solution next time ... (copying the cache temp.
bevor using).
And further it's not possible to use a simple boolean value here.
Because if more then one operation iterates over the same stl container ...
(only to modify it's elements but dont add new or removing existing ones!)
it should be possible doing so. But we must guarantee that the last operation reset
this lock ... not the first one ! So we use a "ref count" mechanism for that."
*/
sal_Int32 m_nDocCacheLock;
/** @descr These members are used to check the minimum disc space, which must exists
to start the corresponding operation.
*/
sal_Int32 m_nMinSpaceDocSave;
sal_Int32 m_nMinSpaceConfigSave;
//---------------------------------------
/** @short special debug option to make testing faster.
@descr We dont interpret the timer unit as [min] ...
we use [ms] instead of that. Further we dont
wait 10 s for user idle ...
*/
#if OSL_DEBUG_LEVEL > 1
sal_Bool m_dbg_bMakeItFaster;
#endif
//---------------------------------------
// HACK ... TODO
css::uno::Reference< css::task::XStatusIndicator > m_xExternalProgress;
//___________________________________________
// interface
public:
AutoRecovery(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR);
virtual ~AutoRecovery( );
// XInterface, XTypeProvider, XServiceInfo
FWK_DECLARE_XINTERFACE
FWK_DECLARE_XTYPEPROVIDER
DECLARE_XSERVICEINFO
//---------------------------------------
// css.frame.XDispatch
virtual void SAL_CALL dispatch(const css::util::URL& aURL ,
const css::uno::Sequence< css::beans::PropertyValue >& lArguments)
throw(css::uno::RuntimeException);
virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener >& xListener,
const css::util::URL& aURL )
throw(css::uno::RuntimeException);
virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >& xListener,
const css::util::URL& aURL )
throw(css::uno::RuntimeException);
//---------------------------------------
// css.document.XEventListener
/** @short informs about created/opened documents.
@descr Every new opened/created document will be saved internaly
so it can be checked if its modified. This modified state
is used later to decide, if it must be saved or not.
@param aEvent
points to the new created/opened document.
*/
virtual void SAL_CALL notifyEvent(const css::document::EventObject& aEvent)
throw(css::uno::RuntimeException);
//---------------------------------------
// css.util.XChangesListener
virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent& aEvent)
throw(css::uno::RuntimeException);
//---------------------------------------
// css.util.XModifyListener
virtual void SAL_CALL modified(const css::lang::EventObject& aEvent)
throw(css::uno::RuntimeException);
//---------------------------------------
// css.lang.XEventListener
using cppu::OPropertySetHelper::disposing;
virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent)
throw(css::uno::RuntimeException);
//___________________________________________
// helper
protected:
//---------------------------------------
// OPropertySetHelper
virtual sal_Bool SAL_CALL convertFastPropertyValue( css::uno::Any& aConvertedValue,
css::uno::Any& aOldValue ,
sal_Int32 nHandle ,
const css::uno::Any& aValue )
throw(css::lang::IllegalArgumentException);
virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,
const css::uno::Any& aValue )
throw(css::uno::Exception);
using cppu::OPropertySetHelper::getFastPropertyValue;
virtual void SAL_CALL getFastPropertyValue(css::uno::Any& aValue ,
sal_Int32 nHandle) const;
virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo()
throw(css::uno::RuntimeException);
//___________________________________________
// helper
private:
//---------------------------------------
/** @short open the underlying configuration.
@descr This method must be called everytimes
a configuartion call is needed. Because
method works together with the member
m_xCFG, open it on demand and cache it
afterwards.
@return [com.sun.star.container.XNameAccess]
the configuration object
@throw [com.sun.star.uno.RuntimeException]
if config could not be opened successfully!
@threadsafe
*/
css::uno::Reference< css::container::XNameAccess > implts_openConfig();
//---------------------------------------
/** @short read the underlying configuration.
@descr After that we know the initial state - means:
- if AutoSave was enabled by the user
- which time intervall has to be used
- which recovery entries may already exists
@throw [com.sun.star.uno.RuntimeException]
if config could not be opened or readed successfully!
@threadsafe
*/
void implts_readConfig();
//---------------------------------------
/** @short read the underlying configuration...
@descr ... but only keys related to the AutoSave mechanism.
Means: State and Timer intervall.
E.g. the recovery list isnt adressed here.
@throw [com.sun.star.uno.RuntimeException]
if config could not be opened or readed successfully!
@threadsafe
*/
void implts_readAutoSaveConfig();
//---------------------------------------
// TODO document me
void implts_flushConfigItem(const AutoRecovery::TDocumentInfo& rInfo ,
sal_Bool bRemoveIt = sal_False);
//---------------------------------------
// TODO document me
void implts_startListening();
void implts_startModifyListeningOnDoc(AutoRecovery::TDocumentInfo& rInfo);
//---------------------------------------
// TODO document me
void implts_stopListening();
void implts_stopModifyListeningOnDoc(AutoRecovery::TDocumentInfo& rInfo);
//---------------------------------------
/** @short stops and may be(!) restarts the timer.
@descr A running timer is stopped everytimes here.
But starting depends from the different internal
timer variables (e.g. AutoSaveEnabled, AutoSaveTimeIntervall,
TimerType etcpp.)
@throw [com.sun.star.uno.RuntimeException]
if timer could not be stopped or started!
@threadsafe
*/
void implts_updateTimer();
//---------------------------------------
/** @short stop the timer.
@descr Double calls will be ignored - means we do
nothing here, if the timer is already disabled.
@throw [com.sun.star.uno.RuntimeException]
if timer could not be stopped!
@threadsafe
*/
void implts_stopTimer();
//---------------------------------------
/** @short callback of our internal timer.
*/
DECL_LINK(implts_timerExpired, void*);
//---------------------------------------
/** @short makes our dispatch() method asynchronous!
*/
DECL_LINK(implts_asyncDispatch, void*);
//---------------------------------------
/** @short implements the dispatch real. */
void implts_dispatch(const DispatchParams& aParams);
//---------------------------------------
/** @short validate new detected document and add it into the internal
document list.
@descr This method should be called only, if its clear that a new
document was opened/created during office runtime.
This method checks, if its a top level document (means not an embedded one).
Only such top level documents can be recognized by this auto save mechanism.
@param xDocument
the new document, which should be checked and registered.
@threadsafe
*/
void implts_registerDocument(const css::uno::Reference< css::frame::XModel >& xDocument);
//---------------------------------------
/** @short remove the specified document from our internal document list.
@param xDocument
the new document, which should be deregistered.
@param bStopListening
sal_False: must be used in case this method is called withion disposing() of the document,
where it make no sense to deregister our listener. The container dies ...
sal_True : must be used in case this method is used on "dergistration" of this document, where
we must deregister our listener .-)
@threadsafe
*/
void implts_deregisterDocument(const css::uno::Reference< css::frame::XModel >& xDocument ,
sal_Bool bStopListening = sal_True);
//---------------------------------------
// TODO document me
void implts_markDocumentModifiedAgainstLastBackup(const css::uno::Reference< css::frame::XModel >& xDocument);
//---------------------------------------
// TODO document me
void implts_updateModifiedState(const css::uno::Reference< css::frame::XModel >& xDocument);
//---------------------------------------
// TODO document me
void implts_updateDocumentUsedForSavingState(const css::uno::Reference< css::frame::XModel >& xDocument ,
sal_Bool bSaveInProgress);
//---------------------------------------
// TODO document me
void implts_markDocumentAsSaved(const css::uno::Reference< css::frame::XModel >& xDocument);
//---------------------------------------
/** @short search a document inside given list.
@param rList
reference to a vector, which can contain such
document.
@param xDocument
the document, which should be located inside the
given list.
@return [TDocumentList::iterator]
which points to the located document.
If document does not exists - its set to
rList.end()!
*/
static TDocumentList::iterator impl_searchDocument( AutoRecovery::TDocumentList& rList ,
const css::uno::Reference< css::frame::XModel >& xDocument);
//---------------------------------------
/** TODO document me */
void implts_changeAllDocVisibility(sal_Bool bVisible);
void implts_prepareSessionShutdown();
//---------------------------------------
/** @short save all current opened documents to a specific
backup directory.
@descr Only realy changed documents will be saved here.
Further this method returns a suggestion, if and how it should
be called again. May be some documents was not saved yet
and must wait for an user idle period ...
@param bAllowUserIdleLoop
Because this method is used for different uses cases, it must
know, which actions are allowed or not.
AUTO_SAVE =>
If a document is the most active one, saving it
will be postponed if there exists other unsaved
documents. This feature was implemented, because
we dont wish to disturb the user on it's work.
... bAllowUserIdleLoop should be set to sal_True
EMERGENCY_SAVE / SESSION_SAVE =>
Here we must finish our work ASAP! It's not allowed
to postpone any document.
... bAllowUserIdleLoop must(!) be set to sal_False
@param pParams
sometimes this method is required inside an external dispatch request.
The it contains some special environment variables, which overwrites
our normal environment.
AutoSave => pParams == 0
SessionSave/CrashSave => pParams != 0
@return A suggestion, how the timer (if its not already disabled!)
should be restarted to full fill the requirements.
@threadsafe
*/
AutoRecovery::ETimerType implts_saveDocs( sal_Bool bAllowUserIdleLoop,
sal_Bool bRemoveLockFiles,
const DispatchParams* pParams = 0);
//---------------------------------------
/** @short save one of the current documents to a specific
backup directory.
@descr It:
- defines a new(!) unique temp file name
- save the new temp file
- remove the old temp file
- patch the given info struct
- and return errors.
It does not:
- patch the configuration.
Note further: It paches the info struct
more then ones. E.g. the new temp URL is set
before the file is saved. And the old URL is removed
only if removing oft he old file was successfully.
If this method returns without an exception - everything
was OK. Otherwhise the info struct can be analyzed to
get more information, e.g. when the problem occures.
@param sBackupPath
the base path for saving such temp files.
@param rInfo
points to an informations structure, where
e.g. the document, its modified state, the count
of autosave-retries etcpp. exists.
Its used also to return the new temp file name
and some other state values!
@threadsafe
*/
void implts_saveOneDoc(const ::rtl::OUString& sBackupPath ,
AutoRecovery::TDocumentInfo& rInfo ,
const css::uno::Reference< css::task::XStatusIndicator >& xExternalProgress);
//---------------------------------------
/** @short recovery all documents, which was saved during
a crash before.
@return A suggestion, how this method must be called back!
@threadsafe
*/
AutoRecovery::ETimerType implts_openDocs(const DispatchParams& aParams);
//---------------------------------------
// TODO document me
void implts_openOneDoc(const ::rtl::OUString& sURL ,
::comphelper::MediaDescriptor& lDescriptor,
AutoRecovery::TDocumentInfo& rInfo );
//---------------------------------------
// TODO document me
void implts_generateNewTempURL(const ::rtl::OUString& sBackupPath ,
::comphelper::MediaDescriptor& rMediaDescriptor,
AutoRecovery::TDocumentInfo& rInfo );
//---------------------------------------
/** @short notifies all interested listener about the current state
of the currently running operation.
@descr We support different set's of functions. AUTO_SAVE, EMERGENCY_SAVE,
AUTO_RECOVERY, FAILURE_SAVE ... etcpp.
Listener can register itself for any type of supported
functionality ... but not for document URL's in special.
@param eJob
is used to know, which set of listener we must notify.
@param aEvent
describe the event more in detail.
@threadsafe
*/
void implts_informListener( sal_Int32 eJob ,
const css::frame::FeatureStateEvent& aEvent);
//---------------------------------------
/** short create a feature event struct, which can be send
to any interested listener.
@param eJob
describe the current running operation
AUTOSAVE, EMERGENCYSAVE, RECOVERY
@param sEventType
describe the type of this event
START, STOP, UPDATE
@param pInfo
if sOperation is an update, this parameter must be different from NULL
and is used to send informations regarding the current handled document.
@return [css::frame::FeatureStateEvent]
the event structure for sending.
*/
static css::frame::FeatureStateEvent implst_createFeatureStateEvent( sal_Int32 eJob ,
const ::rtl::OUString& sEventType,
AutoRecovery::TDocumentInfo* pInfo );
class ListenerInformer
{
private:
AutoRecovery &m_rRecovery;
sal_Int32 m_eJob;
bool m_bStopped;
public:
ListenerInformer(AutoRecovery &rRecovery, sal_Int32 eJob)
: m_rRecovery(rRecovery), m_eJob(eJob), m_bStopped(false)
{
}
void start();
void stop();
~ListenerInformer()
{
stop();
}
};
//---------------------------------------
// TODO document me
void implts_resetHandleStates(sal_Bool bLoadCache);
//---------------------------------------
// TODO document me
void implts_specifyDefaultFilterAndExtension(AutoRecovery::TDocumentInfo& rInfo);
//---------------------------------------
// TODO document me
void implts_specifyAppModuleAndFactory(AutoRecovery::TDocumentInfo& rInfo);
/** retrieves the names of all active views of the given document
@param rInfo
the document info, whose <code>Document</code> member must not be <NULL/>.
*/
void implts_collectActiveViewNames( AutoRecovery::TDocumentInfo& rInfo );
/** updates the configuration so that for all documents, their current view/names are stored
*/
void implts_persistAllActiveViewNames();
//---------------------------------------
// TODO document me
void implts_prepareEmergencySave();
//---------------------------------------
// TODO document me
void implts_doEmergencySave(const DispatchParams& aParams);
//---------------------------------------
// TODO document me
void implts_doRecovery(const DispatchParams& aParams);
//---------------------------------------
// TODO document me
void implts_doSessionSave(const DispatchParams& aParams);
//---------------------------------------
// TODO document me
void implts_doSessionQuietQuit(const DispatchParams& aParams);
//---------------------------------------
// TODO document me
void implts_doSessionRestore(const DispatchParams& aParams);
//---------------------------------------
// TODO document me
void implts_backupWorkingEntry(const DispatchParams& aParams);
//---------------------------------------
// TODO document me
void implts_cleanUpWorkingEntry(const DispatchParams& aParams);
//---------------------------------------
/** try to make sure that all changed config items (not our used
config access only) will be flushed back to disc.
E.g. our svtools::ConfigItems() has to be flushed explicitly .-(
Note: This method cant fail. Flushing of config entries is an
optional feature. Errors can be ignored.
*/
void impl_flushALLConfigChanges();
//---------------------------------------
// TODO document me
AutoRecovery::EFailureSafeResult implts_copyFile(const ::rtl::OUString& sSource ,
const ::rtl::OUString& sTargetPath,
const ::rtl::OUString& sTargetName);
//---------------------------------------
/** @short converts m_eJob into a job description, which
can be used to inform an outside listener
about the current running operation
@param eJob
describe the current running operation
AUTOSAVE, EMERGENCYSAVE, RECOVERY
@return [string]
a suitable job description of form:
vnd.sun.star.autorecovery:/do...
*/
static ::rtl::OUString implst_getJobDescription(sal_Int32 eJob);
//---------------------------------------
/** @short mape the given URL to an internal int representation.
@param aURL
the url, which describe the next starting or may be already running
operation.
@return [long]
the internal int representation
see enum EJob
*/
static sal_Int32 implst_classifyJob(const css::util::URL& aURL);
/// TODO
void implts_verifyCacheAgainstDesktopDocumentList();
/// TODO document me
sal_Bool impl_enoughDiscSpace(sal_Int32 nRequiredSpace);
/// TODO document me
static void impl_showFullDiscError();
//---------------------------------------
/** @short try to create/use a progress and set it inside the
environment.
@descr The problem behind: There exists different use case of this method.
a) An external progress is provided by our CrashSave or Recovery dialog.
b) We must create our own progress e.g. for an AutoSave
c) Sometimes our application filters dont use the progress
provided by the MediaDescriptor. They uses the Frame everytime to create
it's own progress. So we implemented a HACK for these and now we set
an InterceptedProgress there for the time WE use this frame for loading/storing documents .-)
@param xNewFrame
must be set only in case WE create a new frame (e.g. for loading documents
on session restore or recovery). Then search for a frame using rInfo.Document must
be supressed and xFrame must be preferred instead .-)
@param rInfo
used e.g. to find the frame corresponding to a document.
This frame must be used to create a new progress e.g. for an AutoSave.
@param rArgs
is used to set the new created progress as parameter on these set.
*/
void impl_establishProgress(const AutoRecovery::TDocumentInfo& rInfo ,
::comphelper::MediaDescriptor& rArgs ,
const css::uno::Reference< css::frame::XFrame >& xNewFrame);
void impl_forgetProgress(const AutoRecovery::TDocumentInfo& rInfo ,
::comphelper::MediaDescriptor& rArgs ,
const css::uno::Reference< css::frame::XFrame >& xNewFrame);
//---------------------------------------
/** try to remove the specified file from disc.
Every URL supported by our UCB component can be used here.
Further it doesnt matter if the file realy exists or not.
Because removing a non exsistent file will have the same
result at the end ... a non existing file .-)
On the other side removing of files from disc is an optional
feature. If we are not able doing so ... its not a real problem.
Ok - users disc place will be samller then ... but we should produce
a crash during crash save because we cant delete a temporary file only !
@param sURL
the url of the file, which should be removed.
*/
static void st_impl_removeFile(const ::rtl::OUString& sURL);
//---------------------------------------
/** try to remove ".lock" file from disc if office will be terminated
not using the offical way .-)
This method has to be handled "optional". So every error inside
has to be ignored ! This method CANT FAIL ... it can forget something only .-)
*/
static void st_impl_removeLockFile();
};
} // namespace framework
#endif // __FRAMEWORK_SERVICES_AUTORECOVERY_HXX_
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|