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 <sal/alloca.h> 27 28 #include <string.h> 29 #include <osl/diagnose.h> 30 #include <rtl/byteseq.hxx> 31 #include <rtl/ustrbuf.hxx> 32 #include <rtl/uuid.h> 33 #include <cppuhelper/compbase_ex.hxx> 34 35 #include "com/sun/star/uno/RuntimeException.hpp" 36 37 using namespace ::cppu; 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 /** Shared mutex for implementation helper initialization. 47 Not for public use. 48 */ 49 ::osl::Mutex & SAL_CALL getImplHelperInitMutex(void) SAL_THROW( () ); 50 51 //-------------------------------------------------------------------------------------------------- 52 static inline void checkInterface( Type const & rType ) 53 SAL_THROW( (RuntimeException) ) 54 { 55 if (TypeClass_INTERFACE != rType.getTypeClass()) 56 { 57 OUStringBuffer buf( 64 ); 58 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("querying for interface \"") ); 59 buf.append( rType.getTypeName() ); 60 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": no interface type!") ); 61 OUString msg( buf.makeStringAndClear() ); 62 #if OSL_DEBUG_LEVEL > 0 63 OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) ); 64 OSL_ENSURE( 0, str.getStr() ); 65 #endif 66 throw RuntimeException( msg, Reference< XInterface >() ); 67 } 68 } 69 //-------------------------------------------------------------------------------------------------- 70 static inline bool isXInterface( rtl_uString * pStr ) SAL_THROW( () ) 71 { 72 return (((OUString const *)&pStr)->equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ) != sal_False); 73 } 74 //-------------------------------------------------------------------------------------------------- 75 static inline void * makeInterface( sal_IntPtr nOffset, void * that ) SAL_THROW( () ) 76 { 77 return (((char *)that) + nOffset); 78 } 79 //-------------------------------------------------------------------------------------------------- 80 static inline bool __td_equals( 81 typelib_TypeDescriptionReference const * pTDR1, 82 typelib_TypeDescriptionReference const * pTDR2 ) 83 SAL_THROW( () ) 84 { 85 return ((pTDR1 == pTDR2) || 86 ((OUString const *)&pTDR1->pTypeName)->equals( *(OUString const *)&pTDR2->pTypeName ) != sal_False); 87 } 88 //-------------------------------------------------------------------------------------------------- 89 static inline type_entry * __getTypeEntries( class_data * cd ) 90 SAL_THROW( (RuntimeException) ) 91 { 92 type_entry * pEntries = cd->m_typeEntries; 93 if (! cd->m_storedTypeRefs) // not inited? 94 { 95 MutexGuard guard( getImplHelperInitMutex() ); 96 if (! cd->m_storedTypeRefs) // not inited? 97 { 98 // get all types 99 for ( sal_Int32 n = cd->m_nTypes; n--; ) 100 { 101 type_entry * pEntry = &pEntries[ n ]; 102 Type const & rType = (*pEntry->m_type.getCppuType)( 0 ); 103 OSL_ENSURE( rType.getTypeClass() == TypeClass_INTERFACE, "### wrong helper init: expected interface!" ); 104 OSL_ENSURE( ! isXInterface( rType.getTypeLibType()->pTypeName ), "### want to implement XInterface: template argument is XInterface?!?!?!" ); 105 if (rType.getTypeClass() != TypeClass_INTERFACE) 106 { 107 OUStringBuffer buf( 48 ); 108 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("type \"") ); 109 buf.append( rType.getTypeName() ); 110 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" is no interface type!") ); 111 OUString msg( buf.makeStringAndClear() ); 112 #if OSL_DEBUG_LEVEL > 0 113 OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) ); 114 OSL_ENSURE( 0, str.getStr() ); 115 #endif 116 throw RuntimeException( msg, Reference< XInterface >() ); 117 } 118 // ref is statically held by getCppuType() 119 pEntry->m_type.typeRef = rType.getTypeLibType(); 120 } 121 cd->m_storedTypeRefs = sal_True; 122 } 123 } 124 return pEntries; 125 } 126 //-------------------------------------------------------------------------------------------------- 127 static inline void __fillTypes( Type * types, class_data * cd ) 128 SAL_THROW( (RuntimeException) ) 129 { 130 type_entry * pEntries = __getTypeEntries( cd ); 131 for ( sal_Int32 n = cd->m_nTypes; n--; ) 132 { 133 types[ n ] = pEntries[ n ].m_type.typeRef; 134 } 135 } 136 //-------------------------------------------------------------------------------------------------- 137 namespace { 138 139 bool recursivelyFindType( 140 typelib_TypeDescriptionReference const * demandedType, 141 typelib_InterfaceTypeDescription const * type, sal_IntPtr * offset) 142 { 143 // This code assumes that the vtables of a multiple-inheritance class (the 144 // offset amount by which to adjust the this pointer) follow one another in 145 // the object layout, and that they contain slots for the inherited classes 146 // in a specifc order. In theory, that need not hold for any given 147 // platform; in practice, it seems to work well on all supported platforms: 148 next: 149 for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) { 150 if (i > 0) { 151 *offset += sizeof (void *); 152 } 153 typelib_InterfaceTypeDescription const * base = type->ppBaseTypes[i]; 154 // ignore XInterface: 155 if (base->nBaseTypes > 0) { 156 if (__td_equals( 157 reinterpret_cast< 158 typelib_TypeDescriptionReference const * >(base), 159 demandedType)) 160 { 161 return true; 162 } 163 // Profiling showed that it is important to speed up the common case 164 // of only one base: 165 if (type->nBaseTypes == 1) { 166 type = base; 167 goto next; 168 } 169 if (recursivelyFindType(demandedType, base, offset)) { 170 return true; 171 } 172 } 173 } 174 return false; 175 } 176 177 } 178 179 static inline void * __queryDeepNoXInterface( 180 typelib_TypeDescriptionReference * pDemandedTDR, class_data * cd, void * that ) 181 SAL_THROW( (RuntimeException) ) 182 { 183 type_entry * pEntries = __getTypeEntries( cd ); 184 sal_Int32 nTypes = cd->m_nTypes; 185 sal_Int32 n; 186 187 // try top interfaces without getting td 188 for ( n = 0; n < nTypes; ++n ) 189 { 190 if (__td_equals( pEntries[ n ].m_type.typeRef, pDemandedTDR )) 191 { 192 return makeInterface( pEntries[ n ].m_offset, that ); 193 } 194 } 195 // query deep getting td 196 for ( n = 0; n < nTypes; ++n ) 197 { 198 typelib_TypeDescription * pTD = 0; 199 TYPELIB_DANGER_GET( &pTD, pEntries[ n ].m_type.typeRef ); 200 if (pTD) 201 { 202 // exclude top (already tested) and bottom (XInterface) interface 203 OSL_ENSURE( 204 reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD)-> 205 nBaseTypes > 0, 206 "### want to implement XInterface:" 207 " template argument is XInterface?!?!?!" ); 208 sal_IntPtr offset = pEntries[n].m_offset; 209 bool found = recursivelyFindType( 210 pDemandedTDR, 211 reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD), 212 &offset); 213 TYPELIB_DANGER_RELEASE( pTD ); 214 if (found) { 215 return makeInterface( offset, that ); 216 } 217 } 218 else 219 { 220 OUStringBuffer buf( 64 ); 221 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot get type description for type \"") ); 222 buf.append( pEntries[ n ].m_type.typeRef->pTypeName ); 223 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") ); 224 OUString msg( buf.makeStringAndClear() ); 225 #if OSL_DEBUG_LEVEL > 0 226 OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) ); 227 OSL_ENSURE( 0, str.getStr() ); 228 #endif 229 throw RuntimeException( msg, Reference< XInterface >() ); 230 } 231 } 232 return 0; 233 } 234 235 // ImplHelper 236 //================================================================================================== 237 Any SAL_CALL ImplHelper_query( 238 Type const & rType, class_data * cd, void * that ) 239 SAL_THROW( (RuntimeException) ) 240 { 241 checkInterface( rType ); 242 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType(); 243 244 void * p; 245 // shortcut for XInterface 246 if (isXInterface( pTDR->pTypeName )) 247 { 248 // take first one 249 p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that ); 250 } 251 else 252 { 253 p = __queryDeepNoXInterface( pTDR, cd, that ); 254 if (! p) 255 { 256 return Any(); 257 } 258 } 259 return Any( &p, pTDR ); 260 } 261 //================================================================================================== 262 Any SAL_CALL ImplHelper_queryNoXInterface( 263 Type const & rType, class_data * cd, void * that ) 264 SAL_THROW( (RuntimeException) ) 265 { 266 checkInterface( rType ); 267 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType(); 268 269 void * p = __queryDeepNoXInterface( pTDR, cd, that ); 270 if (p) 271 { 272 return Any( &p, pTDR ); 273 } 274 else 275 { 276 return Any(); 277 } 278 } 279 //================================================================================================== 280 Sequence< sal_Int8 > SAL_CALL ImplHelper_getImplementationId( class_data * cd ) 281 SAL_THROW( (RuntimeException) ) 282 { 283 if (! cd->m_createdId) 284 { 285 sal_uInt8 * id = (sal_uInt8 *)alloca( 16 ); 286 ::rtl_createUuid( (sal_uInt8 *)id, 0, sal_True ); 287 288 MutexGuard guard( getImplHelperInitMutex() ); 289 if (! cd->m_createdId) 290 { 291 memcpy( cd->m_id, id, 16 ); 292 cd->m_createdId = sal_True; 293 } 294 } 295 296 sal_Sequence * seq = 0; 297 ::rtl_byte_sequence_constructFromArray( &seq, cd->m_id, 16 ); 298 return Sequence< sal_Int8 >( seq, SAL_NO_ACQUIRE ); 299 } 300 //================================================================================================== 301 Sequence< Type > SAL_CALL ImplHelper_getTypes( 302 class_data * cd ) 303 SAL_THROW( (RuntimeException) ) 304 { 305 Sequence< Type > types( cd->m_nTypes ); 306 Type * pTypes = types.getArray(); 307 __fillTypes( pTypes, cd ); 308 return types; 309 } 310 //================================================================================================== 311 Sequence< Type > SAL_CALL ImplInhHelper_getTypes( 312 class_data * cd, Sequence< Type > const & rAddTypes ) 313 SAL_THROW( (RuntimeException) ) 314 { 315 sal_Int32 nImplTypes = cd->m_nTypes; 316 sal_Int32 nAddTypes = rAddTypes.getLength(); 317 Sequence< Type > types( nImplTypes + nAddTypes ); 318 Type * pTypes = types.getArray(); 319 __fillTypes( pTypes, cd ); 320 // append base types 321 Type const * pAddTypes = rAddTypes.getConstArray(); 322 while (nAddTypes--) 323 { 324 pTypes[ nImplTypes + nAddTypes ] = pAddTypes[ nAddTypes ]; 325 } 326 return types; 327 } 328 329 // WeakImplHelper 330 //================================================================================================== 331 Any SAL_CALL WeakImplHelper_query( 332 Type const & rType, class_data * cd, void * that, OWeakObject * pBase ) 333 SAL_THROW( (RuntimeException) ) 334 { 335 checkInterface( rType ); 336 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType(); 337 338 // shortcut XInterface to OWeakObject 339 if (! isXInterface( pTDR->pTypeName )) 340 { 341 void * p = __queryDeepNoXInterface( pTDR, cd, that ); 342 if (p) 343 { 344 return Any( &p, pTDR ); 345 } 346 } 347 return pBase->OWeakObject::queryInterface( rType ); 348 } 349 //================================================================================================== 350 Sequence< Type > SAL_CALL WeakImplHelper_getTypes( 351 class_data * cd ) 352 SAL_THROW( (RuntimeException) ) 353 { 354 sal_Int32 nTypes = cd->m_nTypes; 355 Sequence< Type > types( nTypes +1 ); 356 Type * pTypes = types.getArray(); 357 __fillTypes( pTypes, cd ); 358 pTypes[ nTypes ] = ::getCppuType( (Reference< XWeak > const *)0 ); 359 return types; 360 } 361 362 // WeakAggImplHelper 363 //================================================================================================== 364 Any SAL_CALL WeakAggImplHelper_queryAgg( 365 Type const & rType, class_data * cd, void * that, OWeakAggObject * pBase ) 366 SAL_THROW( (RuntimeException) ) 367 { 368 checkInterface( rType ); 369 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType(); 370 371 // shortcut XInterface to OWeakAggObject 372 if (! isXInterface( pTDR->pTypeName )) 373 { 374 void * p = __queryDeepNoXInterface( pTDR, cd, that ); 375 if (p) 376 { 377 return Any( &p, pTDR ); 378 } 379 } 380 return pBase->OWeakAggObject::queryAggregation( rType ); 381 } 382 //================================================================================================== 383 Sequence< Type > SAL_CALL WeakAggImplHelper_getTypes( 384 class_data * cd ) 385 SAL_THROW( (RuntimeException) ) 386 { 387 sal_Int32 nTypes = cd->m_nTypes; 388 Sequence< Type > types( nTypes +2 ); 389 Type * pTypes = types.getArray(); 390 __fillTypes( pTypes, cd ); 391 pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 ); 392 pTypes[ nTypes ] = ::getCppuType( (const Reference< XAggregation > *)0 ); 393 return types; 394 } 395 396 // WeakComponentImplHelper 397 //================================================================================================== 398 Any SAL_CALL WeakComponentImplHelper_query( 399 Type const & rType, class_data * cd, void * that, WeakComponentImplHelperBase * pBase ) 400 SAL_THROW( (RuntimeException) ) 401 { 402 checkInterface( rType ); 403 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType(); 404 405 // shortcut XInterface to WeakComponentImplHelperBase 406 if (! isXInterface( pTDR->pTypeName )) 407 { 408 void * p = __queryDeepNoXInterface( pTDR, cd, that ); 409 if (p) 410 { 411 return Any( &p, pTDR ); 412 } 413 } 414 return pBase->WeakComponentImplHelperBase::queryInterface( rType ); 415 } 416 //================================================================================================== 417 Sequence< Type > SAL_CALL WeakComponentImplHelper_getTypes( 418 class_data * cd ) 419 SAL_THROW( (RuntimeException) ) 420 { 421 sal_Int32 nTypes = cd->m_nTypes; 422 Sequence< Type > types( nTypes +2 ); 423 Type * pTypes = types.getArray(); 424 __fillTypes( pTypes, cd ); 425 pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 ); 426 pTypes[ nTypes ] = ::getCppuType( (Reference< lang::XComponent > const *)0 ); 427 return types; 428 } 429 430 // WeakAggComponentImplHelper 431 //================================================================================================== 432 Any SAL_CALL WeakAggComponentImplHelper_queryAgg( 433 Type const & rType, class_data * cd, void * that, WeakAggComponentImplHelperBase * pBase ) 434 SAL_THROW( (RuntimeException) ) 435 { 436 checkInterface( rType ); 437 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType(); 438 439 // shortcut XInterface to WeakAggComponentImplHelperBase 440 if (! isXInterface( pTDR->pTypeName )) 441 { 442 void * p = __queryDeepNoXInterface( pTDR, cd, that ); 443 if (p) 444 { 445 return Any( &p, pTDR ); 446 } 447 } 448 return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType ); 449 } 450 //================================================================================================== 451 Sequence< Type > SAL_CALL WeakAggComponentImplHelper_getTypes( 452 class_data * cd ) 453 SAL_THROW( (RuntimeException) ) 454 { 455 sal_Int32 nTypes = cd->m_nTypes; 456 Sequence< Type > types( nTypes +3 ); 457 Type * pTypes = types.getArray(); 458 __fillTypes( pTypes, cd ); 459 pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 ); 460 pTypes[ nTypes++ ] = ::getCppuType( (const Reference< XAggregation > *)0 ); 461 pTypes[ nTypes ] = ::getCppuType( (const Reference< lang::XComponent > *)0 ); 462 return types; 463 } 464 465 } 466