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 //================================================================================================== 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 //__________________________________________________________________________________________________ 59 ClassDataBase::ClassDataBase() SAL_THROW( () ) 60 : bOffsetsInit( sal_False ) 61 , nType2Offset( 0 ) 62 , nClassCode( 0 ) 63 , pTypes( 0 ) 64 , pId( 0 ) 65 { 66 } 67 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 152 Sequence< Type > ClassData::getTypes() SAL_THROW( () ) 153 { 154 if (! pTypes) 155 initTypeProvider(); 156 return *pTypes; 157 } 158 //__________________________________________________________________________________________________ 159 Sequence< sal_Int8 > ClassData::getImplementationId() SAL_THROW( () ) 160 { 161 if (! pTypes) 162 initTypeProvider(); 163 return *pId; 164 } 165 166 //-------------------------------------------------------------------------------------------------- 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 207 WeakComponentImplHelperBase::WeakComponentImplHelperBase( Mutex & rMutex ) 208 SAL_THROW( () ) 209 : rBHelper( rMutex ) 210 { 211 } 212 //__________________________________________________________________________________________________ 213 WeakComponentImplHelperBase::~WeakComponentImplHelperBase() 214 SAL_THROW( () ) 215 { 216 } 217 //__________________________________________________________________________________________________ 218 void WeakComponentImplHelperBase::disposing() 219 { 220 } 221 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 233 void WeakComponentImplHelperBase::acquire() 234 throw () 235 { 236 OWeakObject::acquire(); 237 } 238 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 333 WeakAggComponentImplHelperBase::WeakAggComponentImplHelperBase( Mutex & rMutex ) 334 SAL_THROW( () ) 335 : rBHelper( rMutex ) 336 { 337 } 338 //__________________________________________________________________________________________________ 339 WeakAggComponentImplHelperBase::~WeakAggComponentImplHelperBase() 340 SAL_THROW( () ) 341 { 342 } 343 //__________________________________________________________________________________________________ 344 void WeakAggComponentImplHelperBase::disposing() 345 { 346 } 347 //__________________________________________________________________________________________________ 348 Any WeakAggComponentImplHelperBase::queryInterface( Type const & rType ) 349 throw (RuntimeException) 350 { 351 return OWeakAggObject::queryInterface( rType ); 352 } 353 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 365 void WeakAggComponentImplHelperBase::acquire() 366 throw () 367 { 368 OWeakAggObject::acquire(); 369 } 370 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 460 void WeakAggComponentImplHelperBase::removeEventListener( 461 Reference< lang::XEventListener > const & xListener ) 462 throw (RuntimeException) 463 { 464 rBHelper.removeListener( ::getCppuType( &xListener ), xListener ); 465 } 466 467 } 468