Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <cppuhelper/implbase.hxx>
21 : #include <cppuhelper/compbase.hxx>
22 : #include <osl/diagnose.h>
23 : #include <rtl/instance.hxx>
24 : #include <rtl/uuid.h>
25 :
26 : #include <com/sun/star/lang/XComponent.hpp>
27 : #include "com/sun/star/uno/RuntimeException.hpp"
28 :
29 : using namespace ::osl;
30 : using namespace ::rtl;
31 : using namespace ::com::sun::star;
32 : using namespace ::com::sun::star::uno;
33 :
34 : namespace
35 : {
36 : class theImplHelperInitMutex : public rtl::Static<Mutex, theImplHelperInitMutex>{};
37 : }
38 :
39 : namespace cppu
40 : {
41 : //==================================================================================================
42 4393 : Mutex & SAL_CALL getImplHelperInitMutex(void) SAL_THROW(())
43 : {
44 4393 : return theImplHelperInitMutex::get();
45 : }
46 :
47 : // ClassDataBase
48 : //__________________________________________________________________________________________________
49 0 : ClassDataBase::ClassDataBase() SAL_THROW(())
50 : : bOffsetsInit( sal_False )
51 : , nType2Offset( 0 )
52 : , nClassCode( 0 )
53 : , pTypes( 0 )
54 0 : , pId( 0 )
55 : {
56 0 : }
57 : //__________________________________________________________________________________________________
58 0 : ClassDataBase::ClassDataBase( sal_Int32 nClassCode_ ) SAL_THROW(())
59 : : bOffsetsInit( sal_False )
60 : , nType2Offset( 0 )
61 : , nClassCode( nClassCode_ )
62 : , pTypes( 0 )
63 0 : , pId( 0 )
64 : {
65 0 : }
66 : //__________________________________________________________________________________________________
67 0 : ClassDataBase::~ClassDataBase() SAL_THROW(())
68 : {
69 0 : delete pTypes;
70 0 : delete pId;
71 :
72 0 : for ( sal_Int32 nPos = nType2Offset; nPos--; )
73 : {
74 : typelib_typedescription_release(
75 0 : (typelib_TypeDescription *)((ClassData *)this)->arType2Offset[nPos].pTD );
76 : }
77 0 : }
78 :
79 : // ClassData
80 : //__________________________________________________________________________________________________
81 0 : void ClassData::writeTypeOffset( const Type & rType, sal_Int32 nOffset ) SAL_THROW(())
82 : {
83 0 : arType2Offset[nType2Offset].nOffset = nOffset;
84 :
85 0 : arType2Offset[nType2Offset].pTD = 0;
86 : typelib_typedescriptionreference_getDescription(
87 0 : (typelib_TypeDescription **)&arType2Offset[nType2Offset].pTD, rType.getTypeLibType() );
88 :
89 0 : if (arType2Offset[nType2Offset].pTD)
90 0 : ++nType2Offset;
91 : #if OSL_DEBUG_LEVEL > 1
92 : else
93 : {
94 : OString msg( "### cannot get type description for " );
95 : msg += OUStringToOString( rType.getTypeName(), RTL_TEXTENCODING_ASCII_US );
96 : OSL_FAIL( msg.getStr() );
97 : }
98 : #endif
99 0 : }
100 : //__________________________________________________________________________________________________
101 0 : void ClassData::initTypeProvider() SAL_THROW(())
102 : {
103 0 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
104 0 : if (! pTypes)
105 : {
106 : // create id
107 0 : pId = new Sequence< sal_Int8 >( 16 );
108 0 : rtl_createUuid( (sal_uInt8 *)pId->getArray(), 0, sal_True );
109 :
110 : // collect types
111 : Sequence< Type > * types = new Sequence< Type >(
112 0 : nType2Offset + 1 + (nClassCode == 4 ? 2 : nClassCode) );
113 0 : Type * pTypeAr = types->getArray();
114 :
115 : // given types
116 0 : sal_Int32 nPos = nType2Offset;
117 0 : while (nPos--)
118 0 : pTypeAr[nPos] = ((typelib_TypeDescription *)arType2Offset[nPos].pTD)->pWeakRef;
119 :
120 : // XTypeProvider
121 0 : pTypeAr[nType2Offset] = ::getCppuType( (const Reference< lang::XTypeProvider > *)0 );
122 :
123 : // class code extra types: [[XComponent,] XWeak[, XAggregation]]
124 0 : switch (nClassCode)
125 : {
126 : case 4:
127 0 : pTypeAr[nType2Offset +2] = ::getCppuType( (const Reference< lang::XComponent > *)0 );
128 0 : pTypeAr[nType2Offset +1] = ::getCppuType( (const Reference< XWeak > *)0 );
129 0 : break;
130 : case 3:
131 0 : pTypeAr[nType2Offset +3] = ::getCppuType( (const Reference< lang::XComponent > *)0 );
132 : case 2:
133 0 : pTypeAr[nType2Offset +2] = ::getCppuType( (const Reference< XAggregation > *)0 );
134 : case 1:
135 0 : pTypeAr[nType2Offset +1] = ::getCppuType( (const Reference< XWeak > *)0 );
136 : }
137 :
138 0 : pTypes = types;
139 0 : }
140 0 : }
141 : //__________________________________________________________________________________________________
142 0 : Sequence< Type > ClassData::getTypes() SAL_THROW(())
143 : {
144 0 : if (! pTypes)
145 0 : initTypeProvider();
146 0 : return *pTypes;
147 : }
148 : //__________________________________________________________________________________________________
149 0 : Sequence< sal_Int8 > ClassData::getImplementationId() SAL_THROW(())
150 : {
151 0 : if (! pTypes)
152 0 : initTypeProvider();
153 0 : return *pId;
154 : }
155 :
156 : //--------------------------------------------------------------------------------------------------
157 0 : static inline sal_Bool td_equals(
158 : typelib_TypeDescription * pTD, typelib_TypeDescriptionReference * pType )
159 : SAL_THROW(())
160 : {
161 : return (pTD->pWeakRef == pType ||
162 : (pTD->pTypeName->length == pType->pTypeName->length &&
163 0 : rtl_ustr_compare( pTD->pTypeName->buffer, pType->pTypeName->buffer ) == 0));
164 : }
165 : //__________________________________________________________________________________________________
166 0 : Any ClassData::query( const Type & rType, lang::XTypeProvider * pBase ) SAL_THROW(())
167 : {
168 0 : if (rType == ::getCppuType( (const Reference< XInterface > *)0 ))
169 0 : return Any( &pBase, ::getCppuType( (const Reference< XInterface > *)0 ) );
170 0 : for ( sal_Int32 nPos = 0; nPos < nType2Offset; ++nPos )
171 : {
172 0 : const Type_Offset & rTO = arType2Offset[nPos];
173 0 : typelib_InterfaceTypeDescription * pTD = rTO.pTD;
174 0 : while (pTD)
175 : {
176 0 : if (td_equals( (typelib_TypeDescription *)pTD,
177 0 : *(typelib_TypeDescriptionReference **)&rType ))
178 : {
179 0 : void * pInterface = (char *)pBase + rTO.nOffset;
180 0 : return Any( &pInterface, (typelib_TypeDescription *)pTD );
181 : }
182 0 : pTD = pTD->pBaseTypeDescription;
183 : }
184 : }
185 0 : if (rType == ::getCppuType( (const Reference< lang::XTypeProvider > *)0 ))
186 0 : return Any( &pBase, ::getCppuType( (const Reference< lang::XTypeProvider > *)0 ) );
187 :
188 0 : return Any();
189 : }
190 :
191 : //##################################################################################################
192 : //##################################################################################################
193 : //##################################################################################################
194 :
195 : // WeakComponentImplHelperBase
196 : //__________________________________________________________________________________________________
197 16005 : WeakComponentImplHelperBase::WeakComponentImplHelperBase( Mutex & rMutex )
198 : SAL_THROW(())
199 16005 : : rBHelper( rMutex )
200 : {
201 16005 : }
202 : //__________________________________________________________________________________________________
203 13391 : WeakComponentImplHelperBase::~WeakComponentImplHelperBase()
204 : SAL_THROW(())
205 : {
206 13391 : }
207 : //__________________________________________________________________________________________________
208 6357 : void WeakComponentImplHelperBase::disposing()
209 : {
210 6357 : }
211 : //__________________________________________________________________________________________________
212 16783 : Any WeakComponentImplHelperBase::queryInterface( Type const & rType )
213 : throw (RuntimeException)
214 : {
215 16783 : if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
216 : {
217 1144 : void * p = static_cast< lang::XComponent * >( this );
218 1144 : return Any( &p, rType );
219 : }
220 15639 : return OWeakObject::queryInterface( rType );
221 : }
222 : //__________________________________________________________________________________________________
223 1152261 : void WeakComponentImplHelperBase::acquire()
224 : throw ()
225 : {
226 1152261 : OWeakObject::acquire();
227 1152261 : }
228 : //__________________________________________________________________________________________________
229 1131405 : void WeakComponentImplHelperBase::release()
230 : throw ()
231 : {
232 1131405 : if (osl_atomic_decrement( &m_refCount ) == 0) {
233 : // ensure no other references are created, via the weak connection point, from now on
234 13363 : disposeWeakConnectionPoint();
235 : // restore reference count:
236 13363 : osl_atomic_increment( &m_refCount );
237 13363 : if (! rBHelper.bDisposed) {
238 : try {
239 12562 : dispose();
240 : }
241 0 : catch (RuntimeException const& exc) { // don't break throw ()
242 : OSL_FAIL(
243 : OUStringToOString(
244 : exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
245 : static_cast<void>(exc);
246 : }
247 : OSL_ASSERT( rBHelper.bDisposed );
248 : }
249 13363 : OWeakObject::release();
250 : }
251 1131405 : }
252 : //__________________________________________________________________________________________________
253 13444 : void WeakComponentImplHelperBase::dispose()
254 : throw (RuntimeException)
255 : {
256 13444 : ClearableMutexGuard aGuard( rBHelper.rMutex );
257 13444 : if (!rBHelper.bDisposed && !rBHelper.bInDispose)
258 : {
259 13443 : rBHelper.bInDispose = sal_True;
260 13443 : aGuard.clear();
261 : try
262 : {
263 : // side effect: keeping a reference to this
264 13443 : lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
265 : try
266 : {
267 13443 : rBHelper.aLC.disposeAndClear( aEvt );
268 13443 : disposing();
269 : }
270 0 : catch (...)
271 : {
272 0 : MutexGuard aGuard2( rBHelper.rMutex );
273 : // bDisposed and bInDispose must be set in this order:
274 0 : rBHelper.bDisposed = sal_True;
275 0 : rBHelper.bInDispose = sal_False;
276 0 : throw;
277 : }
278 13443 : MutexGuard aGuard2( rBHelper.rMutex );
279 : // bDisposed and bInDispose must be set in this order:
280 13443 : rBHelper.bDisposed = sal_True;
281 13443 : rBHelper.bInDispose = sal_False;
282 : }
283 0 : catch (RuntimeException &)
284 : {
285 0 : throw;
286 : }
287 0 : catch (Exception & exc)
288 : {
289 : throw RuntimeException(
290 : OUString( RTL_CONSTASCII_USTRINGPARAM(
291 : "unexpected UNO exception caught: ") ) +
292 0 : exc.Message, Reference< XInterface >() );
293 : }
294 13444 : }
295 13444 : }
296 : //__________________________________________________________________________________________________
297 1024 : void WeakComponentImplHelperBase::addEventListener(
298 : Reference< lang::XEventListener > const & xListener )
299 : throw (RuntimeException)
300 : {
301 1024 : ClearableMutexGuard aGuard( rBHelper.rMutex );
302 1024 : if (rBHelper.bDisposed || rBHelper.bInDispose)
303 : {
304 0 : aGuard.clear();
305 0 : lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
306 0 : xListener->disposing( aEvt );
307 : }
308 : else
309 : {
310 1024 : rBHelper.addListener( ::getCppuType( &xListener ), xListener );
311 1024 : }
312 1024 : }
313 : //__________________________________________________________________________________________________
314 55 : void WeakComponentImplHelperBase::removeEventListener(
315 : Reference< lang::XEventListener > const & xListener )
316 : throw (RuntimeException)
317 : {
318 55 : rBHelper.removeListener( ::getCppuType( &xListener ), xListener );
319 55 : }
320 :
321 : // WeakAggComponentImplHelperBase
322 : //__________________________________________________________________________________________________
323 6 : WeakAggComponentImplHelperBase::WeakAggComponentImplHelperBase( Mutex & rMutex )
324 : SAL_THROW(())
325 6 : : rBHelper( rMutex )
326 : {
327 6 : }
328 : //__________________________________________________________________________________________________
329 5 : WeakAggComponentImplHelperBase::~WeakAggComponentImplHelperBase()
330 : SAL_THROW(())
331 : {
332 5 : }
333 : //__________________________________________________________________________________________________
334 4 : void WeakAggComponentImplHelperBase::disposing()
335 : {
336 4 : }
337 : //__________________________________________________________________________________________________
338 54 : Any WeakAggComponentImplHelperBase::queryInterface( Type const & rType )
339 : throw (RuntimeException)
340 : {
341 54 : return OWeakAggObject::queryInterface( rType );
342 : }
343 : //__________________________________________________________________________________________________
344 33 : Any WeakAggComponentImplHelperBase::queryAggregation( Type const & rType )
345 : throw (RuntimeException)
346 : {
347 33 : if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
348 : {
349 2 : void * p = static_cast< lang::XComponent * >( this );
350 2 : return Any( &p, rType );
351 : }
352 31 : return OWeakAggObject::queryAggregation( rType );
353 : }
354 : //__________________________________________________________________________________________________
355 142 : void WeakAggComponentImplHelperBase::acquire()
356 : throw ()
357 : {
358 142 : OWeakAggObject::acquire();
359 142 : }
360 : //__________________________________________________________________________________________________
361 134 : void WeakAggComponentImplHelperBase::release()
362 : throw ()
363 : {
364 134 : Reference<XInterface> const xDelegator_(xDelegator);
365 134 : if (xDelegator_.is()) {
366 24 : OWeakAggObject::release();
367 : }
368 110 : else if (osl_atomic_decrement( &m_refCount ) == 0) {
369 : // ensure no other references are created, via the weak connection point, from now on
370 5 : disposeWeakConnectionPoint();
371 : // restore reference count:
372 5 : osl_atomic_increment( &m_refCount );
373 5 : if (! rBHelper.bDisposed) {
374 : try {
375 4 : dispose();
376 : }
377 0 : catch (RuntimeException const& exc) { // don't break throw ()
378 : OSL_FAIL(
379 : OUStringToOString(
380 : exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
381 : static_cast<void>(exc);
382 : }
383 : OSL_ASSERT( rBHelper.bDisposed );
384 : }
385 5 : OWeakAggObject::release();
386 134 : }
387 134 : }
388 : //__________________________________________________________________________________________________
389 6 : void WeakAggComponentImplHelperBase::dispose()
390 : throw (RuntimeException)
391 : {
392 6 : ClearableMutexGuard aGuard( rBHelper.rMutex );
393 6 : if (!rBHelper.bDisposed && !rBHelper.bInDispose)
394 : {
395 6 : rBHelper.bInDispose = sal_True;
396 6 : aGuard.clear();
397 : try
398 : {
399 : // side effect: keeping a reference to this
400 6 : lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
401 : try
402 : {
403 6 : rBHelper.aLC.disposeAndClear( aEvt );
404 6 : disposing();
405 : }
406 0 : catch (...)
407 : {
408 0 : MutexGuard aGuard2( rBHelper.rMutex );
409 : // bDisposed and bInDispose must be set in this order:
410 0 : rBHelper.bDisposed = sal_True;
411 0 : rBHelper.bInDispose = sal_False;
412 0 : throw;
413 : }
414 6 : MutexGuard aGuard2( rBHelper.rMutex );
415 : // bDisposed and bInDispose must be set in this order:
416 6 : rBHelper.bDisposed = sal_True;
417 6 : rBHelper.bInDispose = sal_False;
418 : }
419 0 : catch (RuntimeException &)
420 : {
421 0 : throw;
422 : }
423 0 : catch (Exception & exc)
424 : {
425 : throw RuntimeException(
426 : OUString( RTL_CONSTASCII_USTRINGPARAM(
427 : "unexpected UNO exception caught: ") ) +
428 0 : exc.Message, Reference< XInterface >() );
429 : }
430 6 : }
431 6 : }
432 : //__________________________________________________________________________________________________
433 0 : void WeakAggComponentImplHelperBase::addEventListener(
434 : Reference< lang::XEventListener > const & xListener )
435 : throw (RuntimeException)
436 : {
437 0 : ClearableMutexGuard aGuard( rBHelper.rMutex );
438 0 : if (rBHelper.bDisposed || rBHelper.bInDispose)
439 : {
440 0 : aGuard.clear();
441 0 : lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
442 0 : xListener->disposing( aEvt );
443 : }
444 : else
445 : {
446 0 : rBHelper.addListener( ::getCppuType( &xListener ), xListener );
447 0 : }
448 0 : }
449 : //__________________________________________________________________________________________________
450 0 : void WeakAggComponentImplHelperBase::removeEventListener(
451 : Reference< lang::XEventListener > const & xListener )
452 : throw (RuntimeException)
453 : {
454 0 : rBHelper.removeListener( ::getCppuType( &xListener ), xListener );
455 0 : }
456 :
457 : }
458 :
459 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|