CWS-TOOLING: integrate CWS os146
[LibreOffice.git] / comphelper / source / misc / instancelocker.cxx
blobc147217f1e7f436887455ef203246cfbf083d42f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
31 #include "comphelper_module.hxx"
33 #include <com/sun/star/util/XCloseBroadcaster.hpp>
34 #include <com/sun/star/util/XCloseable.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <com/sun/star/lang/IllegalArgumentException.hpp>
37 #include <com/sun/star/frame/XDesktop.hpp>
38 #include <com/sun/star/frame/DoubleInitializationException.hpp>
39 #include <com/sun/star/frame/DoubleInitializationException.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include "instancelocker.hxx"
44 using namespace ::com::sun::star;
47 // ====================================================================
48 // OInstanceLocker
49 // ====================================================================
51 // --------------------------------------------------------
52 OInstanceLocker::OInstanceLocker( const uno::Reference< uno::XComponentContext >& xContext )
53 : m_xContext( xContext )
54 , m_pLockListener( NULL )
55 , m_pListenersContainer( NULL )
56 , m_bDisposed( sal_False )
57 , m_bInitialized( sal_False )
61 // --------------------------------------------------------
62 OInstanceLocker::~OInstanceLocker()
64 if ( !m_bDisposed )
66 m_refCount++; // to call dispose
67 try {
68 dispose();
70 catch ( uno::RuntimeException& )
74 if ( m_pListenersContainer )
76 delete m_pListenersContainer;
77 m_pListenersContainer = NULL;
81 // XComponent
82 // --------------------------------------------------------
83 void SAL_CALL OInstanceLocker::dispose()
84 throw (uno::RuntimeException)
86 ::osl::MutexGuard aGuard( m_aMutex );
88 if ( m_bDisposed )
89 throw lang::DisposedException();
91 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
92 if ( m_pListenersContainer )
93 m_pListenersContainer->disposeAndClear( aSource );
95 if ( m_xLockListener.is() )
97 if ( m_pLockListener )
99 m_pLockListener->Dispose();
100 m_pLockListener = NULL;
102 m_xLockListener = uno::Reference< uno::XInterface >();
105 m_bDisposed = sal_True;
108 // --------------------------------------------------------
109 void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
110 throw (uno::RuntimeException)
112 ::osl::MutexGuard aGuard( m_aMutex );
113 if ( m_bDisposed )
114 throw lang::DisposedException(); // TODO
116 if ( !m_pListenersContainer )
117 m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex );
119 m_pListenersContainer->addInterface( xListener );
122 // --------------------------------------------------------
123 void SAL_CALL OInstanceLocker::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
124 throw (uno::RuntimeException)
126 ::osl::MutexGuard aGuard( m_aMutex );
127 if ( m_pListenersContainer )
128 m_pListenersContainer->removeInterface( xListener );
131 // XInitialization
132 // --------------------------------------------------------
133 void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArguments )
134 throw (uno::Exception, uno::RuntimeException)
136 ::osl::MutexGuard aGuard( m_aMutex );
137 if ( m_bInitialized )
138 throw frame::DoubleInitializationException();
140 if ( m_bDisposed )
141 throw lang::DisposedException(); // TODO
143 if ( !m_refCount )
144 throw uno::RuntimeException(); // the object must be refcounted already!
146 uno::Reference< uno::XInterface > xInstance;
147 uno::Reference< embed::XActionsApproval > xApproval;
148 sal_Int32 nModes = 0;
152 sal_Int32 nLen = aArguments.getLength();
153 if ( nLen < 2 || nLen > 3 )
154 throw lang::IllegalArgumentException(
155 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Wrong count of parameters!" ) ),
156 uno::Reference< uno::XInterface >(),
157 0 );
159 if ( !( aArguments[0] >>= xInstance ) || !xInstance.is() )
160 throw lang::IllegalArgumentException(
161 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Nonempty reference is expected as the first argument!" ) ),
162 uno::Reference< uno::XInterface >(),
163 0 );
165 if (
166 !( aArguments[1] >>= nModes ) ||
168 !( nModes & embed::Actions::PREVENT_CLOSE ) &&
169 !( nModes & embed::Actions::PREVENT_TERMINATION )
173 throw lang::IllegalArgumentException(
174 ::rtl::OUString(
175 RTL_CONSTASCII_USTRINGPARAM("The correct modes set is expected as the second argument!" ) ),
176 uno::Reference< uno::XInterface >(),
177 0 );
180 if ( nLen == 3 && !( aArguments[2] >>= xApproval ) )
181 throw lang::IllegalArgumentException(
182 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("If the third argument is provided, it must be XActionsApproval implementation!" ) ),
183 uno::Reference< uno::XInterface >(),
184 0 );
186 m_pLockListener = new OLockListener( uno::Reference< lang::XComponent > ( static_cast< lang::XComponent* >( this ) ),
187 xInstance,
188 nModes,
189 xApproval );
190 m_xLockListener = uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( m_pLockListener ) );
191 m_pLockListener->Init();
193 catch( uno::Exception& )
195 dispose();
196 throw;
199 m_bInitialized = sal_True;
203 // XServiceInfo
204 // --------------------------------------------------------
205 ::rtl::OUString SAL_CALL OInstanceLocker::getImplementationName( )
206 throw (uno::RuntimeException)
208 return getImplementationName_static();
211 // --------------------------------------------------------
212 ::sal_Bool SAL_CALL OInstanceLocker::supportsService( const ::rtl::OUString& ServiceName )
213 throw (uno::RuntimeException)
215 uno::Sequence< ::rtl::OUString > aSeq = getSupportedServiceNames();
217 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
218 if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
219 return sal_True;
221 return sal_False;
224 // --------------------------------------------------------
225 uno::Sequence< ::rtl::OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames()
226 throw (uno::RuntimeException)
228 return getSupportedServiceNames_static();
231 // Static methods
232 // --------------------------------------------------------
233 uno::Sequence< ::rtl::OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames_static()
235 const rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.InstanceLocker" ) );
236 return uno::Sequence< rtl::OUString >( &aServiceName, 1 );
239 // --------------------------------------------------------
240 ::rtl::OUString SAL_CALL OInstanceLocker::getImplementationName_static()
242 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.embed.InstanceLocker" ) );
245 // --------------------------------------------------------
246 uno::Reference< uno::XInterface > SAL_CALL OInstanceLocker::Create(
247 const uno::Reference< uno::XComponentContext >& rxContext )
249 return static_cast< cppu::OWeakObject * >( new OInstanceLocker( rxContext ) );
254 // ====================================================================
255 // OLockListener
256 // ====================================================================
258 // --------------------------------------------------------
259 OLockListener::OLockListener( const uno::WeakReference< lang::XComponent >& xWrapper,
260 const uno::Reference< uno::XInterface >& xInstance,
261 sal_Int32 nMode,
262 const uno::Reference< embed::XActionsApproval > xApproval )
263 : m_xInstance( xInstance )
264 , m_xApproval( xApproval )
265 , m_xWrapper( xWrapper )
266 , m_bDisposed( sal_False )
267 , m_bInitialized( sal_False )
268 , m_nMode( nMode )
272 // --------------------------------------------------------
273 OLockListener::~OLockListener()
277 // --------------------------------------------------------
278 void OLockListener::Dispose()
280 ::osl::ResettableMutexGuard aGuard( m_aMutex );
282 if ( m_bDisposed )
283 return;
285 if ( m_nMode & embed::Actions::PREVENT_CLOSE )
289 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY );
290 if ( xCloseBroadcaster.is() )
291 xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) );
293 uno::Reference< util::XCloseable > xCloseable( m_xInstance, uno::UNO_QUERY );
294 if ( xCloseable.is() )
295 xCloseable->close( sal_True );
297 catch( uno::Exception& )
301 if ( m_nMode & embed::Actions::PREVENT_TERMINATION )
305 uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW );
306 xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
308 catch( uno::Exception& )
312 m_xInstance = uno::Reference< uno::XInterface >();
313 m_bDisposed = sal_True;
316 // XEventListener
317 // --------------------------------------------------------
318 void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent )
319 throw (uno::RuntimeException)
321 ::osl::ResettableMutexGuard aGuard( m_aMutex );
323 // object is disposed
324 if ( aEvent.Source == m_xInstance )
326 // the object does not listen for anything any more
327 m_nMode = 0;
329 // dispose the wrapper;
330 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
331 aGuard.clear();
332 if ( xComponent.is() )
334 try { xComponent->dispose(); }
335 catch( uno::Exception& ){}
341 // XCloseListener
342 // --------------------------------------------------------
343 void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_Bool )
344 throw (util::CloseVetoException, uno::RuntimeException)
346 // GetsOwnership parameter is always ignored, the user of the service must close the object always
347 ::osl::ResettableMutexGuard aGuard( m_aMutex );
348 if ( !m_bDisposed && aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_CLOSE ) )
352 uno::Reference< embed::XActionsApproval > xApprove = m_xApproval;
354 // unlock the mutex here
355 aGuard.clear();
357 if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_CLOSE ) )
358 throw util::CloseVetoException();
360 catch( util::CloseVetoException& )
362 // rethrow this exception
363 throw;
365 catch( uno::Exception& )
367 // no action should be done
372 // --------------------------------------------------------
373 void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent )
374 throw (uno::RuntimeException)
376 ::osl::ResettableMutexGuard aGuard( m_aMutex );
378 // object is closed, no reason to listen
379 if ( aEvent.Source == m_xInstance )
381 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( aEvent.Source, uno::UNO_QUERY );
382 if ( xCloseBroadcaster.is() )
384 xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) );
385 m_nMode &= ~embed::Actions::PREVENT_CLOSE;
386 if ( !m_nMode )
388 // dispose the wrapper;
389 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
390 aGuard.clear();
391 if ( xComponent.is() )
393 try { xComponent->dispose(); }
394 catch( uno::Exception& ){}
402 // XTerminateListener
403 // --------------------------------------------------------
404 void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent )
405 throw (frame::TerminationVetoException, uno::RuntimeException)
407 ::osl::ResettableMutexGuard aGuard( m_aMutex );
408 if ( aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_TERMINATION ) )
412 uno::Reference< embed::XActionsApproval > xApprove = m_xApproval;
414 // unlock the mutex here
415 aGuard.clear();
417 if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_TERMINATION ) )
418 throw frame::TerminationVetoException();
420 catch( frame::TerminationVetoException& )
422 // rethrow this exception
423 throw;
425 catch( uno::Exception& )
427 // no action should be done
432 // --------------------------------------------------------
433 void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent )
434 throw (uno::RuntimeException)
436 ::osl::ResettableMutexGuard aGuard( m_aMutex );
438 // object is terminated, no reason to listen
439 if ( aEvent.Source == m_xInstance )
441 uno::Reference< frame::XDesktop > xDesktop( aEvent.Source, uno::UNO_QUERY );
442 if ( xDesktop.is() )
446 xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
447 m_nMode &= ~embed::Actions::PREVENT_TERMINATION;
448 if ( !m_nMode )
450 // dispose the wrapper;
451 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
452 aGuard.clear();
453 if ( xComponent.is() )
455 try { xComponent->dispose(); }
456 catch( uno::Exception& ){}
460 catch( uno::Exception& )
467 // XInitialization
468 // --------------------------------------------------------
469 sal_Bool OLockListener::Init()
471 ::osl::ResettableMutexGuard aGuard( m_aMutex );
473 if ( m_bDisposed || m_bInitialized )
474 return sal_False;
478 if ( m_nMode & embed::Actions::PREVENT_CLOSE )
480 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY_THROW );
481 xCloseBroadcaster->addCloseListener( static_cast< util::XCloseListener* >( this ) );
484 if ( m_nMode & embed::Actions::PREVENT_TERMINATION )
486 uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW );
487 xDesktop->addTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
490 catch( uno::Exception& )
492 // dispose the wrapper;
493 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
494 aGuard.clear();
495 if ( xComponent.is() )
497 try { xComponent->dispose(); }
498 catch( uno::Exception& ){}
501 throw;
504 m_bInitialized = sal_True;
506 return sal_True;
509 void createRegistryInfo_OInstanceLocker()
511 static ::comphelper::module::OAutoRegistration< OInstanceLocker > aAutoRegistration;