1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
31 #include "comphelper_module.hxx"
33 #include <com/sun/star/util/XCloseBroadcaster.hpp>
34 #include <com/sun/star/util/XCloseable.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <com/sun/star/lang/IllegalArgumentException.hpp>
37 #include <com/sun/star/frame/XDesktop.hpp>
38 #include <com/sun/star/frame/DoubleInitializationException.hpp>
39 #include <com/sun/star/frame/DoubleInitializationException.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include "instancelocker.hxx"
44 using namespace ::com::sun::star
;
47 // ====================================================================
49 // ====================================================================
51 // --------------------------------------------------------
52 OInstanceLocker::OInstanceLocker( const uno::Reference
< uno::XComponentContext
>& xContext
)
53 : m_xContext( xContext
)
54 , m_pLockListener( NULL
)
55 , m_pListenersContainer( NULL
)
56 , m_bDisposed( sal_False
)
57 , m_bInitialized( sal_False
)
61 // --------------------------------------------------------
62 OInstanceLocker::~OInstanceLocker()
66 m_refCount
++; // to call dispose
70 catch ( uno::RuntimeException
& )
74 if ( m_pListenersContainer
)
76 delete m_pListenersContainer
;
77 m_pListenersContainer
= NULL
;
82 // --------------------------------------------------------
83 void SAL_CALL
OInstanceLocker::dispose()
84 throw (uno::RuntimeException
)
86 ::osl::MutexGuard
aGuard( m_aMutex
);
89 throw lang::DisposedException();
91 lang::EventObject
aSource( static_cast< ::cppu::OWeakObject
* >(this) );
92 if ( m_pListenersContainer
)
93 m_pListenersContainer
->disposeAndClear( aSource
);
95 if ( m_xLockListener
.is() )
97 if ( m_pLockListener
)
99 m_pLockListener
->Dispose();
100 m_pLockListener
= NULL
;
102 m_xLockListener
= uno::Reference
< uno::XInterface
>();
105 m_bDisposed
= sal_True
;
108 // --------------------------------------------------------
109 void SAL_CALL
OInstanceLocker::addEventListener( const uno::Reference
< lang::XEventListener
>& xListener
)
110 throw (uno::RuntimeException
)
112 ::osl::MutexGuard
aGuard( m_aMutex
);
114 throw lang::DisposedException(); // TODO
116 if ( !m_pListenersContainer
)
117 m_pListenersContainer
= new ::cppu::OInterfaceContainerHelper( m_aMutex
);
119 m_pListenersContainer
->addInterface( xListener
);
122 // --------------------------------------------------------
123 void SAL_CALL
OInstanceLocker::removeEventListener( const uno::Reference
< lang::XEventListener
>& xListener
)
124 throw (uno::RuntimeException
)
126 ::osl::MutexGuard
aGuard( m_aMutex
);
127 if ( m_pListenersContainer
)
128 m_pListenersContainer
->removeInterface( xListener
);
132 // --------------------------------------------------------
133 void SAL_CALL
OInstanceLocker::initialize( const uno::Sequence
< uno::Any
>& aArguments
)
134 throw (uno::Exception
, uno::RuntimeException
)
136 ::osl::MutexGuard
aGuard( m_aMutex
);
137 if ( m_bInitialized
)
138 throw frame::DoubleInitializationException();
141 throw lang::DisposedException(); // TODO
144 throw uno::RuntimeException(); // the object must be refcounted already!
146 uno::Reference
< uno::XInterface
> xInstance
;
147 uno::Reference
< embed::XActionsApproval
> xApproval
;
148 sal_Int32 nModes
= 0;
152 sal_Int32 nLen
= aArguments
.getLength();
153 if ( nLen
< 2 || nLen
> 3 )
154 throw lang::IllegalArgumentException(
155 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Wrong count of parameters!" ) ),
156 uno::Reference
< uno::XInterface
>(),
159 if ( !( aArguments
[0] >>= xInstance
) || !xInstance
.is() )
160 throw lang::IllegalArgumentException(
161 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Nonempty reference is expected as the first argument!" ) ),
162 uno::Reference
< uno::XInterface
>(),
166 !( aArguments
[1] >>= nModes
) ||
168 !( nModes
& embed::Actions::PREVENT_CLOSE
) &&
169 !( nModes
& embed::Actions::PREVENT_TERMINATION
)
173 throw lang::IllegalArgumentException(
175 RTL_CONSTASCII_USTRINGPARAM("The correct modes set is expected as the second argument!" ) ),
176 uno::Reference
< uno::XInterface
>(),
180 if ( nLen
== 3 && !( aArguments
[2] >>= xApproval
) )
181 throw lang::IllegalArgumentException(
182 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("If the third argument is provided, it must be XActionsApproval implementation!" ) ),
183 uno::Reference
< uno::XInterface
>(),
186 m_pLockListener
= new OLockListener( uno::Reference
< lang::XComponent
> ( static_cast< lang::XComponent
* >( this ) ),
190 m_xLockListener
= uno::Reference
< uno::XInterface
>( static_cast< OWeakObject
* >( m_pLockListener
) );
191 m_pLockListener
->Init();
193 catch( uno::Exception
& )
199 m_bInitialized
= sal_True
;
204 // --------------------------------------------------------
205 ::rtl::OUString SAL_CALL
OInstanceLocker::getImplementationName( )
206 throw (uno::RuntimeException
)
208 return getImplementationName_static();
211 // --------------------------------------------------------
212 ::sal_Bool SAL_CALL
OInstanceLocker::supportsService( const ::rtl::OUString
& ServiceName
)
213 throw (uno::RuntimeException
)
215 uno::Sequence
< ::rtl::OUString
> aSeq
= getSupportedServiceNames();
217 for ( sal_Int32 nInd
= 0; nInd
< aSeq
.getLength(); nInd
++ )
218 if ( ServiceName
.compareTo( aSeq
[nInd
] ) == 0 )
224 // --------------------------------------------------------
225 uno::Sequence
< ::rtl::OUString
> SAL_CALL
OInstanceLocker::getSupportedServiceNames()
226 throw (uno::RuntimeException
)
228 return getSupportedServiceNames_static();
232 // --------------------------------------------------------
233 uno::Sequence
< ::rtl::OUString
> SAL_CALL
OInstanceLocker::getSupportedServiceNames_static()
235 const rtl::OUString
aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.InstanceLocker" ) );
236 return uno::Sequence
< rtl::OUString
>( &aServiceName
, 1 );
239 // --------------------------------------------------------
240 ::rtl::OUString SAL_CALL
OInstanceLocker::getImplementationName_static()
242 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.embed.InstanceLocker" ) );
245 // --------------------------------------------------------
246 uno::Reference
< uno::XInterface
> SAL_CALL
OInstanceLocker::Create(
247 const uno::Reference
< uno::XComponentContext
>& rxContext
)
249 return static_cast< cppu::OWeakObject
* >( new OInstanceLocker( rxContext
) );
254 // ====================================================================
256 // ====================================================================
258 // --------------------------------------------------------
259 OLockListener::OLockListener( const uno::WeakReference
< lang::XComponent
>& xWrapper
,
260 const uno::Reference
< uno::XInterface
>& xInstance
,
262 const uno::Reference
< embed::XActionsApproval
> xApproval
)
263 : m_xInstance( xInstance
)
264 , m_xApproval( xApproval
)
265 , m_xWrapper( xWrapper
)
266 , m_bDisposed( sal_False
)
267 , m_bInitialized( sal_False
)
272 // --------------------------------------------------------
273 OLockListener::~OLockListener()
277 // --------------------------------------------------------
278 void OLockListener::Dispose()
280 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
285 if ( m_nMode
& embed::Actions::PREVENT_CLOSE
)
289 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xInstance
, uno::UNO_QUERY
);
290 if ( xCloseBroadcaster
.is() )
291 xCloseBroadcaster
->removeCloseListener( static_cast< util::XCloseListener
* >( this ) );
293 uno::Reference
< util::XCloseable
> xCloseable( m_xInstance
, uno::UNO_QUERY
);
294 if ( xCloseable
.is() )
295 xCloseable
->close( sal_True
);
297 catch( uno::Exception
& )
301 if ( m_nMode
& embed::Actions::PREVENT_TERMINATION
)
305 uno::Reference
< frame::XDesktop
> xDesktop( m_xInstance
, uno::UNO_QUERY_THROW
);
306 xDesktop
->removeTerminateListener( static_cast< frame::XTerminateListener
* >( this ) );
308 catch( uno::Exception
& )
312 m_xInstance
= uno::Reference
< uno::XInterface
>();
313 m_bDisposed
= sal_True
;
317 // --------------------------------------------------------
318 void SAL_CALL
OLockListener::disposing( const lang::EventObject
& aEvent
)
319 throw (uno::RuntimeException
)
321 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
323 // object is disposed
324 if ( aEvent
.Source
== m_xInstance
)
326 // the object does not listen for anything any more
329 // dispose the wrapper;
330 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
332 if ( xComponent
.is() )
334 try { xComponent
->dispose(); }
335 catch( uno::Exception
& ){}
342 // --------------------------------------------------------
343 void SAL_CALL
OLockListener::queryClosing( const lang::EventObject
& aEvent
, sal_Bool
)
344 throw (util::CloseVetoException
, uno::RuntimeException
)
346 // GetsOwnership parameter is always ignored, the user of the service must close the object always
347 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
348 if ( !m_bDisposed
&& aEvent
.Source
== m_xInstance
&& ( m_nMode
& embed::Actions::PREVENT_CLOSE
) )
352 uno::Reference
< embed::XActionsApproval
> xApprove
= m_xApproval
;
354 // unlock the mutex here
357 if ( xApprove
.is() && xApprove
->approveAction( embed::Actions::PREVENT_CLOSE
) )
358 throw util::CloseVetoException();
360 catch( util::CloseVetoException
& )
362 // rethrow this exception
365 catch( uno::Exception
& )
367 // no action should be done
372 // --------------------------------------------------------
373 void SAL_CALL
OLockListener::notifyClosing( const lang::EventObject
& aEvent
)
374 throw (uno::RuntimeException
)
376 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
378 // object is closed, no reason to listen
379 if ( aEvent
.Source
== m_xInstance
)
381 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( aEvent
.Source
, uno::UNO_QUERY
);
382 if ( xCloseBroadcaster
.is() )
384 xCloseBroadcaster
->removeCloseListener( static_cast< util::XCloseListener
* >( this ) );
385 m_nMode
&= ~embed::Actions::PREVENT_CLOSE
;
388 // dispose the wrapper;
389 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
391 if ( xComponent
.is() )
393 try { xComponent
->dispose(); }
394 catch( uno::Exception
& ){}
402 // XTerminateListener
403 // --------------------------------------------------------
404 void SAL_CALL
OLockListener::queryTermination( const lang::EventObject
& aEvent
)
405 throw (frame::TerminationVetoException
, uno::RuntimeException
)
407 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
408 if ( aEvent
.Source
== m_xInstance
&& ( m_nMode
& embed::Actions::PREVENT_TERMINATION
) )
412 uno::Reference
< embed::XActionsApproval
> xApprove
= m_xApproval
;
414 // unlock the mutex here
417 if ( xApprove
.is() && xApprove
->approveAction( embed::Actions::PREVENT_TERMINATION
) )
418 throw frame::TerminationVetoException();
420 catch( frame::TerminationVetoException
& )
422 // rethrow this exception
425 catch( uno::Exception
& )
427 // no action should be done
432 // --------------------------------------------------------
433 void SAL_CALL
OLockListener::notifyTermination( const lang::EventObject
& aEvent
)
434 throw (uno::RuntimeException
)
436 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
438 // object is terminated, no reason to listen
439 if ( aEvent
.Source
== m_xInstance
)
441 uno::Reference
< frame::XDesktop
> xDesktop( aEvent
.Source
, uno::UNO_QUERY
);
446 xDesktop
->removeTerminateListener( static_cast< frame::XTerminateListener
* >( this ) );
447 m_nMode
&= ~embed::Actions::PREVENT_TERMINATION
;
450 // dispose the wrapper;
451 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
453 if ( xComponent
.is() )
455 try { xComponent
->dispose(); }
456 catch( uno::Exception
& ){}
460 catch( uno::Exception
& )
468 // --------------------------------------------------------
469 sal_Bool
OLockListener::Init()
471 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
473 if ( m_bDisposed
|| m_bInitialized
)
478 if ( m_nMode
& embed::Actions::PREVENT_CLOSE
)
480 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xInstance
, uno::UNO_QUERY_THROW
);
481 xCloseBroadcaster
->addCloseListener( static_cast< util::XCloseListener
* >( this ) );
484 if ( m_nMode
& embed::Actions::PREVENT_TERMINATION
)
486 uno::Reference
< frame::XDesktop
> xDesktop( m_xInstance
, uno::UNO_QUERY_THROW
);
487 xDesktop
->addTerminateListener( static_cast< frame::XTerminateListener
* >( this ) );
490 catch( uno::Exception
& )
492 // dispose the wrapper;
493 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
495 if ( xComponent
.is() )
497 try { xComponent
->dispose(); }
498 catch( uno::Exception
& ){}
504 m_bInitialized
= sal_True
;
509 void createRegistryInfo_OInstanceLocker()
511 static ::comphelper::module::OAutoRegistration
< OInstanceLocker
> aAutoRegistration
;