1 |
/************************************************************** |
2 |
* |
3 |
* Licensed to the Apache Software Foundation (ASF) under one |
4 |
* or more contributor license agreements. See the NOTICE file |
5 |
* distributed with this work for additional information |
6 |
* regarding copyright ownership. The ASF licenses this file |
7 |
* to you under the Apache License, Version 2.0 (the |
8 |
* "License"); you may not use this file except in compliance |
9 |
* with the License. You may obtain a copy of the License at |
10 |
* |
11 |
* http://www.apache.org/licenses/LICENSE-2.0 |
12 |
* |
13 |
* Unless required by applicable law or agreed to in writing, |
14 |
* software distributed under the License is distributed on an |
15 |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
16 |
* KIND, either express or implied. See the License for the |
17 |
* specific language governing permissions and limitations |
18 |
* under the License. |
19 |
* |
20 |
*************************************************************/ |
21 |
|
22 |
|
23 |
|
24 |
// MARKER(update_precomp.py): autogen include statement, do not remove |
25 |
#include "precompiled_comphelper.hxx" |
26 |
|
27 |
#include "comphelper_module.hxx" |
28 |
|
29 |
#include <com/sun/star/util/XCloseBroadcaster.hpp> |
30 |
#include <com/sun/star/util/XCloseable.hpp> |
31 |
#include <com/sun/star/lang/DisposedException.hpp> |
32 |
#include <com/sun/star/lang/IllegalArgumentException.hpp> |
33 |
#include <com/sun/star/frame/XDesktop.hpp> |
34 |
#include <com/sun/star/frame/DoubleInitializationException.hpp> |
35 |
#include <com/sun/star/frame/DoubleInitializationException.hpp> |
36 |
#include <com/sun/star/beans/XPropertySet.hpp> |
37 |
|
38 |
#include "instancelocker.hxx" |
39 |
|
40 |
using namespace ::com::sun::star; |
41 |
|
42 |
|
43 |
// ==================================================================== |
44 |
// OInstanceLocker |
45 |
// ==================================================================== |
46 |
|
47 |
// -------------------------------------------------------- |
48 |
OInstanceLocker::OInstanceLocker( const uno::Reference< uno::XComponentContext >& xContext ) |
49 |
: m_xContext( xContext ) |
50 |
, m_pLockListener( NULL ) |
51 |
, m_pListenersContainer( NULL ) |
52 |
, m_bDisposed( sal_False ) |
53 |
, m_bInitialized( sal_False ) |
54 |
{ |
55 |
} |
56 |
|
57 |
// -------------------------------------------------------- |
58 |
OInstanceLocker::~OInstanceLocker() |
59 |
{ |
60 |
if ( !m_bDisposed ) |
61 |
{ |
62 |
m_refCount++; // to call dispose |
63 |
try { |
64 |
dispose(); |
65 |
} |
66 |
catch ( uno::RuntimeException& ) |
67 |
{} |
68 |
} |
69 |
|
70 |
if ( m_pListenersContainer ) |
71 |
{ |
72 |
delete m_pListenersContainer; |
73 |
m_pListenersContainer = NULL; |
74 |
} |
75 |
} |
76 |
|
77 |
// XComponent |
78 |
// -------------------------------------------------------- |
79 |
void SAL_CALL OInstanceLocker::dispose() |
80 |
throw (uno::RuntimeException) |
81 |
{ |
82 |
::osl::MutexGuard aGuard( m_aMutex ); |
83 |
|
84 |
if ( m_bDisposed ) |
85 |
throw lang::DisposedException(); |
86 |
|
87 |
lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); |
88 |
if ( m_pListenersContainer ) |
89 |
m_pListenersContainer->disposeAndClear( aSource ); |
90 |
|
91 |
if ( m_xLockListener.is() ) |
92 |
{ |
93 |
if ( m_pLockListener ) |
94 |
{ |
95 |
m_pLockListener->Dispose(); |
96 |
m_pLockListener = NULL; |
97 |
} |
98 |
m_xLockListener = uno::Reference< uno::XInterface >(); |
99 |
} |
100 |
|
101 |
m_bDisposed = sal_True; |
102 |
} |
103 |
|
104 |
// -------------------------------------------------------- |
105 |
void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) |
106 |
throw (uno::RuntimeException) |
107 |
{ |
108 |
::osl::MutexGuard aGuard( m_aMutex ); |
109 |
if ( m_bDisposed ) |
110 |
throw lang::DisposedException(); // TODO |
111 |
|
112 |
if ( !m_pListenersContainer ) |
113 |
m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex ); |
114 |
|
115 |
m_pListenersContainer->addInterface( xListener ); |
116 |
} |
117 |
|
118 |
// -------------------------------------------------------- |
119 |
void SAL_CALL OInstanceLocker::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) |
120 |
throw (uno::RuntimeException) |
121 |
{ |
122 |
::osl::MutexGuard aGuard( m_aMutex ); |
123 |
if ( m_pListenersContainer ) |
124 |
m_pListenersContainer->removeInterface( xListener ); |
125 |
} |
126 |
|
127 |
// XInitialization |
128 |
// -------------------------------------------------------- |
129 |
void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArguments ) |
130 |
throw (uno::Exception, uno::RuntimeException) |
131 |
{ |
132 |
::osl::MutexGuard aGuard( m_aMutex ); |
133 |
if ( m_bInitialized ) |
134 |
throw frame::DoubleInitializationException(); |
135 |
|
136 |
if ( m_bDisposed ) |
137 |
throw lang::DisposedException(); // TODO |
138 |
|
139 |
if ( !m_refCount ) |
140 |
throw uno::RuntimeException(); // the object must be refcounted already! |
141 |
|
142 |
uno::Reference< uno::XInterface > xInstance; |
143 |
uno::Reference< embed::XActionsApproval > xApproval; |
144 |
sal_Int32 nModes = 0; |
145 |
|
146 |
try |
147 |
{ |
148 |
sal_Int32 nLen = aArguments.getLength(); |
149 |
if ( nLen < 2 || nLen > 3 ) |
150 |
throw lang::IllegalArgumentException( |
151 |
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Wrong count of parameters!" ) ), |
152 |
uno::Reference< uno::XInterface >(), |
153 |
0 ); |
154 |
|
155 |
if ( !( aArguments[0] >>= xInstance ) || !xInstance.is() ) |
156 |
throw lang::IllegalArgumentException( |
157 |
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Nonempty reference is expected as the first argument!" ) ), |
158 |
uno::Reference< uno::XInterface >(), |
159 |
0 ); |
160 |
|
161 |
if ( |
162 |
!( aArguments[1] >>= nModes ) || |
163 |
( |
164 |
!( nModes & embed::Actions::PREVENT_CLOSE ) && |
165 |
!( nModes & embed::Actions::PREVENT_TERMINATION ) |
166 |
) |
167 |
) |
168 |
{ |
169 |
throw lang::IllegalArgumentException( |
170 |
::rtl::OUString( |
171 |
RTL_CONSTASCII_USTRINGPARAM("The correct modes set is expected as the second argument!" ) ), |
172 |
uno::Reference< uno::XInterface >(), |
173 |
0 ); |
174 |
} |
175 |
|
176 |
if ( nLen == 3 && !( aArguments[2] >>= xApproval ) ) |
177 |
throw lang::IllegalArgumentException( |
178 |
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("If the third argument is provided, it must be XActionsApproval implementation!" ) ), |
179 |
uno::Reference< uno::XInterface >(), |
180 |
0 ); |
181 |
|
182 |
m_pLockListener = new OLockListener( uno::Reference< lang::XComponent > ( static_cast< lang::XComponent* >( this ) ), |
183 |
xInstance, |
184 |
nModes, |
185 |
xApproval ); |
186 |
m_xLockListener = uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( m_pLockListener ) ); |
187 |
m_pLockListener->Init(); |
188 |
} |
189 |
catch( uno::Exception& ) |
190 |
{ |
191 |
dispose(); |
192 |
throw; |
193 |
} |
194 |
|
195 |
m_bInitialized = sal_True; |
196 |
} |
197 |
|
198 |
|
199 |
// XServiceInfo |
200 |
// -------------------------------------------------------- |
201 |
::rtl::OUString SAL_CALL OInstanceLocker::getImplementationName( ) |
202 |
throw (uno::RuntimeException) |
203 |
{ |
204 |
return getImplementationName_static(); |
205 |
} |
206 |
|
207 |
// -------------------------------------------------------- |
208 |
::sal_Bool SAL_CALL OInstanceLocker::supportsService( const ::rtl::OUString& ServiceName ) |
209 |
throw (uno::RuntimeException) |
210 |
{ |
211 |
uno::Sequence< ::rtl::OUString > aSeq = getSupportedServiceNames(); |
212 |
|
213 |
for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) |
214 |
if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) |
215 |
return sal_True; |
216 |
|
217 |
return sal_False; |
218 |
} |
219 |
|
220 |
// -------------------------------------------------------- |
221 |
uno::Sequence< ::rtl::OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames() |
222 |
throw (uno::RuntimeException) |
223 |
{ |
224 |
return getSupportedServiceNames_static(); |
225 |
} |
226 |
|
227 |
// Static methods |
228 |
// -------------------------------------------------------- |
229 |
uno::Sequence< ::rtl::OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames_static() |
230 |
{ |
231 |
const rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.InstanceLocker" ) ); |
232 |
return uno::Sequence< rtl::OUString >( &aServiceName, 1 ); |
233 |
} |
234 |
|
235 |
// -------------------------------------------------------- |
236 |
::rtl::OUString SAL_CALL OInstanceLocker::getImplementationName_static() |
237 |
{ |
238 |
return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.embed.InstanceLocker" ) ); |
239 |
} |
240 |
|
241 |
// -------------------------------------------------------- |
242 |
uno::Reference< uno::XInterface > SAL_CALL OInstanceLocker::Create( |
243 |
const uno::Reference< uno::XComponentContext >& rxContext ) |
244 |
{ |
245 |
return static_cast< cppu::OWeakObject * >( new OInstanceLocker( rxContext ) ); |
246 |
} |
247 |
|
248 |
|
249 |
|
250 |
// ==================================================================== |
251 |
// OLockListener |
252 |
// ==================================================================== |
253 |
|
254 |
// -------------------------------------------------------- |
255 |
OLockListener::OLockListener( const uno::WeakReference< lang::XComponent >& xWrapper, |
256 |
const uno::Reference< uno::XInterface >& xInstance, |
257 |
sal_Int32 nMode, |
258 |
const uno::Reference< embed::XActionsApproval > xApproval ) |
259 |
: m_xInstance( xInstance ) |
260 |
, m_xApproval( xApproval ) |
261 |
, m_xWrapper( xWrapper ) |
262 |
, m_bDisposed( sal_False ) |
263 |
, m_bInitialized( sal_False ) |
264 |
, m_nMode( nMode ) |
265 |
{ |
266 |
} |
267 |
|
268 |
// -------------------------------------------------------- |
269 |
OLockListener::~OLockListener() |
270 |
{ |
271 |
} |
272 |
|
273 |
// -------------------------------------------------------- |
274 |
void OLockListener::Dispose() |
275 |
{ |
276 |
::osl::ResettableMutexGuard aGuard( m_aMutex ); |
277 |
|
278 |
if ( m_bDisposed ) |
279 |
return; |
280 |
|
281 |
if ( m_nMode & embed::Actions::PREVENT_CLOSE ) |
282 |
{ |
283 |
try |
284 |
{ |
285 |
uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY ); |
286 |
if ( xCloseBroadcaster.is() ) |
287 |
xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) ); |
288 |
|
289 |
uno::Reference< util::XCloseable > xCloseable( m_xInstance, uno::UNO_QUERY ); |
290 |
if ( xCloseable.is() ) |
291 |
xCloseable->close( sal_True ); |
292 |
} |
293 |
catch( uno::Exception& ) |
294 |
{} |
295 |
} |
296 |
|
297 |
if ( m_nMode & embed::Actions::PREVENT_TERMINATION ) |
298 |
{ |
299 |
try |
300 |
{ |
301 |
uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW ); |
302 |
xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) ); |
303 |
} |
304 |
catch( uno::Exception& ) |
305 |
{} |
306 |
} |
307 |
|
308 |
m_xInstance = uno::Reference< uno::XInterface >(); |
309 |
m_bDisposed = sal_True; |
310 |
} |
311 |
|
312 |
// XEventListener |
313 |
// -------------------------------------------------------- |
314 |
void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent ) |
315 |
throw (uno::RuntimeException) |
316 |
{ |
317 |
::osl::ResettableMutexGuard aGuard( m_aMutex ); |
318 |
|
319 |
// object is disposed |
320 |
if ( aEvent.Source == m_xInstance ) |
321 |
{ |
322 |
// the object does not listen for anything any more |
323 |
m_nMode = 0; |
324 |
|
325 |
// dispose the wrapper; |
326 |
uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); |
327 |
aGuard.clear(); |
328 |
if ( xComponent.is() ) |
329 |
{ |
330 |
try { xComponent->dispose(); } |
331 |
catch( uno::Exception& ){} |
332 |
} |
333 |
} |
334 |
} |
335 |
|
336 |
|
337 |
// XCloseListener |
338 |
// -------------------------------------------------------- |
339 |
void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_Bool ) |
340 |
throw (util::CloseVetoException, uno::RuntimeException) |
341 |
{ |
342 |
// GetsOwnership parameter is always ignored, the user of the service must close the object always |
343 |
::osl::ResettableMutexGuard aGuard( m_aMutex ); |
344 |
if ( !m_bDisposed && aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_CLOSE ) ) |
345 |
{ |
346 |
try |
347 |
{ |
348 |
uno::Reference< embed::XActionsApproval > xApprove = m_xApproval; |
349 |
|
350 |
// unlock the mutex here |
351 |
aGuard.clear(); |
352 |
|
353 |
if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_CLOSE ) ) |
354 |
throw util::CloseVetoException(); |
355 |
} |
356 |
catch( util::CloseVetoException& ) |
357 |
{ |
358 |
// rethrow this exception |
359 |
throw; |
360 |
} |
361 |
catch( uno::Exception& ) |
362 |
{ |
363 |
// no action should be done |
364 |
} |
365 |
} |
366 |
} |
367 |
|
368 |
// -------------------------------------------------------- |
369 |
void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent ) |
370 |
throw (uno::RuntimeException) |
371 |
{ |
372 |
::osl::ResettableMutexGuard aGuard( m_aMutex ); |
373 |
|
374 |
// object is closed, no reason to listen |
375 |
if ( aEvent.Source == m_xInstance ) |
376 |
{ |
377 |
uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( aEvent.Source, uno::UNO_QUERY ); |
378 |
if ( xCloseBroadcaster.is() ) |
379 |
{ |
380 |
xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) ); |
381 |
m_nMode &= ~embed::Actions::PREVENT_CLOSE; |
382 |
if ( !m_nMode ) |
383 |
{ |
384 |
// dispose the wrapper; |
385 |
uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); |
386 |
aGuard.clear(); |
387 |
if ( xComponent.is() ) |
388 |
{ |
389 |
try { xComponent->dispose(); } |
390 |
catch( uno::Exception& ){} |
391 |
} |
392 |
} |
393 |
} |
394 |
} |
395 |
} |
396 |
|
397 |
|
398 |
// XTerminateListener |
399 |
// -------------------------------------------------------- |
400 |
void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent ) |
401 |
throw (frame::TerminationVetoException, uno::RuntimeException) |
402 |
{ |
403 |
::osl::ResettableMutexGuard aGuard( m_aMutex ); |
404 |
if ( aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_TERMINATION ) ) |
405 |
{ |
406 |
try |
407 |
{ |
408 |
uno::Reference< embed::XActionsApproval > xApprove = m_xApproval; |
409 |
|
410 |
// unlock the mutex here |
411 |
aGuard.clear(); |
412 |
|
413 |
if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_TERMINATION ) ) |
414 |
throw frame::TerminationVetoException(); |
415 |
} |
416 |
catch( frame::TerminationVetoException& ) |
417 |
{ |
418 |
// rethrow this exception |
419 |
throw; |
420 |
} |
421 |
catch( uno::Exception& ) |
422 |
{ |
423 |
// no action should be done |
424 |
} |
425 |
} |
426 |
} |
427 |
|
428 |
// -------------------------------------------------------- |
429 |
void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent ) |
430 |
throw (uno::RuntimeException) |
431 |
{ |
432 |
::osl::ResettableMutexGuard aGuard( m_aMutex ); |
433 |
|
434 |
// object is terminated, no reason to listen |
435 |
if ( aEvent.Source == m_xInstance ) |
436 |
{ |
437 |
uno::Reference< frame::XDesktop > xDesktop( aEvent.Source, uno::UNO_QUERY ); |
438 |
if ( xDesktop.is() ) |
439 |
{ |
440 |
try |
441 |
{ |
442 |
xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) ); |
443 |
m_nMode &= ~embed::Actions::PREVENT_TERMINATION; |
444 |
if ( !m_nMode ) |
445 |
{ |
446 |
// dispose the wrapper; |
447 |
uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); |
448 |
aGuard.clear(); |
449 |
if ( xComponent.is() ) |
450 |
{ |
451 |
try { xComponent->dispose(); } |
452 |
catch( uno::Exception& ){} |
453 |
} |
454 |
} |
455 |
} |
456 |
catch( uno::Exception& ) |
457 |
{} |
458 |
} |
459 |
} |
460 |
} |
461 |
|
462 |
|
463 |
// XInitialization |
464 |
// -------------------------------------------------------- |
465 |
sal_Bool OLockListener::Init() |
466 |
{ |
467 |
::osl::ResettableMutexGuard aGuard( m_aMutex ); |
468 |
|
469 |
if ( m_bDisposed || m_bInitialized ) |
470 |
return sal_False; |
471 |
|
472 |
try |
473 |
{ |
474 |
if ( m_nMode & embed::Actions::PREVENT_CLOSE ) |
475 |
{ |
476 |
uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY_THROW ); |
477 |
xCloseBroadcaster->addCloseListener( static_cast< util::XCloseListener* >( this ) ); |
478 |
} |
479 |
|
480 |
if ( m_nMode & embed::Actions::PREVENT_TERMINATION ) |
481 |
{ |
482 |
uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW ); |
483 |
xDesktop->addTerminateListener( static_cast< frame::XTerminateListener* >( this ) ); |
484 |
} |
485 |
} |
486 |
catch( uno::Exception& ) |
487 |
{ |
488 |
// dispose the wrapper; |
489 |
uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); |
490 |
aGuard.clear(); |
491 |
if ( xComponent.is() ) |
492 |
{ |
493 |
try { xComponent->dispose(); } |
494 |
catch( uno::Exception& ){} |
495 |
} |
496 |
|
497 |
throw; |
498 |
} |
499 |
|
500 |
m_bInitialized = sal_True; |
501 |
|
502 |
return sal_True; |
503 |
} |
504 |
|
505 |
void createRegistryInfo_OInstanceLocker() |
506 |
{ |
507 |
static ::comphelper::module::OAutoRegistration< OInstanceLocker > aAutoRegistration; |
508 |
} |