update credits
[LibreOffice.git] / cppuhelper / source / implbase.cxx
blob4816c4a63832cf3d296659ebd3ef377a5b6e90b4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
26 #include <com/sun/star/lang/XComponent.hpp>
27 #include "com/sun/star/uno/RuntimeException.hpp"
29 using namespace ::osl;
30 using namespace ::rtl;
31 using namespace ::com::sun::star;
32 using namespace ::com::sun::star::uno;
34 namespace
36 class theImplHelperInitMutex : public rtl::Static<Mutex, theImplHelperInitMutex>{};
39 namespace cppu
41 //==================================================================================================
42 Mutex & SAL_CALL getImplHelperInitMutex(void) SAL_THROW(())
44 return theImplHelperInitMutex::get();
47 // ClassDataBase
48 //__________________________________________________________________________________________________
49 ClassDataBase::ClassDataBase() SAL_THROW(())
50 : bOffsetsInit( sal_False )
51 , nType2Offset( 0 )
52 , nClassCode( 0 )
53 , pTypes( 0 )
54 , pId( 0 )
57 //__________________________________________________________________________________________________
58 ClassDataBase::ClassDataBase( sal_Int32 nClassCode_ ) SAL_THROW(())
59 : bOffsetsInit( sal_False )
60 , nType2Offset( 0 )
61 , nClassCode( nClassCode_ )
62 , pTypes( 0 )
63 , pId( 0 )
66 //__________________________________________________________________________________________________
67 ClassDataBase::~ClassDataBase() SAL_THROW(())
69 delete pTypes;
70 delete pId;
72 for ( sal_Int32 nPos = nType2Offset; nPos--; )
74 typelib_typedescription_release(
75 (typelib_TypeDescription *)((ClassData *)this)->arType2Offset[nPos].pTD );
79 // ClassData
80 //__________________________________________________________________________________________________
81 void ClassData::writeTypeOffset( const Type & rType, sal_Int32 nOffset ) SAL_THROW(())
83 arType2Offset[nType2Offset].nOffset = nOffset;
85 arType2Offset[nType2Offset].pTD = 0;
86 typelib_typedescriptionreference_getDescription(
87 (typelib_TypeDescription **)&arType2Offset[nType2Offset].pTD, rType.getTypeLibType() );
89 if (arType2Offset[nType2Offset].pTD)
90 ++nType2Offset;
91 #if OSL_DEBUG_LEVEL > 1
92 else
94 OString msg( "### cannot get type description for " );
95 msg += OUStringToOString( rType.getTypeName(), RTL_TEXTENCODING_ASCII_US );
96 OSL_FAIL( msg.getStr() );
98 #endif
100 //__________________________________________________________________________________________________
101 void ClassData::initTypeProvider() SAL_THROW(())
103 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
104 if (! pTypes)
106 // create id
107 pId = new Sequence< sal_Int8 >( 16 );
108 rtl_createUuid( (sal_uInt8 *)pId->getArray(), 0, sal_True );
110 // collect types
111 Sequence< Type > * types = new Sequence< Type >(
112 nType2Offset + 1 + (nClassCode == 4 ? 2 : nClassCode) );
113 Type * pTypeAr = types->getArray();
115 // given types
116 sal_Int32 nPos = nType2Offset;
117 while (nPos--)
118 pTypeAr[nPos] = ((typelib_TypeDescription *)arType2Offset[nPos].pTD)->pWeakRef;
120 // XTypeProvider
121 pTypeAr[nType2Offset] = ::getCppuType( (const Reference< lang::XTypeProvider > *)0 );
123 // class code extra types: [[XComponent,] XWeak[, XAggregation]]
124 switch (nClassCode)
126 case 4:
127 pTypeAr[nType2Offset +2] = ::getCppuType( (const Reference< lang::XComponent > *)0 );
128 pTypeAr[nType2Offset +1] = ::getCppuType( (const Reference< XWeak > *)0 );
129 break;
130 case 3:
131 pTypeAr[nType2Offset +3] = ::getCppuType( (const Reference< lang::XComponent > *)0 );
132 case 2:
133 pTypeAr[nType2Offset +2] = ::getCppuType( (const Reference< XAggregation > *)0 );
134 case 1:
135 pTypeAr[nType2Offset +1] = ::getCppuType( (const Reference< XWeak > *)0 );
138 pTypes = types;
141 //__________________________________________________________________________________________________
142 Sequence< Type > ClassData::getTypes() SAL_THROW(())
144 if (! pTypes)
145 initTypeProvider();
146 return *pTypes;
148 //__________________________________________________________________________________________________
149 Sequence< sal_Int8 > ClassData::getImplementationId() SAL_THROW(())
151 if (! pTypes)
152 initTypeProvider();
153 return *pId;
156 //--------------------------------------------------------------------------------------------------
157 static inline sal_Bool td_equals(
158 typelib_TypeDescription * pTD, typelib_TypeDescriptionReference * pType )
159 SAL_THROW(())
161 return (pTD->pWeakRef == pType ||
162 (pTD->pTypeName->length == pType->pTypeName->length &&
163 rtl_ustr_compare( pTD->pTypeName->buffer, pType->pTypeName->buffer ) == 0));
165 //__________________________________________________________________________________________________
166 Any ClassData::query( const Type & rType, lang::XTypeProvider * pBase ) SAL_THROW(())
168 if (rType == ::getCppuType( (const Reference< XInterface > *)0 ))
169 return Any( &pBase, ::getCppuType( (const Reference< XInterface > *)0 ) );
170 for ( sal_Int32 nPos = 0; nPos < nType2Offset; ++nPos )
172 const Type_Offset & rTO = arType2Offset[nPos];
173 typelib_InterfaceTypeDescription * pTD = rTO.pTD;
174 while (pTD)
176 if (td_equals( (typelib_TypeDescription *)pTD,
177 *(typelib_TypeDescriptionReference **)&rType ))
179 void * pInterface = (char *)pBase + rTO.nOffset;
180 return Any( &pInterface, (typelib_TypeDescription *)pTD );
182 pTD = pTD->pBaseTypeDescription;
185 if (rType == ::getCppuType( (const Reference< lang::XTypeProvider > *)0 ))
186 return Any( &pBase, ::getCppuType( (const Reference< lang::XTypeProvider > *)0 ) );
188 return Any();
191 //##################################################################################################
192 //##################################################################################################
193 //##################################################################################################
195 // WeakComponentImplHelperBase
196 //__________________________________________________________________________________________________
197 WeakComponentImplHelperBase::WeakComponentImplHelperBase( Mutex & rMutex )
198 SAL_THROW(())
199 : rBHelper( rMutex )
202 //__________________________________________________________________________________________________
203 WeakComponentImplHelperBase::~WeakComponentImplHelperBase()
204 SAL_THROW(())
207 //__________________________________________________________________________________________________
208 void WeakComponentImplHelperBase::disposing()
211 //__________________________________________________________________________________________________
212 Any WeakComponentImplHelperBase::queryInterface( Type const & rType )
213 throw (RuntimeException)
215 if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
217 void * p = static_cast< lang::XComponent * >( this );
218 return Any( &p, rType );
220 return OWeakObject::queryInterface( rType );
222 //__________________________________________________________________________________________________
223 void WeakComponentImplHelperBase::acquire()
224 throw ()
226 OWeakObject::acquire();
228 //__________________________________________________________________________________________________
229 void WeakComponentImplHelperBase::release()
230 throw ()
232 if (osl_atomic_decrement( &m_refCount ) == 0) {
233 // ensure no other references are created, via the weak connection point, from now on
234 disposeWeakConnectionPoint();
235 // restore reference count:
236 osl_atomic_increment( &m_refCount );
237 if (! rBHelper.bDisposed) {
238 try {
239 dispose();
241 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);
247 OSL_ASSERT( rBHelper.bDisposed );
249 OWeakObject::release();
252 //__________________________________________________________________________________________________
253 void WeakComponentImplHelperBase::dispose()
254 throw (RuntimeException)
256 ClearableMutexGuard aGuard( rBHelper.rMutex );
257 if (!rBHelper.bDisposed && !rBHelper.bInDispose)
259 rBHelper.bInDispose = sal_True;
260 aGuard.clear();
263 // side effect: keeping a reference to this
264 lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
267 rBHelper.aLC.disposeAndClear( aEvt );
268 disposing();
270 catch (...)
272 MutexGuard aGuard2( rBHelper.rMutex );
273 // bDisposed and bInDispose must be set in this order:
274 rBHelper.bDisposed = sal_True;
275 rBHelper.bInDispose = sal_False;
276 throw;
278 MutexGuard aGuard2( rBHelper.rMutex );
279 // bDisposed and bInDispose must be set in this order:
280 rBHelper.bDisposed = sal_True;
281 rBHelper.bInDispose = sal_False;
283 catch (RuntimeException &)
285 throw;
287 catch (Exception & exc)
289 throw RuntimeException(
290 OUString(
291 "unexpected UNO exception caught: ") +
292 exc.Message, Reference< XInterface >() );
296 //__________________________________________________________________________________________________
297 void WeakComponentImplHelperBase::addEventListener(
298 Reference< lang::XEventListener > const & xListener )
299 throw (RuntimeException)
301 ClearableMutexGuard aGuard( rBHelper.rMutex );
302 if (rBHelper.bDisposed || rBHelper.bInDispose)
304 aGuard.clear();
305 lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
306 xListener->disposing( aEvt );
308 else
310 rBHelper.addListener( ::getCppuType( &xListener ), xListener );
313 //__________________________________________________________________________________________________
314 void WeakComponentImplHelperBase::removeEventListener(
315 Reference< lang::XEventListener > const & xListener )
316 throw (RuntimeException)
318 rBHelper.removeListener( ::getCppuType( &xListener ), xListener );
321 // WeakAggComponentImplHelperBase
322 //__________________________________________________________________________________________________
323 WeakAggComponentImplHelperBase::WeakAggComponentImplHelperBase( Mutex & rMutex )
324 SAL_THROW(())
325 : rBHelper( rMutex )
328 //__________________________________________________________________________________________________
329 WeakAggComponentImplHelperBase::~WeakAggComponentImplHelperBase()
330 SAL_THROW(())
333 //__________________________________________________________________________________________________
334 void WeakAggComponentImplHelperBase::disposing()
337 //__________________________________________________________________________________________________
338 Any WeakAggComponentImplHelperBase::queryInterface( Type const & rType )
339 throw (RuntimeException)
341 return OWeakAggObject::queryInterface( rType );
343 //__________________________________________________________________________________________________
344 Any WeakAggComponentImplHelperBase::queryAggregation( Type const & rType )
345 throw (RuntimeException)
347 if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
349 void * p = static_cast< lang::XComponent * >( this );
350 return Any( &p, rType );
352 return OWeakAggObject::queryAggregation( rType );
354 //__________________________________________________________________________________________________
355 void WeakAggComponentImplHelperBase::acquire()
356 throw ()
358 OWeakAggObject::acquire();
360 //__________________________________________________________________________________________________
361 void WeakAggComponentImplHelperBase::release()
362 throw ()
364 Reference<XInterface> const xDelegator_(xDelegator);
365 if (xDelegator_.is()) {
366 OWeakAggObject::release();
368 else if (osl_atomic_decrement( &m_refCount ) == 0) {
369 // ensure no other references are created, via the weak connection point, from now on
370 disposeWeakConnectionPoint();
371 // restore reference count:
372 osl_atomic_increment( &m_refCount );
373 if (! rBHelper.bDisposed) {
374 try {
375 dispose();
377 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);
383 OSL_ASSERT( rBHelper.bDisposed );
385 OWeakAggObject::release();
388 //__________________________________________________________________________________________________
389 void WeakAggComponentImplHelperBase::dispose()
390 throw (RuntimeException)
392 ClearableMutexGuard aGuard( rBHelper.rMutex );
393 if (!rBHelper.bDisposed && !rBHelper.bInDispose)
395 rBHelper.bInDispose = sal_True;
396 aGuard.clear();
399 // side effect: keeping a reference to this
400 lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
403 rBHelper.aLC.disposeAndClear( aEvt );
404 disposing();
406 catch (...)
408 MutexGuard aGuard2( rBHelper.rMutex );
409 // bDisposed and bInDispose must be set in this order:
410 rBHelper.bDisposed = sal_True;
411 rBHelper.bInDispose = sal_False;
412 throw;
414 MutexGuard aGuard2( rBHelper.rMutex );
415 // bDisposed and bInDispose must be set in this order:
416 rBHelper.bDisposed = sal_True;
417 rBHelper.bInDispose = sal_False;
419 catch (RuntimeException &)
421 throw;
423 catch (Exception & exc)
425 throw RuntimeException(
426 OUString(
427 "unexpected UNO exception caught: ") +
428 exc.Message, Reference< XInterface >() );
432 //__________________________________________________________________________________________________
433 void WeakAggComponentImplHelperBase::addEventListener(
434 Reference< lang::XEventListener > const & xListener )
435 throw (RuntimeException)
437 ClearableMutexGuard aGuard( rBHelper.rMutex );
438 if (rBHelper.bDisposed || rBHelper.bInDispose)
440 aGuard.clear();
441 lang::EventObject aEvt( static_cast< OWeakObject * >( this ) );
442 xListener->disposing( aEvt );
444 else
446 rBHelper.addListener( ::getCppuType( &xListener ), xListener );
449 //__________________________________________________________________________________________________
450 void WeakAggComponentImplHelperBase::removeEventListener(
451 Reference< lang::XEventListener > const & xListener )
452 throw (RuntimeException)
454 rBHelper.removeListener( ::getCppuType( &xListener ), xListener );
459 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */