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