1*96de5490SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*96de5490SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*96de5490SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*96de5490SAndrew Rist  * distributed with this work for additional information
6*96de5490SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*96de5490SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*96de5490SAndrew Rist  * "License"); you may not use this file except in compliance
9*96de5490SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*96de5490SAndrew Rist  *
11*96de5490SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*96de5490SAndrew Rist  *
13*96de5490SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*96de5490SAndrew Rist  * software distributed under the License is distributed on an
15*96de5490SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*96de5490SAndrew Rist  * KIND, either express or implied.  See the License for the
17*96de5490SAndrew Rist  * specific language governing permissions and limitations
18*96de5490SAndrew Rist  * under the License.
19*96de5490SAndrew Rist  *
20*96de5490SAndrew Rist  *************************************************************/
21*96de5490SAndrew Rist 
22*96de5490SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_dbaccess.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "documenteventnotifier.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir /** === begin UNO includes === **/
30cdf0e10cSrcweir #include <com/sun/star/frame/DoubleInitializationException.hpp>
31cdf0e10cSrcweir /** === end UNO includes === **/
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <comphelper/asyncnotification.hxx>
34cdf0e10cSrcweir #include <cppuhelper/interfacecontainer.hxx>
35cdf0e10cSrcweir #include <cppuhelper/weak.hxx>
36cdf0e10cSrcweir #include <tools/diagnose_ex.h>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir //........................................................................
39cdf0e10cSrcweir namespace dbaccess
40cdf0e10cSrcweir {
41cdf0e10cSrcweir //........................................................................
42cdf0e10cSrcweir 
43cdf0e10cSrcweir 	/** === begin UNO using === **/
44cdf0e10cSrcweir 	using ::com::sun::star::uno::Reference;
45cdf0e10cSrcweir 	using ::com::sun::star::uno::XInterface;
46cdf0e10cSrcweir 	using ::com::sun::star::uno::UNO_QUERY;
47cdf0e10cSrcweir 	using ::com::sun::star::uno::UNO_QUERY_THROW;
48cdf0e10cSrcweir 	using ::com::sun::star::uno::UNO_SET_THROW;
49cdf0e10cSrcweir 	using ::com::sun::star::uno::Exception;
50cdf0e10cSrcweir 	using ::com::sun::star::uno::RuntimeException;
51cdf0e10cSrcweir 	using ::com::sun::star::uno::Any;
52cdf0e10cSrcweir 	using ::com::sun::star::uno::makeAny;
53cdf0e10cSrcweir 	using ::com::sun::star::uno::Sequence;
54cdf0e10cSrcweir 	using ::com::sun::star::uno::Type;
55cdf0e10cSrcweir     using ::com::sun::star::frame::DoubleInitializationException;
56cdf0e10cSrcweir     using ::com::sun::star::document::XDocumentEventListener;
57cdf0e10cSrcweir     using ::com::sun::star::document::DocumentEvent;
58cdf0e10cSrcweir     using ::com::sun::star::frame::XController2;
59cdf0e10cSrcweir 	/** === end UNO using === **/
60cdf0e10cSrcweir 	using namespace ::com::sun::star;
61cdf0e10cSrcweir 
62cdf0e10cSrcweir     //==================================================================
63cdf0e10cSrcweir     //= DocumentEventHolder
64cdf0e10cSrcweir     //==================================================================
65cdf0e10cSrcweir     typedef ::comphelper::EventHolder< DocumentEvent >  DocumentEventHolder;
66cdf0e10cSrcweir 
67cdf0e10cSrcweir     //====================================================================
68cdf0e10cSrcweir 	//= DocumentEventNotifier_Impl
69cdf0e10cSrcweir 	//====================================================================
70cdf0e10cSrcweir     class DocumentEventNotifier_Impl : public ::comphelper::IEventProcessor
71cdf0e10cSrcweir     {
72cdf0e10cSrcweir         oslInterlockedCount                                     m_refCount;
73cdf0e10cSrcweir         ::cppu::OWeakObject&                                    m_rDocument;
74cdf0e10cSrcweir         ::osl::Mutex&                                           m_rMutex;
75cdf0e10cSrcweir         bool                                                    m_bInitialized;
76cdf0e10cSrcweir         bool                                                    m_bDisposed;
77cdf0e10cSrcweir         ::rtl::Reference< ::comphelper::AsyncEventNotifier >    m_pEventBroadcaster;
78cdf0e10cSrcweir         ::cppu::OInterfaceContainerHelper					    m_aLegacyEventListeners;
79cdf0e10cSrcweir         ::cppu::OInterfaceContainerHelper					    m_aDocumentEventListeners;
80cdf0e10cSrcweir 
81cdf0e10cSrcweir     public:
DocumentEventNotifier_Impl(::cppu::OWeakObject & _rBroadcasterDocument,::osl::Mutex & _rMutex)82cdf0e10cSrcweir         DocumentEventNotifier_Impl( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex )
83cdf0e10cSrcweir             :m_refCount( 0 )
84cdf0e10cSrcweir             ,m_rDocument( _rBroadcasterDocument )
85cdf0e10cSrcweir             ,m_rMutex( _rMutex )
86cdf0e10cSrcweir             ,m_bInitialized( false )
87cdf0e10cSrcweir             ,m_bDisposed( false )
88cdf0e10cSrcweir             ,m_aLegacyEventListeners( _rMutex )
89cdf0e10cSrcweir             ,m_aDocumentEventListeners( _rMutex )
90cdf0e10cSrcweir         {
91cdf0e10cSrcweir         }
92cdf0e10cSrcweir 
93cdf0e10cSrcweir         // IReference
94cdf0e10cSrcweir         virtual void SAL_CALL acquire();
95cdf0e10cSrcweir         virtual void SAL_CALL release();
96cdf0e10cSrcweir 
addLegacyEventListener(const Reference<document::XEventListener> & _Listener)97cdf0e10cSrcweir         void addLegacyEventListener( const Reference< document::XEventListener >& _Listener )
98cdf0e10cSrcweir         {
99cdf0e10cSrcweir             m_aLegacyEventListeners.addInterface( _Listener );
100cdf0e10cSrcweir         }
101cdf0e10cSrcweir 
removeLegacyEventListener(const Reference<document::XEventListener> & _Listener)102cdf0e10cSrcweir         void removeLegacyEventListener( const Reference< document::XEventListener >& _Listener )
103cdf0e10cSrcweir         {
104cdf0e10cSrcweir             m_aLegacyEventListeners.removeInterface( _Listener );
105cdf0e10cSrcweir         }
106cdf0e10cSrcweir 
addDocumentEventListener(const Reference<XDocumentEventListener> & _Listener)107cdf0e10cSrcweir         void addDocumentEventListener( const Reference< XDocumentEventListener >& _Listener )
108cdf0e10cSrcweir         {
109cdf0e10cSrcweir             m_aDocumentEventListeners.addInterface( _Listener );
110cdf0e10cSrcweir         }
111cdf0e10cSrcweir 
removeDocumentEventListener(const Reference<XDocumentEventListener> & _Listener)112cdf0e10cSrcweir         void removeDocumentEventListener( const Reference< XDocumentEventListener >& _Listener )
113cdf0e10cSrcweir         {
114cdf0e10cSrcweir             m_aDocumentEventListeners.removeInterface( _Listener );
115cdf0e10cSrcweir         }
116cdf0e10cSrcweir 
117cdf0e10cSrcweir         void disposing();
118cdf0e10cSrcweir 
119cdf0e10cSrcweir         void onDocumentInitialized();
120cdf0e10cSrcweir 
notifyDocumentEvent(const::rtl::OUString & _EventName,const Reference<XController2> & _ViewController,const Any & _Supplement)121cdf0e10cSrcweir         void    notifyDocumentEvent( const ::rtl::OUString& _EventName, const Reference< XController2 >& _ViewController,
122cdf0e10cSrcweir                     const Any& _Supplement )
123cdf0e10cSrcweir         {
124cdf0e10cSrcweir             impl_notifyEvent_nothrow( DocumentEvent(
125cdf0e10cSrcweir                 m_rDocument, _EventName, _ViewController, _Supplement ) );
126cdf0e10cSrcweir         }
127cdf0e10cSrcweir 
notifyDocumentEventAsync(const::rtl::OUString & _EventName,const Reference<XController2> & _ViewController,const Any & _Supplement)128cdf0e10cSrcweir         void    notifyDocumentEventAsync( const ::rtl::OUString& _EventName, const Reference< XController2 >& _ViewController,
129cdf0e10cSrcweir                     const Any& _Supplement )
130cdf0e10cSrcweir         {
131cdf0e10cSrcweir             impl_notifyEventAsync_nothrow( DocumentEvent(
132cdf0e10cSrcweir                 m_rDocument, _EventName, _ViewController, _Supplement ) );
133cdf0e10cSrcweir         }
134cdf0e10cSrcweir 
135cdf0e10cSrcweir     protected:
~DocumentEventNotifier_Impl()136cdf0e10cSrcweir         virtual ~DocumentEventNotifier_Impl()
137cdf0e10cSrcweir         {
138cdf0e10cSrcweir         }
139cdf0e10cSrcweir 
140cdf0e10cSrcweir         // IEventProcessor
141cdf0e10cSrcweir         virtual void processEvent( const ::comphelper::AnyEvent& _rEvent );
142cdf0e10cSrcweir 
143cdf0e10cSrcweir     private:
144cdf0e10cSrcweir         void impl_notifyEvent_nothrow( const DocumentEvent& _rEvent );
145cdf0e10cSrcweir         void impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent );
146cdf0e10cSrcweir     };
147cdf0e10cSrcweir 
148cdf0e10cSrcweir 	//--------------------------------------------------------------------
acquire()149cdf0e10cSrcweir     void SAL_CALL DocumentEventNotifier_Impl::acquire()
150cdf0e10cSrcweir     {
151cdf0e10cSrcweir         osl_incrementInterlockedCount( &m_refCount );
152cdf0e10cSrcweir     }
153cdf0e10cSrcweir 
154cdf0e10cSrcweir 	//--------------------------------------------------------------------
release()155cdf0e10cSrcweir     void SAL_CALL DocumentEventNotifier_Impl::release()
156cdf0e10cSrcweir     {
157cdf0e10cSrcweir         if ( 0 == osl_decrementInterlockedCount( &m_refCount ) )
158cdf0e10cSrcweir             delete this;
159cdf0e10cSrcweir     }
160cdf0e10cSrcweir 
161cdf0e10cSrcweir 	//--------------------------------------------------------------------
disposing()162cdf0e10cSrcweir     void DocumentEventNotifier_Impl::disposing()
163cdf0e10cSrcweir     {
164cdf0e10cSrcweir         // SYNCHRONIZED ->
165cdf0e10cSrcweir         // cancel any pending asynchronous events
166cdf0e10cSrcweir         ::osl::ResettableMutexGuard aGuard( m_rMutex );
167cdf0e10cSrcweir         if ( m_pEventBroadcaster.is() )
168cdf0e10cSrcweir         {
169cdf0e10cSrcweir             m_pEventBroadcaster->removeEventsForProcessor( this );
170cdf0e10cSrcweir             m_pEventBroadcaster->terminate();
171cdf0e10cSrcweir             m_pEventBroadcaster = NULL;
172cdf0e10cSrcweir         }
173cdf0e10cSrcweir 
174cdf0e10cSrcweir         lang::EventObject aEvent( m_rDocument );
175cdf0e10cSrcweir         aGuard.clear();
176cdf0e10cSrcweir         // <-- SYNCHRONIZED
177cdf0e10cSrcweir 
178cdf0e10cSrcweir         m_aLegacyEventListeners.disposeAndClear( aEvent );
179cdf0e10cSrcweir         m_aDocumentEventListeners.disposeAndClear( aEvent );
180cdf0e10cSrcweir 
181cdf0e10cSrcweir         // SYNCHRONIZED ->
182cdf0e10cSrcweir         aGuard.reset();
183cdf0e10cSrcweir         m_bDisposed = true;
184cdf0e10cSrcweir         // <-- SYNCHRONIZED
185cdf0e10cSrcweir     }
186cdf0e10cSrcweir 
187cdf0e10cSrcweir 	//--------------------------------------------------------------------
onDocumentInitialized()188cdf0e10cSrcweir     void DocumentEventNotifier_Impl::onDocumentInitialized()
189cdf0e10cSrcweir     {
190cdf0e10cSrcweir         if ( m_bInitialized )
191cdf0e10cSrcweir             throw DoubleInitializationException();
192cdf0e10cSrcweir 
193cdf0e10cSrcweir         m_bInitialized = true;
194cdf0e10cSrcweir         if ( m_pEventBroadcaster.is() )
195cdf0e10cSrcweir             // there are already pending asynchronous events
196cdf0e10cSrcweir             m_pEventBroadcaster->create();
197cdf0e10cSrcweir     }
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 	//--------------------------------------------------------------------
impl_notifyEvent_nothrow(const DocumentEvent & _rEvent)200cdf0e10cSrcweir     void DocumentEventNotifier_Impl::impl_notifyEvent_nothrow( const DocumentEvent& _rEvent )
201cdf0e10cSrcweir     {
202cdf0e10cSrcweir         OSL_PRECOND( m_bInitialized,
203cdf0e10cSrcweir             "DocumentEventNotifier_Impl::impl_notifyEvent_nothrow: only to be called when the document is already initialized!" );
204cdf0e10cSrcweir 	    try
205cdf0e10cSrcweir 	    {
206cdf0e10cSrcweir             document::EventObject aLegacyEvent( _rEvent.Source, _rEvent.EventName );
207cdf0e10cSrcweir             m_aLegacyEventListeners.notifyEach( &document::XEventListener::notifyEvent, aLegacyEvent );
208cdf0e10cSrcweir 	    }
209cdf0e10cSrcweir 	    catch(const Exception&)
210cdf0e10cSrcweir 	    {
211cdf0e10cSrcweir             DBG_UNHANDLED_EXCEPTION();
212cdf0e10cSrcweir 	    }
213cdf0e10cSrcweir         try
214cdf0e10cSrcweir         {
215cdf0e10cSrcweir             m_aDocumentEventListeners.notifyEach( &XDocumentEventListener::documentEventOccured, _rEvent );
216cdf0e10cSrcweir         }
217cdf0e10cSrcweir         catch( const Exception& )
218cdf0e10cSrcweir         {
219cdf0e10cSrcweir         	DBG_UNHANDLED_EXCEPTION();
220cdf0e10cSrcweir         }
221cdf0e10cSrcweir     }
222cdf0e10cSrcweir 
223cdf0e10cSrcweir 	//--------------------------------------------------------------------
impl_notifyEventAsync_nothrow(const DocumentEvent & _rEvent)224cdf0e10cSrcweir     void DocumentEventNotifier_Impl::impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent )
225cdf0e10cSrcweir     {
226cdf0e10cSrcweir         if ( !m_pEventBroadcaster.is() )
227cdf0e10cSrcweir         {
228cdf0e10cSrcweir             m_pEventBroadcaster.set( new ::comphelper::AsyncEventNotifier );
229cdf0e10cSrcweir             if ( m_bInitialized )
230cdf0e10cSrcweir                 // start processing the events if and only if we (our document, respectively) are
231cdf0e10cSrcweir                 // already initialized
232cdf0e10cSrcweir                 m_pEventBroadcaster->create();
233cdf0e10cSrcweir         }
234cdf0e10cSrcweir         m_pEventBroadcaster->addEvent( new DocumentEventHolder( _rEvent ), this );
235cdf0e10cSrcweir     }
236cdf0e10cSrcweir 
237cdf0e10cSrcweir     // -----------------------------------------------------------------------------
processEvent(const::comphelper::AnyEvent & _rEvent)238cdf0e10cSrcweir     void DocumentEventNotifier_Impl::processEvent( const ::comphelper::AnyEvent& _rEvent )
239cdf0e10cSrcweir     {
240cdf0e10cSrcweir         // beware, this is called from the notification thread
241cdf0e10cSrcweir         {
242cdf0e10cSrcweir             ::osl::MutexGuard aGuard( m_rMutex );
243cdf0e10cSrcweir             if  ( m_bDisposed )
244cdf0e10cSrcweir                 return;
245cdf0e10cSrcweir         }
246cdf0e10cSrcweir         const DocumentEventHolder& rEventHolder = dynamic_cast< const DocumentEventHolder& >( _rEvent );
247cdf0e10cSrcweir         impl_notifyEvent_nothrow( rEventHolder.getEventObject() );
248cdf0e10cSrcweir     }
249cdf0e10cSrcweir 
250cdf0e10cSrcweir 	//====================================================================
251cdf0e10cSrcweir 	//= DocumentEventNotifier
252cdf0e10cSrcweir 	//====================================================================
253cdf0e10cSrcweir 	//--------------------------------------------------------------------
DocumentEventNotifier(::cppu::OWeakObject & _rBroadcasterDocument,::osl::Mutex & _rMutex)254cdf0e10cSrcweir     DocumentEventNotifier::DocumentEventNotifier( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex )
255cdf0e10cSrcweir         :m_pImpl( new DocumentEventNotifier_Impl( _rBroadcasterDocument, _rMutex ) )
256cdf0e10cSrcweir     {
257cdf0e10cSrcweir     }
258cdf0e10cSrcweir 
259cdf0e10cSrcweir 	//--------------------------------------------------------------------
~DocumentEventNotifier()260cdf0e10cSrcweir     DocumentEventNotifier::~DocumentEventNotifier()
261cdf0e10cSrcweir     {
262cdf0e10cSrcweir     }
263cdf0e10cSrcweir 
264cdf0e10cSrcweir 	//--------------------------------------------------------------------
disposing()265cdf0e10cSrcweir     void DocumentEventNotifier::disposing()
266cdf0e10cSrcweir     {
267cdf0e10cSrcweir         m_pImpl->disposing();
268cdf0e10cSrcweir     }
269cdf0e10cSrcweir 
270cdf0e10cSrcweir 	//--------------------------------------------------------------------
onDocumentInitialized()271cdf0e10cSrcweir     void DocumentEventNotifier::onDocumentInitialized()
272cdf0e10cSrcweir     {
273cdf0e10cSrcweir         m_pImpl->onDocumentInitialized();
274cdf0e10cSrcweir     }
275cdf0e10cSrcweir 
276cdf0e10cSrcweir 	//--------------------------------------------------------------------
addLegacyEventListener(const Reference<document::XEventListener> & _Listener)277cdf0e10cSrcweir     void DocumentEventNotifier::addLegacyEventListener( const Reference< document::XEventListener >& _Listener )
278cdf0e10cSrcweir     {
279cdf0e10cSrcweir         m_pImpl->addLegacyEventListener( _Listener );
280cdf0e10cSrcweir     }
281cdf0e10cSrcweir 
282cdf0e10cSrcweir 	//--------------------------------------------------------------------
removeLegacyEventListener(const Reference<document::XEventListener> & _Listener)283cdf0e10cSrcweir     void DocumentEventNotifier::removeLegacyEventListener( const Reference< document::XEventListener >& _Listener )
284cdf0e10cSrcweir     {
285cdf0e10cSrcweir         m_pImpl->removeLegacyEventListener( _Listener );
286cdf0e10cSrcweir     }
287cdf0e10cSrcweir 
288cdf0e10cSrcweir 	//--------------------------------------------------------------------
addDocumentEventListener(const Reference<XDocumentEventListener> & _Listener)289cdf0e10cSrcweir     void DocumentEventNotifier::addDocumentEventListener( const Reference< XDocumentEventListener >& _Listener )
290cdf0e10cSrcweir     {
291cdf0e10cSrcweir         m_pImpl->addDocumentEventListener( _Listener );
292cdf0e10cSrcweir     }
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 	//--------------------------------------------------------------------
removeDocumentEventListener(const Reference<XDocumentEventListener> & _Listener)295cdf0e10cSrcweir     void DocumentEventNotifier::removeDocumentEventListener( const Reference< XDocumentEventListener >& _Listener )
296cdf0e10cSrcweir     {
297cdf0e10cSrcweir         m_pImpl->removeDocumentEventListener( _Listener );
298cdf0e10cSrcweir     }
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 	//--------------------------------------------------------------------
notifyDocumentEvent(const::rtl::OUString & _EventName,const Reference<XController2> & _ViewController,const Any & _Supplement)301cdf0e10cSrcweir     void DocumentEventNotifier::notifyDocumentEvent( const ::rtl::OUString& _EventName,
302cdf0e10cSrcweir         const Reference< XController2 >& _ViewController, const Any& _Supplement )
303cdf0e10cSrcweir     {
304cdf0e10cSrcweir         m_pImpl->notifyDocumentEvent( _EventName, _ViewController, _Supplement );
305cdf0e10cSrcweir     }
306cdf0e10cSrcweir 
307cdf0e10cSrcweir 	//--------------------------------------------------------------------
notifyDocumentEventAsync(const::rtl::OUString & _EventName,const Reference<XController2> & _ViewController,const Any & _Supplement)308cdf0e10cSrcweir     void DocumentEventNotifier::notifyDocumentEventAsync( const ::rtl::OUString& _EventName,
309cdf0e10cSrcweir         const Reference< XController2 >& _ViewController, const Any& _Supplement )
310cdf0e10cSrcweir     {
311cdf0e10cSrcweir         m_pImpl->notifyDocumentEventAsync( _EventName, _ViewController, _Supplement );
312cdf0e10cSrcweir     }
313cdf0e10cSrcweir 
314cdf0e10cSrcweir //........................................................................
315cdf0e10cSrcweir } // namespace dbaccess
316cdf0e10cSrcweir //........................................................................
317