1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
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()
57 m_refCount
++; // to call dispose
61 catch ( uno::RuntimeException
& )
65 if ( m_pListenersContainer
)
67 delete m_pListenersContainer
;
68 m_pListenersContainer
= NULL
;
74 void SAL_CALL
OInstanceLocker::dispose()
75 throw (uno::RuntimeException
, std::exception
)
77 ::osl::MutexGuard
aGuard( m_aMutex
);
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
>();
100 void SAL_CALL
OInstanceLocker::addEventListener( const uno::Reference
< lang::XEventListener
>& xListener
)
101 throw (uno::RuntimeException
, std::exception
)
103 ::osl::MutexGuard
aGuard( m_aMutex
);
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
);
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();
132 throw lang::DisposedException(); // TODO
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
>(),
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
>(),
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
>(),
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
>(),
176 m_pLockListener
= new OLockListener( uno::Reference
< lang::XComponent
> ( static_cast< lang::XComponent
* >( this ) ),
180 m_xLockListener
= uno::Reference
< uno::XInterface
>( static_cast< OWeakObject
* >( m_pLockListener
) );
181 m_pLockListener
->Init();
183 catch( uno::Exception
& )
189 m_bInitialized
= true;
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();
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
) );
239 OLockListener::OLockListener( const uno::WeakReference
< lang::XComponent
>& xWrapper
,
240 const uno::Reference
< uno::XInterface
>& xInstance
,
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 )
253 OLockListener::~OLockListener()
258 void OLockListener::Dispose()
260 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
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
>();
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
309 // dispose the wrapper;
310 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
312 if ( xComponent
.is() )
314 try { xComponent
->dispose(); }
315 catch( uno::Exception
& ){}
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
337 if ( xApprove
.is() && xApprove
->approveAction( embed::Actions::PREVENT_CLOSE
) )
338 throw util::CloseVetoException();
340 catch( util::CloseVetoException
& )
342 // rethrow this exception
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
;
368 // dispose the wrapper;
369 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
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
397 if ( xApprove
.is() && xApprove
->approveAction( embed::Actions::PREVENT_TERMINATION
) )
398 throw frame::TerminationVetoException();
400 catch( frame::TerminationVetoException
& )
402 // rethrow this exception
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
);
426 xDesktop
->removeTerminateListener( static_cast< frame::XTerminateListener
* >( this ) );
427 m_nMode
&= ~embed::Actions::PREVENT_TERMINATION
;
430 // dispose the wrapper;
431 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
433 if ( xComponent
.is() )
435 try { xComponent
->dispose(); }
436 catch( uno::Exception
& ){}
440 catch( uno::Exception
& )
449 bool OLockListener::Init()
451 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
453 if ( m_bDisposed
|| m_bInitialized
)
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
);
475 if ( xComponent
.is() )
477 try { xComponent
->dispose(); }
478 catch( uno::Exception
& ){}
484 m_bInitialized
= true;
489 void createRegistryInfo_OInstanceLocker()
491 static ::comphelper::module::OAutoRegistration
< OInstanceLocker
> aAutoRegistration
;
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */