merge the formfield patch from ooo-build
[ooovba.git] / comphelper / source / misc / instancelocker.cxx
blob054e842f66feaca5559f05b89cdc9a5e5f2bb888
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: instancelocker.cxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_comphelper.hxx"
34 #include "comphelper_module.hxx"
36 #include <com/sun/star/util/XCloseBroadcaster.hpp>
37 #include <com/sun/star/util/XCloseable.hpp>
38 #include <com/sun/star/lang/DisposedException.hpp>
39 #include <com/sun/star/lang/IllegalArgumentException.hpp>
40 #include <com/sun/star/frame/XDesktop.hpp>
41 #include <com/sun/star/frame/DoubleInitializationException.hpp>
42 #include <com/sun/star/frame/DoubleInitializationException.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include "instancelocker.hxx"
47 using namespace ::com::sun::star;
50 // ====================================================================
51 // OInstanceLocker
52 // ====================================================================
54 // --------------------------------------------------------
55 OInstanceLocker::OInstanceLocker( const uno::Reference< uno::XComponentContext >& xContext )
56 : m_xContext( xContext )
57 , m_pLockListener( NULL )
58 , m_pListenersContainer( NULL )
59 , m_bDisposed( sal_False )
60 , m_bInitialized( sal_False )
64 // --------------------------------------------------------
65 OInstanceLocker::~OInstanceLocker()
67 if ( !m_bDisposed )
69 m_refCount++; // to call dispose
70 try {
71 dispose();
73 catch ( uno::RuntimeException& )
77 if ( m_pListenersContainer )
79 delete m_pListenersContainer;
80 m_pListenersContainer = NULL;
84 // XComponent
85 // --------------------------------------------------------
86 void SAL_CALL OInstanceLocker::dispose()
87 throw (uno::RuntimeException)
89 ::osl::MutexGuard aGuard( m_aMutex );
91 if ( m_bDisposed )
92 throw lang::DisposedException();
94 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
95 if ( m_pListenersContainer )
96 m_pListenersContainer->disposeAndClear( aSource );
98 if ( m_xLockListener.is() )
100 if ( m_pLockListener )
102 m_pLockListener->Dispose();
103 m_pLockListener = NULL;
105 m_xLockListener = uno::Reference< uno::XInterface >();
108 m_bDisposed = sal_True;
111 // --------------------------------------------------------
112 void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
113 throw (uno::RuntimeException)
115 ::osl::MutexGuard aGuard( m_aMutex );
116 if ( m_bDisposed )
117 throw lang::DisposedException(); // TODO
119 if ( !m_pListenersContainer )
120 m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex );
122 m_pListenersContainer->addInterface( xListener );
125 // --------------------------------------------------------
126 void SAL_CALL OInstanceLocker::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
127 throw (uno::RuntimeException)
129 ::osl::MutexGuard aGuard( m_aMutex );
130 if ( m_pListenersContainer )
131 m_pListenersContainer->removeInterface( xListener );
134 // XInitialization
135 // --------------------------------------------------------
136 void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArguments )
137 throw (uno::Exception, uno::RuntimeException)
139 ::osl::MutexGuard aGuard( m_aMutex );
140 if ( m_bInitialized )
141 throw frame::DoubleInitializationException();
143 if ( m_bDisposed )
144 throw lang::DisposedException(); // TODO
146 if ( !m_refCount )
147 throw uno::RuntimeException(); // the object must be refcounted already!
149 uno::Reference< uno::XInterface > xInstance;
150 uno::Reference< embed::XActionsApproval > xApproval;
151 sal_Int32 nModes = 0;
155 sal_Int32 nLen = aArguments.getLength();
156 if ( nLen < 2 || nLen > 3 )
157 throw lang::IllegalArgumentException(
158 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Wrong count of parameters!" ) ),
159 uno::Reference< uno::XInterface >(),
160 0 );
162 if ( !( aArguments[0] >>= xInstance ) || !xInstance.is() )
163 throw lang::IllegalArgumentException(
164 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Nonempty reference is expected as the first argument!" ) ),
165 uno::Reference< uno::XInterface >(),
166 0 );
168 if (
169 !( aArguments[1] >>= nModes ) ||
171 !( nModes & embed::Actions::PREVENT_CLOSE ) &&
172 !( nModes & embed::Actions::PREVENT_TERMINATION )
176 throw lang::IllegalArgumentException(
177 ::rtl::OUString(
178 RTL_CONSTASCII_USTRINGPARAM("The correct modes set is expected as the second argument!" ) ),
179 uno::Reference< uno::XInterface >(),
180 0 );
183 if ( nLen == 3 && !( aArguments[2] >>= xApproval ) )
184 throw lang::IllegalArgumentException(
185 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("If the third argument is provided, it must be XActionsApproval implementation!" ) ),
186 uno::Reference< uno::XInterface >(),
187 0 );
189 m_pLockListener = new OLockListener( uno::Reference< lang::XComponent > ( static_cast< lang::XComponent* >( this ) ),
190 xInstance,
191 nModes,
192 xApproval );
193 m_xLockListener = uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( m_pLockListener ) );
194 m_pLockListener->Init();
196 catch( uno::Exception& )
198 dispose();
199 throw;
202 m_bInitialized = sal_True;
206 // XServiceInfo
207 // --------------------------------------------------------
208 ::rtl::OUString SAL_CALL OInstanceLocker::getImplementationName( )
209 throw (uno::RuntimeException)
211 return getImplementationName_static();
214 // --------------------------------------------------------
215 ::sal_Bool SAL_CALL OInstanceLocker::supportsService( const ::rtl::OUString& ServiceName )
216 throw (uno::RuntimeException)
218 uno::Sequence< ::rtl::OUString > aSeq = getSupportedServiceNames();
220 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
221 if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
222 return sal_True;
224 return sal_False;
227 // --------------------------------------------------------
228 uno::Sequence< ::rtl::OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames()
229 throw (uno::RuntimeException)
231 return getSupportedServiceNames_static();
234 // Static methods
235 // --------------------------------------------------------
236 uno::Sequence< ::rtl::OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames_static()
238 const rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.InstanceLocker" ) );
239 return uno::Sequence< rtl::OUString >( &aServiceName, 1 );
242 // --------------------------------------------------------
243 ::rtl::OUString SAL_CALL OInstanceLocker::getImplementationName_static()
245 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.embed.InstanceLocker" ) );
248 // --------------------------------------------------------
249 uno::Reference< uno::XInterface > SAL_CALL OInstanceLocker::Create(
250 const uno::Reference< uno::XComponentContext >& rxContext )
252 return static_cast< cppu::OWeakObject * >( new OInstanceLocker( rxContext ) );
257 // ====================================================================
258 // OLockListener
259 // ====================================================================
261 // --------------------------------------------------------
262 OLockListener::OLockListener( const uno::WeakReference< lang::XComponent >& xWrapper,
263 const uno::Reference< uno::XInterface >& xInstance,
264 sal_Int32 nMode,
265 const uno::Reference< embed::XActionsApproval > xApproval )
266 : m_xInstance( xInstance )
267 , m_xApproval( xApproval )
268 , m_xWrapper( xWrapper )
269 , m_bDisposed( sal_False )
270 , m_bInitialized( sal_False )
271 , m_nMode( nMode )
275 // --------------------------------------------------------
276 OLockListener::~OLockListener()
280 // --------------------------------------------------------
281 void OLockListener::Dispose()
283 ::osl::ResettableMutexGuard aGuard( m_aMutex );
285 if ( m_bDisposed )
286 return;
288 if ( m_nMode & embed::Actions::PREVENT_CLOSE )
292 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY );
293 if ( xCloseBroadcaster.is() )
294 xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) );
296 uno::Reference< util::XCloseable > xCloseable( m_xInstance, uno::UNO_QUERY );
297 if ( xCloseable.is() )
298 xCloseable->close( sal_True );
300 catch( uno::Exception& )
304 if ( m_nMode & embed::Actions::PREVENT_TERMINATION )
308 uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW );
309 xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
311 catch( uno::Exception& )
315 m_xInstance = uno::Reference< uno::XInterface >();
316 m_bDisposed = sal_True;
319 // XEventListener
320 // --------------------------------------------------------
321 void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent )
322 throw (uno::RuntimeException)
324 ::osl::ResettableMutexGuard aGuard( m_aMutex );
326 // object is disposed
327 if ( aEvent.Source == m_xInstance )
329 // the object does not listen for anything any more
330 m_nMode = 0;
332 // dispose the wrapper;
333 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
334 aGuard.clear();
335 if ( xComponent.is() )
337 try { xComponent->dispose(); }
338 catch( uno::Exception& ){}
344 // XCloseListener
345 // --------------------------------------------------------
346 void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_Bool )
347 throw (util::CloseVetoException, uno::RuntimeException)
349 // GetsOwnership parameter is always ignored, the user of the service must close the object always
350 ::osl::ResettableMutexGuard aGuard( m_aMutex );
351 if ( !m_bDisposed && aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_CLOSE ) )
355 uno::Reference< embed::XActionsApproval > xApprove = m_xApproval;
357 // unlock the mutex here
358 aGuard.clear();
360 if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_CLOSE ) )
361 throw util::CloseVetoException();
363 catch( util::CloseVetoException& )
365 // rethrow this exception
366 throw;
368 catch( uno::Exception& )
370 // no action should be done
375 // --------------------------------------------------------
376 void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent )
377 throw (uno::RuntimeException)
379 ::osl::ResettableMutexGuard aGuard( m_aMutex );
381 // object is closed, no reason to listen
382 if ( aEvent.Source == m_xInstance )
384 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( aEvent.Source, uno::UNO_QUERY );
385 if ( xCloseBroadcaster.is() )
387 xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) );
388 m_nMode &= ~embed::Actions::PREVENT_CLOSE;
389 if ( !m_nMode )
391 // dispose the wrapper;
392 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
393 aGuard.clear();
394 if ( xComponent.is() )
396 try { xComponent->dispose(); }
397 catch( uno::Exception& ){}
405 // XTerminateListener
406 // --------------------------------------------------------
407 void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent )
408 throw (frame::TerminationVetoException, uno::RuntimeException)
410 ::osl::ResettableMutexGuard aGuard( m_aMutex );
411 if ( aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_TERMINATION ) )
415 uno::Reference< embed::XActionsApproval > xApprove = m_xApproval;
417 // unlock the mutex here
418 aGuard.clear();
420 if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_TERMINATION ) )
421 throw frame::TerminationVetoException();
423 catch( frame::TerminationVetoException& )
425 // rethrow this exception
426 throw;
428 catch( uno::Exception& )
430 // no action should be done
435 // --------------------------------------------------------
436 void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent )
437 throw (uno::RuntimeException)
439 ::osl::ResettableMutexGuard aGuard( m_aMutex );
441 // object is terminated, no reason to listen
442 if ( aEvent.Source == m_xInstance )
444 uno::Reference< frame::XDesktop > xDesktop( aEvent.Source, uno::UNO_QUERY );
445 if ( xDesktop.is() )
449 xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
450 m_nMode &= ~embed::Actions::PREVENT_TERMINATION;
451 if ( !m_nMode )
453 // dispose the wrapper;
454 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
455 aGuard.clear();
456 if ( xComponent.is() )
458 try { xComponent->dispose(); }
459 catch( uno::Exception& ){}
463 catch( uno::Exception& )
470 // XInitialization
471 // --------------------------------------------------------
472 sal_Bool OLockListener::Init()
474 ::osl::ResettableMutexGuard aGuard( m_aMutex );
476 if ( m_bDisposed || m_bInitialized )
477 return sal_False;
481 if ( m_nMode & embed::Actions::PREVENT_CLOSE )
483 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY_THROW );
484 xCloseBroadcaster->addCloseListener( static_cast< util::XCloseListener* >( this ) );
487 if ( m_nMode & embed::Actions::PREVENT_TERMINATION )
489 uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW );
490 xDesktop->addTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
493 catch( uno::Exception& )
495 // dispose the wrapper;
496 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
497 aGuard.clear();
498 if ( xComponent.is() )
500 try { xComponent->dispose(); }
501 catch( uno::Exception& ){}
504 throw;
507 m_bInitialized = sal_True;
509 return sal_True;
512 void createRegistryInfo_OInstanceLocker()
514 static ::comphelper::module::OAutoRegistration< OInstanceLocker > aAutoRegistration;