1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_unotools.hxx" 30 #include <unotools/desktopterminationobserver.hxx> 31 32 /** === begin UNO includes === **/ 33 #include <com/sun/star/frame/XTerminateListener.hpp> 34 #include <com/sun/star/frame/XDesktop.hpp> 35 /** === end UNO includes === **/ 36 #include <cppuhelper/implbase1.hxx> 37 #include <comphelper/processfactory.hxx> 38 39 #include <list> 40 41 //........................................................................ 42 namespace utl 43 { 44 //........................................................................ 45 46 using namespace ::com::sun::star::uno; 47 using namespace ::com::sun::star::lang; 48 using namespace ::com::sun::star::frame; 49 50 namespace 51 { 52 //................................................................ 53 typedef ::std::list< ITerminationListener* > Listeners; 54 55 struct ListenerAdminData 56 { 57 Listeners aListeners; 58 bool bAlreadyTerminated; 59 bool bCreatedAdapter; 60 61 ListenerAdminData() : bAlreadyTerminated( false ), bCreatedAdapter( false ) { } 62 }; 63 64 //................................................................ 65 ListenerAdminData& getListenerAdminData() 66 { 67 static ListenerAdminData s_aData; 68 return s_aData; 69 } 70 71 //================================================================ 72 //= OObserverImpl 73 //================================================================ 74 class OObserverImpl : public ::cppu::WeakImplHelper1< XTerminateListener > 75 { 76 public: 77 static void ensureObservation(); 78 79 protected: 80 OObserverImpl(); 81 ~OObserverImpl(); 82 83 private: 84 // XTerminateListener 85 virtual void SAL_CALL queryTermination( const EventObject& Event ) throw (TerminationVetoException, RuntimeException); 86 virtual void SAL_CALL notifyTermination( const EventObject& Event ) throw (RuntimeException); 87 88 // XEventListener 89 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); 90 }; 91 92 //-------------------------------------------------------------------- 93 OObserverImpl::OObserverImpl() 94 { 95 } 96 97 //-------------------------------------------------------------------- 98 OObserverImpl::~OObserverImpl() 99 { 100 } 101 102 //-------------------------------------------------------------------- 103 void OObserverImpl::ensureObservation() 104 { 105 { 106 if ( getListenerAdminData().bCreatedAdapter ) 107 return; 108 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 109 if ( getListenerAdminData().bCreatedAdapter ) 110 return; 111 112 getListenerAdminData().bCreatedAdapter = true; 113 } 114 115 try 116 { 117 Reference< XDesktop > xDesktop; 118 xDesktop = xDesktop.query( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ) ); 119 OSL_ENSURE( xDesktop.is(), "OObserverImpl::ensureObservation: could not ensureObservation the desktop!" ); 120 if ( xDesktop.is() ) 121 xDesktop->addTerminateListener( new OObserverImpl ); 122 } 123 catch( const Exception& ) 124 { 125 OSL_ENSURE( sal_False, "OObserverImpl::ensureObservation: caught an exception!" ); 126 } 127 } 128 129 //-------------------------------------------------------------------- 130 void SAL_CALL OObserverImpl::queryTermination( const EventObject& /*Event*/ ) throw (TerminationVetoException, RuntimeException) 131 { 132 Listeners aToNotify; 133 { 134 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 135 aToNotify = getListenerAdminData().aListeners; 136 } 137 138 for ( Listeners::const_iterator listener = aToNotify.begin(); 139 listener != aToNotify.end(); 140 ++listener 141 ) 142 { 143 if ( !(*listener)->queryTermination() ) 144 throw TerminationVetoException(); 145 } 146 } 147 148 //-------------------------------------------------------------------- 149 void SAL_CALL OObserverImpl::notifyTermination( const EventObject& /*Event*/ ) throw (RuntimeException) 150 { 151 // get the listeners 152 Listeners aToNotify; 153 { 154 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 155 OSL_ENSURE( !getListenerAdminData().bAlreadyTerminated, "OObserverImpl::notifyTermination: terminated twice?" ); 156 aToNotify = getListenerAdminData().aListeners; 157 getListenerAdminData().bAlreadyTerminated = true; 158 } 159 160 // notify the listeners 161 for ( Listeners::const_iterator listener = aToNotify.begin(); 162 listener != aToNotify.end(); 163 ++listener 164 ) 165 { 166 (*listener)->notifyTermination(); 167 } 168 169 // clear the listener container 170 { 171 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 172 getListenerAdminData().aListeners.clear(); 173 } 174 } 175 176 //-------------------------------------------------------------------- 177 void SAL_CALL OObserverImpl::disposing( const EventObject& /*Event*/ ) throw (RuntimeException) 178 { 179 #if OSL_DEBUG_LEVEL > 0 180 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 181 OSL_ENSURE( getListenerAdminData().bAlreadyTerminated, "OObserverImpl::disposing: disposing without terminated?" ); 182 #endif 183 // not interested in 184 } 185 } 186 187 //==================================================================== 188 //= DesktopTerminationObserver 189 //==================================================================== 190 //-------------------------------------------------------------------- 191 void DesktopTerminationObserver::registerTerminationListener( ITerminationListener* _pListener ) 192 { 193 if ( !_pListener ) 194 return; 195 196 { 197 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 198 if ( getListenerAdminData().bAlreadyTerminated ) 199 { 200 _pListener->notifyTermination(); 201 return; 202 } 203 204 getListenerAdminData().aListeners.push_back( _pListener ); 205 } 206 207 OObserverImpl::ensureObservation(); 208 } 209 210 //-------------------------------------------------------------------- 211 void DesktopTerminationObserver::revokeTerminationListener( ITerminationListener* _pListener ) 212 { 213 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 214 Listeners& rListeners = getListenerAdminData().aListeners; 215 for ( Listeners::iterator lookup = rListeners.begin(); 216 lookup != rListeners.end(); 217 ++lookup 218 ) 219 { 220 if ( *lookup == _pListener ) 221 { 222 rListeners.erase( lookup ); 223 break; 224 } 225 } 226 } 227 228 //........................................................................ 229 } // namespace utl 230 //........................................................................ 231 232