1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_unotools.hxx" 26 #include <unotools/desktopterminationobserver.hxx> 27 28 /** === begin UNO includes === **/ 29 #include <com/sun/star/frame/XTerminateListener.hpp> 30 #include <com/sun/star/frame/XDesktop.hpp> 31 /** === end UNO includes === **/ 32 #include <cppuhelper/implbase1.hxx> 33 #include <comphelper/processfactory.hxx> 34 35 #include <list> 36 37 //........................................................................ 38 namespace utl 39 { 40 //........................................................................ 41 42 using namespace ::com::sun::star::uno; 43 using namespace ::com::sun::star::lang; 44 using namespace ::com::sun::star::frame; 45 46 namespace 47 { 48 //................................................................ 49 typedef ::std::list< ITerminationListener* > Listeners; 50 51 struct ListenerAdminData 52 { 53 Listeners aListeners; 54 bool bAlreadyTerminated; 55 bool bCreatedAdapter; 56 ListenerAdminDatautl::__anonf12dc6390111::ListenerAdminData57 ListenerAdminData() : bAlreadyTerminated( false ), bCreatedAdapter( false ) { } 58 }; 59 60 //................................................................ getListenerAdminData()61 ListenerAdminData& getListenerAdminData() 62 { 63 static ListenerAdminData s_aData; 64 return s_aData; 65 } 66 67 //================================================================ 68 //= OObserverImpl 69 //================================================================ 70 class OObserverImpl : public ::cppu::WeakImplHelper1< XTerminateListener > 71 { 72 public: 73 static void ensureObservation(); 74 75 protected: 76 OObserverImpl(); 77 ~OObserverImpl(); 78 79 private: 80 // XTerminateListener 81 virtual void SAL_CALL queryTermination( const EventObject& Event ) throw (TerminationVetoException, RuntimeException); 82 virtual void SAL_CALL notifyTermination( const EventObject& Event ) throw (RuntimeException); 83 84 // XEventListener 85 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); 86 }; 87 88 //-------------------------------------------------------------------- OObserverImpl()89 OObserverImpl::OObserverImpl() 90 { 91 } 92 93 //-------------------------------------------------------------------- ~OObserverImpl()94 OObserverImpl::~OObserverImpl() 95 { 96 } 97 98 //-------------------------------------------------------------------- ensureObservation()99 void OObserverImpl::ensureObservation() 100 { 101 { 102 if ( getListenerAdminData().bCreatedAdapter ) 103 return; 104 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 105 if ( getListenerAdminData().bCreatedAdapter ) 106 return; 107 108 getListenerAdminData().bCreatedAdapter = true; 109 } 110 111 try 112 { 113 Reference< XDesktop > xDesktop; 114 xDesktop = xDesktop.query( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ) ); 115 OSL_ENSURE( xDesktop.is(), "OObserverImpl::ensureObservation: could not ensureObservation the desktop!" ); 116 if ( xDesktop.is() ) 117 xDesktop->addTerminateListener( new OObserverImpl ); 118 } 119 catch( const Exception& ) 120 { 121 OSL_ENSURE( sal_False, "OObserverImpl::ensureObservation: caught an exception!" ); 122 } 123 } 124 125 //-------------------------------------------------------------------- queryTermination(const EventObject &)126 void SAL_CALL OObserverImpl::queryTermination( const EventObject& /*Event*/ ) throw (TerminationVetoException, RuntimeException) 127 { 128 Listeners aToNotify; 129 { 130 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 131 aToNotify = getListenerAdminData().aListeners; 132 } 133 134 for ( Listeners::const_iterator listener = aToNotify.begin(); 135 listener != aToNotify.end(); 136 ++listener 137 ) 138 { 139 if ( !(*listener)->queryTermination() ) 140 throw TerminationVetoException(); 141 } 142 } 143 144 //-------------------------------------------------------------------- notifyTermination(const EventObject &)145 void SAL_CALL OObserverImpl::notifyTermination( const EventObject& /*Event*/ ) throw (RuntimeException) 146 { 147 // get the listeners 148 Listeners aToNotify; 149 { 150 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 151 OSL_ENSURE( !getListenerAdminData().bAlreadyTerminated, "OObserverImpl::notifyTermination: terminated twice?" ); 152 aToNotify = getListenerAdminData().aListeners; 153 getListenerAdminData().bAlreadyTerminated = true; 154 } 155 156 // notify the listeners 157 for ( Listeners::const_iterator listener = aToNotify.begin(); 158 listener != aToNotify.end(); 159 ++listener 160 ) 161 { 162 (*listener)->notifyTermination(); 163 } 164 165 // clear the listener container 166 { 167 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 168 getListenerAdminData().aListeners.clear(); 169 } 170 } 171 172 //-------------------------------------------------------------------- disposing(const EventObject &)173 void SAL_CALL OObserverImpl::disposing( const EventObject& /*Event*/ ) throw (RuntimeException) 174 { 175 #if OSL_DEBUG_LEVEL > 0 176 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 177 OSL_ENSURE( getListenerAdminData().bAlreadyTerminated, "OObserverImpl::disposing: disposing without terminated?" ); 178 #endif 179 // not interested in 180 } 181 } 182 183 //==================================================================== 184 //= DesktopTerminationObserver 185 //==================================================================== 186 //-------------------------------------------------------------------- registerTerminationListener(ITerminationListener * _pListener)187 void DesktopTerminationObserver::registerTerminationListener( ITerminationListener* _pListener ) 188 { 189 if ( !_pListener ) 190 return; 191 192 { 193 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 194 if ( getListenerAdminData().bAlreadyTerminated ) 195 { 196 _pListener->notifyTermination(); 197 return; 198 } 199 200 getListenerAdminData().aListeners.push_back( _pListener ); 201 } 202 203 OObserverImpl::ensureObservation(); 204 } 205 206 //-------------------------------------------------------------------- revokeTerminationListener(ITerminationListener * _pListener)207 void DesktopTerminationObserver::revokeTerminationListener( ITerminationListener* _pListener ) 208 { 209 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 210 Listeners& rListeners = getListenerAdminData().aListeners; 211 for ( Listeners::iterator lookup = rListeners.begin(); 212 lookup != rListeners.end(); 213 ++lookup 214 ) 215 { 216 if ( *lookup == _pListener ) 217 { 218 rListeners.erase( lookup ); 219 break; 220 } 221 } 222 } 223 224 //........................................................................ 225 } // namespace utl 226 //........................................................................ 227 228