update credits
[LibreOffice.git] / comphelper / source / misc / instancelocker.cxx
blobf14be18a0ba1151bb4a0e031d973e6bc9d46306e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "comphelper_module.hxx"
23 #include <com/sun/star/util/XCloseBroadcaster.hpp>
24 #include <com/sun/star/util/XCloseable.hpp>
25 #include <com/sun/star/lang/DisposedException.hpp>
26 #include <com/sun/star/lang/IllegalArgumentException.hpp>
27 #include <com/sun/star/frame/XDesktop.hpp>
28 #include <com/sun/star/frame/DoubleInitializationException.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include "instancelocker.hxx"
33 using namespace ::com::sun::star;
36 // ====================================================================
37 // OInstanceLocker
38 // ====================================================================
40 // --------------------------------------------------------
41 OInstanceLocker::OInstanceLocker( const uno::Reference< uno::XComponentContext >& xContext )
42 : m_xContext( xContext )
43 , m_pLockListener( NULL )
44 , m_pListenersContainer( NULL )
45 , m_bDisposed( sal_False )
46 , m_bInitialized( sal_False )
50 // --------------------------------------------------------
51 OInstanceLocker::~OInstanceLocker()
53 if ( !m_bDisposed )
55 m_refCount++; // to call dispose
56 try {
57 dispose();
59 catch ( uno::RuntimeException& )
63 if ( m_pListenersContainer )
65 delete m_pListenersContainer;
66 m_pListenersContainer = NULL;
70 // XComponent
71 // --------------------------------------------------------
72 void SAL_CALL OInstanceLocker::dispose()
73 throw (uno::RuntimeException)
75 ::osl::MutexGuard aGuard( m_aMutex );
77 if ( m_bDisposed )
78 throw lang::DisposedException();
80 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
81 if ( m_pListenersContainer )
82 m_pListenersContainer->disposeAndClear( aSource );
84 if ( m_xLockListener.is() )
86 if ( m_pLockListener )
88 m_pLockListener->Dispose();
89 m_pLockListener = NULL;
91 m_xLockListener = uno::Reference< uno::XInterface >();
94 m_bDisposed = sal_True;
97 // --------------------------------------------------------
98 void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
99 throw (uno::RuntimeException)
101 ::osl::MutexGuard aGuard( m_aMutex );
102 if ( m_bDisposed )
103 throw lang::DisposedException(); // TODO
105 if ( !m_pListenersContainer )
106 m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex );
108 m_pListenersContainer->addInterface( xListener );
111 // --------------------------------------------------------
112 void SAL_CALL OInstanceLocker::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
113 throw (uno::RuntimeException)
115 ::osl::MutexGuard aGuard( m_aMutex );
116 if ( m_pListenersContainer )
117 m_pListenersContainer->removeInterface( xListener );
120 // XInitialization
121 // --------------------------------------------------------
122 void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArguments )
123 throw (uno::Exception, uno::RuntimeException)
125 ::osl::MutexGuard aGuard( m_aMutex );
126 if ( m_bInitialized )
127 throw frame::DoubleInitializationException();
129 if ( m_bDisposed )
130 throw lang::DisposedException(); // TODO
132 if ( !m_refCount )
133 throw uno::RuntimeException(); // the object must be refcounted already!
135 uno::Reference< uno::XInterface > xInstance;
136 uno::Reference< embed::XActionsApproval > xApproval;
137 sal_Int32 nModes = 0;
141 sal_Int32 nLen = aArguments.getLength();
142 if ( nLen < 2 || nLen > 3 )
143 throw lang::IllegalArgumentException(
144 OUString( "Wrong count of parameters!" ),
145 uno::Reference< uno::XInterface >(),
146 0 );
148 if ( !( aArguments[0] >>= xInstance ) || !xInstance.is() )
149 throw lang::IllegalArgumentException(
150 OUString( "Nonempty reference is expected as the first argument!" ),
151 uno::Reference< uno::XInterface >(),
152 0 );
154 if (
155 !( aArguments[1] >>= nModes ) ||
157 !( nModes & embed::Actions::PREVENT_CLOSE ) &&
158 !( nModes & embed::Actions::PREVENT_TERMINATION )
162 throw lang::IllegalArgumentException(
163 OUString("The correct modes set is expected as the second argument!"),
164 uno::Reference< uno::XInterface >(),
165 0 );
168 if ( nLen == 3 && !( aArguments[2] >>= xApproval ) )
169 throw lang::IllegalArgumentException(
170 OUString( "If the third argument is provided, it must be XActionsApproval implementation!" ),
171 uno::Reference< uno::XInterface >(),
172 0 );
174 m_pLockListener = new OLockListener( uno::Reference< lang::XComponent > ( static_cast< lang::XComponent* >( this ) ),
175 xInstance,
176 nModes,
177 xApproval );
178 m_xLockListener = uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( m_pLockListener ) );
179 m_pLockListener->Init();
181 catch( uno::Exception& )
183 dispose();
184 throw;
187 m_bInitialized = sal_True;
191 // XServiceInfo
192 // --------------------------------------------------------
193 OUString SAL_CALL OInstanceLocker::getImplementationName( )
194 throw (uno::RuntimeException)
196 return getImplementationName_static();
199 // --------------------------------------------------------
200 ::sal_Bool SAL_CALL OInstanceLocker::supportsService( const OUString& ServiceName )
201 throw (uno::RuntimeException)
203 uno::Sequence< OUString > aSeq = getSupportedServiceNames();
205 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
206 if ( ServiceName == aSeq[nInd] )
207 return sal_True;
209 return sal_False;
212 // --------------------------------------------------------
213 uno::Sequence< OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames()
214 throw (uno::RuntimeException)
216 return getSupportedServiceNames_static();
219 // Static methods
220 // --------------------------------------------------------
221 uno::Sequence< OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames_static()
223 const OUString aServiceName( "com.sun.star.embed.InstanceLocker" );
224 return uno::Sequence< OUString >( &aServiceName, 1 );
227 // --------------------------------------------------------
228 OUString SAL_CALL OInstanceLocker::getImplementationName_static()
230 return OUString( "com.sun.star.comp.embed.InstanceLocker" );
233 // --------------------------------------------------------
234 uno::Reference< uno::XInterface > SAL_CALL OInstanceLocker::Create(
235 const uno::Reference< uno::XComponentContext >& rxContext )
237 return static_cast< cppu::OWeakObject * >( new OInstanceLocker( rxContext ) );
242 // ====================================================================
243 // OLockListener
244 // ====================================================================
246 // --------------------------------------------------------
247 OLockListener::OLockListener( const uno::WeakReference< lang::XComponent >& xWrapper,
248 const uno::Reference< uno::XInterface >& xInstance,
249 sal_Int32 nMode,
250 const uno::Reference< embed::XActionsApproval > xApproval )
251 : m_xInstance( xInstance )
252 , m_xApproval( xApproval )
253 , m_xWrapper( xWrapper )
254 , m_bDisposed( sal_False )
255 , m_bInitialized( sal_False )
256 , m_nMode( nMode )
260 // --------------------------------------------------------
261 OLockListener::~OLockListener()
265 // --------------------------------------------------------
266 void OLockListener::Dispose()
268 ::osl::ResettableMutexGuard aGuard( m_aMutex );
270 if ( m_bDisposed )
271 return;
273 if ( m_nMode & embed::Actions::PREVENT_CLOSE )
277 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY );
278 if ( xCloseBroadcaster.is() )
279 xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) );
281 uno::Reference< util::XCloseable > xCloseable( m_xInstance, uno::UNO_QUERY );
282 if ( xCloseable.is() )
283 xCloseable->close( sal_True );
285 catch( uno::Exception& )
289 if ( m_nMode & embed::Actions::PREVENT_TERMINATION )
293 uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW );
294 xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
296 catch( uno::Exception& )
300 m_xInstance = uno::Reference< uno::XInterface >();
301 m_bDisposed = sal_True;
304 // XEventListener
305 // --------------------------------------------------------
306 void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent )
307 throw (uno::RuntimeException)
309 ::osl::ResettableMutexGuard aGuard( m_aMutex );
311 // object is disposed
312 if ( aEvent.Source == m_xInstance )
314 // the object does not listen for anything any more
315 m_nMode = 0;
317 // dispose the wrapper;
318 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
319 aGuard.clear();
320 if ( xComponent.is() )
322 try { xComponent->dispose(); }
323 catch( uno::Exception& ){}
329 // XCloseListener
330 // --------------------------------------------------------
331 void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_Bool )
332 throw (util::CloseVetoException, uno::RuntimeException)
334 // GetsOwnership parameter is always ignored, the user of the service must close the object always
335 ::osl::ResettableMutexGuard aGuard( m_aMutex );
336 if ( !m_bDisposed && aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_CLOSE ) )
340 uno::Reference< embed::XActionsApproval > xApprove = m_xApproval;
342 // unlock the mutex here
343 aGuard.clear();
345 if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_CLOSE ) )
346 throw util::CloseVetoException();
348 catch( util::CloseVetoException& )
350 // rethrow this exception
351 throw;
353 catch( uno::Exception& )
355 // no action should be done
360 // --------------------------------------------------------
361 void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent )
362 throw (uno::RuntimeException)
364 ::osl::ResettableMutexGuard aGuard( m_aMutex );
366 // object is closed, no reason to listen
367 if ( aEvent.Source == m_xInstance )
369 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( aEvent.Source, uno::UNO_QUERY );
370 if ( xCloseBroadcaster.is() )
372 xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) );
373 m_nMode &= ~embed::Actions::PREVENT_CLOSE;
374 if ( !m_nMode )
376 // dispose the wrapper;
377 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
378 aGuard.clear();
379 if ( xComponent.is() )
381 try { xComponent->dispose(); }
382 catch( uno::Exception& ){}
390 // XTerminateListener
391 // --------------------------------------------------------
392 void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent )
393 throw (frame::TerminationVetoException, uno::RuntimeException)
395 ::osl::ResettableMutexGuard aGuard( m_aMutex );
396 if ( aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_TERMINATION ) )
400 uno::Reference< embed::XActionsApproval > xApprove = m_xApproval;
402 // unlock the mutex here
403 aGuard.clear();
405 if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_TERMINATION ) )
406 throw frame::TerminationVetoException();
408 catch( frame::TerminationVetoException& )
410 // rethrow this exception
411 throw;
413 catch( uno::Exception& )
415 // no action should be done
420 // --------------------------------------------------------
421 void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent )
422 throw (uno::RuntimeException)
424 ::osl::ResettableMutexGuard aGuard( m_aMutex );
426 // object is terminated, no reason to listen
427 if ( aEvent.Source == m_xInstance )
429 uno::Reference< frame::XDesktop > xDesktop( aEvent.Source, uno::UNO_QUERY );
430 if ( xDesktop.is() )
434 xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
435 m_nMode &= ~embed::Actions::PREVENT_TERMINATION;
436 if ( !m_nMode )
438 // dispose the wrapper;
439 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
440 aGuard.clear();
441 if ( xComponent.is() )
443 try { xComponent->dispose(); }
444 catch( uno::Exception& ){}
448 catch( uno::Exception& )
455 // XInitialization
456 // --------------------------------------------------------
457 sal_Bool OLockListener::Init()
459 ::osl::ResettableMutexGuard aGuard( m_aMutex );
461 if ( m_bDisposed || m_bInitialized )
462 return sal_False;
466 if ( m_nMode & embed::Actions::PREVENT_CLOSE )
468 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY_THROW );
469 xCloseBroadcaster->addCloseListener( static_cast< util::XCloseListener* >( this ) );
472 if ( m_nMode & embed::Actions::PREVENT_TERMINATION )
474 uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW );
475 xDesktop->addTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
478 catch( uno::Exception& )
480 // dispose the wrapper;
481 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
482 aGuard.clear();
483 if ( xComponent.is() )
485 try { xComponent->dispose(); }
486 catch( uno::Exception& ){}
489 throw;
492 m_bInitialized = sal_True;
494 return sal_True;
497 void createRegistryInfo_OInstanceLocker()
499 static ::comphelper::module::OAutoRegistration< OInstanceLocker > aAutoRegistration;
502 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */