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