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"
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 // ====================================================================
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()
55 m_refCount
++; // to call dispose
59 catch ( uno::RuntimeException
& )
63 if ( m_pListenersContainer
)
65 delete m_pListenersContainer
;
66 m_pListenersContainer
= NULL
;
71 // --------------------------------------------------------
72 void SAL_CALL
OInstanceLocker::dispose()
73 throw (uno::RuntimeException
)
75 ::osl::MutexGuard
aGuard( m_aMutex
);
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
);
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
);
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();
130 throw lang::DisposedException(); // TODO
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
>(),
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
>(),
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
>(),
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
>(),
174 m_pLockListener
= new OLockListener( uno::Reference
< lang::XComponent
> ( static_cast< lang::XComponent
* >( this ) ),
178 m_xLockListener
= uno::Reference
< uno::XInterface
>( static_cast< OWeakObject
* >( m_pLockListener
) );
179 m_pLockListener
->Init();
181 catch( uno::Exception
& )
187 m_bInitialized
= sal_True
;
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
] )
212 // --------------------------------------------------------
213 uno::Sequence
< OUString
> SAL_CALL
OInstanceLocker::getSupportedServiceNames()
214 throw (uno::RuntimeException
)
216 return getSupportedServiceNames_static();
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 // ====================================================================
244 // ====================================================================
246 // --------------------------------------------------------
247 OLockListener::OLockListener( const uno::WeakReference
< lang::XComponent
>& xWrapper
,
248 const uno::Reference
< uno::XInterface
>& xInstance
,
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
)
260 // --------------------------------------------------------
261 OLockListener::~OLockListener()
265 // --------------------------------------------------------
266 void OLockListener::Dispose()
268 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
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
;
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
317 // dispose the wrapper;
318 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
320 if ( xComponent
.is() )
322 try { xComponent
->dispose(); }
323 catch( uno::Exception
& ){}
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
345 if ( xApprove
.is() && xApprove
->approveAction( embed::Actions::PREVENT_CLOSE
) )
346 throw util::CloseVetoException();
348 catch( util::CloseVetoException
& )
350 // rethrow this exception
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
;
376 // dispose the wrapper;
377 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
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
405 if ( xApprove
.is() && xApprove
->approveAction( embed::Actions::PREVENT_TERMINATION
) )
406 throw frame::TerminationVetoException();
408 catch( frame::TerminationVetoException
& )
410 // rethrow this exception
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
);
434 xDesktop
->removeTerminateListener( static_cast< frame::XTerminateListener
* >( this ) );
435 m_nMode
&= ~embed::Actions::PREVENT_TERMINATION
;
438 // dispose the wrapper;
439 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
441 if ( xComponent
.is() )
443 try { xComponent
->dispose(); }
444 catch( uno::Exception
& ){}
448 catch( uno::Exception
& )
456 // --------------------------------------------------------
457 sal_Bool
OLockListener::Init()
459 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
461 if ( m_bDisposed
|| m_bInitialized
)
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
);
483 if ( xComponent
.is() )
485 try { xComponent
->dispose(); }
486 catch( uno::Exception
& ){}
492 m_bInitialized
= sal_True
;
497 void createRegistryInfo_OInstanceLocker()
499 static ::comphelper::module::OAutoRegistration
< OInstanceLocker
> aAutoRegistration
;
502 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */