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