1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: instancelocker.cxx,v $
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 // ====================================================================
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()
69 m_refCount
++; // to call dispose
73 catch ( uno::RuntimeException
& )
77 if ( m_pListenersContainer
)
79 delete m_pListenersContainer
;
80 m_pListenersContainer
= NULL
;
85 // --------------------------------------------------------
86 void SAL_CALL
OInstanceLocker::dispose()
87 throw (uno::RuntimeException
)
89 ::osl::MutexGuard
aGuard( m_aMutex
);
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
);
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
);
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();
144 throw lang::DisposedException(); // TODO
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
>(),
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
>(),
169 !( aArguments
[1] >>= nModes
) ||
171 !( nModes
& embed::Actions::PREVENT_CLOSE
) &&
172 !( nModes
& embed::Actions::PREVENT_TERMINATION
)
176 throw lang::IllegalArgumentException(
178 RTL_CONSTASCII_USTRINGPARAM("The correct modes set is expected as the second argument!" ) ),
179 uno::Reference
< uno::XInterface
>(),
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
>(),
189 m_pLockListener
= new OLockListener( uno::Reference
< lang::XComponent
> ( static_cast< lang::XComponent
* >( this ) ),
193 m_xLockListener
= uno::Reference
< uno::XInterface
>( static_cast< OWeakObject
* >( m_pLockListener
) );
194 m_pLockListener
->Init();
196 catch( uno::Exception
& )
202 m_bInitialized
= sal_True
;
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 )
227 // --------------------------------------------------------
228 uno::Sequence
< ::rtl::OUString
> SAL_CALL
OInstanceLocker::getSupportedServiceNames()
229 throw (uno::RuntimeException
)
231 return getSupportedServiceNames_static();
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 // ====================================================================
259 // ====================================================================
261 // --------------------------------------------------------
262 OLockListener::OLockListener( const uno::WeakReference
< lang::XComponent
>& xWrapper
,
263 const uno::Reference
< uno::XInterface
>& xInstance
,
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
)
275 // --------------------------------------------------------
276 OLockListener::~OLockListener()
280 // --------------------------------------------------------
281 void OLockListener::Dispose()
283 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
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
;
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
332 // dispose the wrapper;
333 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
335 if ( xComponent
.is() )
337 try { xComponent
->dispose(); }
338 catch( uno::Exception
& ){}
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
360 if ( xApprove
.is() && xApprove
->approveAction( embed::Actions::PREVENT_CLOSE
) )
361 throw util::CloseVetoException();
363 catch( util::CloseVetoException
& )
365 // rethrow this exception
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
;
391 // dispose the wrapper;
392 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
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
420 if ( xApprove
.is() && xApprove
->approveAction( embed::Actions::PREVENT_TERMINATION
) )
421 throw frame::TerminationVetoException();
423 catch( frame::TerminationVetoException
& )
425 // rethrow this exception
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
);
449 xDesktop
->removeTerminateListener( static_cast< frame::XTerminateListener
* >( this ) );
450 m_nMode
&= ~embed::Actions::PREVENT_TERMINATION
;
453 // dispose the wrapper;
454 uno::Reference
< lang::XComponent
> xComponent( m_xWrapper
.get(), uno::UNO_QUERY
);
456 if ( xComponent
.is() )
458 try { xComponent
->dispose(); }
459 catch( uno::Exception
& ){}
463 catch( uno::Exception
& )
471 // --------------------------------------------------------
472 sal_Bool
OLockListener::Init()
474 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
476 if ( m_bDisposed
|| m_bInitialized
)
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
);
498 if ( xComponent
.is() )
500 try { xComponent
->dispose(); }
501 catch( uno::Exception
& ){}
507 m_bInitialized
= sal_True
;
512 void createRegistryInfo_OInstanceLocker()
514 static ::comphelper::module::OAutoRegistration
< OInstanceLocker
> aAutoRegistration
;