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