bump product version to 5.0.4.1
[LibreOffice.git] / comphelper / source / misc / instancelocker.cxx
blob204d1a9baca30eaeb0c47db8eaeb45604888e205
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"
22 #include "comphelper_services.hxx"
23 #include <cppuhelper/supportsservice.hxx>
25 #include <com/sun/star/util/XCloseBroadcaster.hpp>
26 #include <com/sun/star/util/XCloseable.hpp>
27 #include <com/sun/star/lang/DisposedException.hpp>
28 #include <com/sun/star/lang/IllegalArgumentException.hpp>
29 #include <com/sun/star/frame/XDesktop.hpp>
30 #include <com/sun/star/frame/DoubleInitializationException.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include "instancelocker.hxx"
35 using namespace ::com::sun::star;
39 // OInstanceLocker
43 OInstanceLocker::OInstanceLocker( const uno::Reference< uno::XComponentContext >& xContext )
44 : m_xContext( xContext )
45 , m_pLockListener( NULL )
46 , m_pListenersContainer( NULL )
47 , m_bDisposed( false )
48 , m_bInitialized( false )
53 OInstanceLocker::~OInstanceLocker()
55 if ( !m_bDisposed )
57 m_refCount++; // to call dispose
58 try {
59 dispose();
61 catch ( uno::RuntimeException& )
65 if ( m_pListenersContainer )
67 delete m_pListenersContainer;
68 m_pListenersContainer = NULL;
72 // XComponent
74 void SAL_CALL OInstanceLocker::dispose()
75 throw (uno::RuntimeException, std::exception)
77 ::osl::MutexGuard aGuard( m_aMutex );
79 if ( m_bDisposed )
80 throw lang::DisposedException();
82 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
83 if ( m_pListenersContainer )
84 m_pListenersContainer->disposeAndClear( aSource );
86 if ( m_xLockListener.is() )
88 if ( m_pLockListener )
90 m_pLockListener->Dispose();
91 m_pLockListener = NULL;
93 m_xLockListener = uno::Reference< uno::XInterface >();
96 m_bDisposed = true;
100 void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
101 throw (uno::RuntimeException, std::exception)
103 ::osl::MutexGuard aGuard( m_aMutex );
104 if ( m_bDisposed )
105 throw lang::DisposedException(); // TODO
107 if ( !m_pListenersContainer )
108 m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex );
110 m_pListenersContainer->addInterface( xListener );
114 void SAL_CALL OInstanceLocker::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
115 throw (uno::RuntimeException, std::exception)
117 ::osl::MutexGuard aGuard( m_aMutex );
118 if ( m_pListenersContainer )
119 m_pListenersContainer->removeInterface( xListener );
122 // XInitialization
124 void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArguments )
125 throw (uno::Exception, uno::RuntimeException, std::exception)
127 ::osl::MutexGuard aGuard( m_aMutex );
128 if ( m_bInitialized )
129 throw frame::DoubleInitializationException();
131 if ( m_bDisposed )
132 throw lang::DisposedException(); // TODO
134 if ( !m_refCount )
135 throw uno::RuntimeException(); // the object must be refcounted already!
137 uno::Reference< uno::XInterface > xInstance;
138 uno::Reference< embed::XActionsApproval > xApproval;
139 sal_Int32 nModes = 0;
143 sal_Int32 nLen = aArguments.getLength();
144 if ( nLen < 2 || nLen > 3 )
145 throw lang::IllegalArgumentException(
146 OUString( "Wrong count of parameters!" ),
147 uno::Reference< uno::XInterface >(),
148 0 );
150 if ( !( aArguments[0] >>= xInstance ) || !xInstance.is() )
151 throw lang::IllegalArgumentException(
152 OUString( "Nonempty reference is expected as the first argument!" ),
153 uno::Reference< uno::XInterface >(),
154 0 );
156 if (
157 !( aArguments[1] >>= nModes ) ||
159 !( nModes & embed::Actions::PREVENT_CLOSE ) &&
160 !( nModes & embed::Actions::PREVENT_TERMINATION )
164 throw lang::IllegalArgumentException(
165 OUString("The correct modes set is expected as the second argument!"),
166 uno::Reference< uno::XInterface >(),
167 0 );
170 if ( nLen == 3 && !( aArguments[2] >>= xApproval ) )
171 throw lang::IllegalArgumentException(
172 OUString( "If the third argument is provided, it must be XActionsApproval implementation!" ),
173 uno::Reference< uno::XInterface >(),
174 0 );
176 m_pLockListener = new OLockListener( uno::Reference< lang::XComponent > ( static_cast< lang::XComponent* >( this ) ),
177 xInstance,
178 nModes,
179 xApproval );
180 m_xLockListener = uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( m_pLockListener ) );
181 m_pLockListener->Init();
183 catch( uno::Exception& )
185 dispose();
186 throw;
189 m_bInitialized = true;
192 // XServiceInfo
193 OUString SAL_CALL OInstanceLocker::getImplementationName( )
194 throw (uno::RuntimeException, std::exception)
196 return getImplementationName_static();
199 sal_Bool SAL_CALL OInstanceLocker::supportsService( const OUString& ServiceName )
200 throw (uno::RuntimeException, std::exception)
202 return cppu::supportsService(this, ServiceName);
205 uno::Sequence< OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames()
206 throw (uno::RuntimeException, std::exception)
208 return getSupportedServiceNames_static();
211 // Static methods
213 uno::Sequence< OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames_static()
215 const OUString aServiceName( "com.sun.star.embed.InstanceLocker" );
216 return uno::Sequence< OUString >( &aServiceName, 1 );
220 OUString SAL_CALL OInstanceLocker::getImplementationName_static()
222 return OUString( "com.sun.star.comp.embed.InstanceLocker" );
226 uno::Reference< uno::XInterface > SAL_CALL OInstanceLocker::Create(
227 const uno::Reference< uno::XComponentContext >& rxContext )
229 return static_cast< cppu::OWeakObject * >( new OInstanceLocker( rxContext ) );
235 // OLockListener
239 OLockListener::OLockListener( const uno::WeakReference< lang::XComponent >& xWrapper,
240 const uno::Reference< uno::XInterface >& xInstance,
241 sal_Int32 nMode,
242 const uno::Reference< embed::XActionsApproval >& rApproval )
243 : m_xInstance( xInstance )
244 , m_xApproval( rApproval )
245 , m_xWrapper( xWrapper )
246 , m_bDisposed( false )
247 , m_bInitialized( false )
248 , m_nMode( nMode )
253 OLockListener::~OLockListener()
258 void OLockListener::Dispose()
260 ::osl::ResettableMutexGuard aGuard( m_aMutex );
262 if ( m_bDisposed )
263 return;
265 if ( m_nMode & embed::Actions::PREVENT_CLOSE )
269 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY );
270 if ( xCloseBroadcaster.is() )
271 xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) );
273 uno::Reference< util::XCloseable > xCloseable( m_xInstance, uno::UNO_QUERY );
274 if ( xCloseable.is() )
275 xCloseable->close( sal_True );
277 catch( uno::Exception& )
281 if ( m_nMode & embed::Actions::PREVENT_TERMINATION )
285 uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW );
286 xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
288 catch( uno::Exception& )
292 m_xInstance = uno::Reference< uno::XInterface >();
293 m_bDisposed = true;
296 // XEventListener
298 void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent )
299 throw (uno::RuntimeException, std::exception)
301 ::osl::ResettableMutexGuard aGuard( m_aMutex );
303 // object is disposed
304 if ( aEvent.Source == m_xInstance )
306 // the object does not listen for anything any more
307 m_nMode = 0;
309 // dispose the wrapper;
310 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
311 aGuard.clear();
312 if ( xComponent.is() )
314 try { xComponent->dispose(); }
315 catch( uno::Exception& ){}
321 // XCloseListener
323 void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_Bool )
324 throw (util::CloseVetoException, uno::RuntimeException, std::exception)
326 // GetsOwnership parameter is always ignored, the user of the service must close the object always
327 ::osl::ResettableMutexGuard aGuard( m_aMutex );
328 if ( !m_bDisposed && aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_CLOSE ) )
332 uno::Reference< embed::XActionsApproval > xApprove = m_xApproval;
334 // unlock the mutex here
335 aGuard.clear();
337 if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_CLOSE ) )
338 throw util::CloseVetoException();
340 catch( util::CloseVetoException& )
342 // rethrow this exception
343 throw;
345 catch( uno::Exception& )
347 // no action should be done
353 void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent )
354 throw (uno::RuntimeException, std::exception)
356 ::osl::ResettableMutexGuard aGuard( m_aMutex );
358 // object is closed, no reason to listen
359 if ( aEvent.Source == m_xInstance )
361 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( aEvent.Source, uno::UNO_QUERY );
362 if ( xCloseBroadcaster.is() )
364 xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) );
365 m_nMode &= ~embed::Actions::PREVENT_CLOSE;
366 if ( !m_nMode )
368 // dispose the wrapper;
369 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
370 aGuard.clear();
371 if ( xComponent.is() )
373 try { xComponent->dispose(); }
374 catch( uno::Exception& ){}
382 // XTerminateListener
384 void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent )
385 throw (frame::TerminationVetoException, uno::RuntimeException, std::exception)
387 ::osl::ResettableMutexGuard aGuard( m_aMutex );
388 if ( aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_TERMINATION ) )
392 uno::Reference< embed::XActionsApproval > xApprove = m_xApproval;
394 // unlock the mutex here
395 aGuard.clear();
397 if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_TERMINATION ) )
398 throw frame::TerminationVetoException();
400 catch( frame::TerminationVetoException& )
402 // rethrow this exception
403 throw;
405 catch( uno::Exception& )
407 // no action should be done
413 void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent )
414 throw (uno::RuntimeException, std::exception)
416 ::osl::ResettableMutexGuard aGuard( m_aMutex );
418 // object is terminated, no reason to listen
419 if ( aEvent.Source == m_xInstance )
421 uno::Reference< frame::XDesktop > xDesktop( aEvent.Source, uno::UNO_QUERY );
422 if ( xDesktop.is() )
426 xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
427 m_nMode &= ~embed::Actions::PREVENT_TERMINATION;
428 if ( !m_nMode )
430 // dispose the wrapper;
431 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
432 aGuard.clear();
433 if ( xComponent.is() )
435 try { xComponent->dispose(); }
436 catch( uno::Exception& ){}
440 catch( uno::Exception& )
447 // XInitialization
449 bool OLockListener::Init()
451 ::osl::ResettableMutexGuard aGuard( m_aMutex );
453 if ( m_bDisposed || m_bInitialized )
454 return false;
458 if ( m_nMode & embed::Actions::PREVENT_CLOSE )
460 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY_THROW );
461 xCloseBroadcaster->addCloseListener( static_cast< util::XCloseListener* >( this ) );
464 if ( m_nMode & embed::Actions::PREVENT_TERMINATION )
466 uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW );
467 xDesktop->addTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
470 catch( uno::Exception& )
472 // dispose the wrapper;
473 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
474 aGuard.clear();
475 if ( xComponent.is() )
477 try { xComponent->dispose(); }
478 catch( uno::Exception& ){}
481 throw;
484 m_bInitialized = true;
486 return true;
489 void createRegistryInfo_OInstanceLocker()
491 static ::comphelper::module::OAutoRegistration< OInstanceLocker > aAutoRegistration;
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */