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_stoc.hxx" 30 31 #include <hash_map> 32 #include <hash_set> 33 34 #include <osl/diagnose.h> 35 #include <osl/interlck.h> 36 #include <osl/mutex.hxx> 37 38 #include <uno/dispatcher.h> 39 #include <uno/data.h> 40 #include <uno/any2.h> 41 #include <uno/mapping.hxx> 42 43 #include <cppuhelper/factory.hxx> 44 #include <cppuhelper/implbase3.hxx> 45 #include <cppuhelper/implementationentry.hxx> 46 47 #include <com/sun/star/uno/XAggregation.hpp> 48 #include <com/sun/star/script/XTypeConverter.hpp> 49 #include <com/sun/star/script/XInvocationAdapterFactory.hpp> 50 #include <com/sun/star/script/XInvocationAdapterFactory2.hpp> 51 #include <com/sun/star/script/XInvocation.hpp> 52 #include <com/sun/star/lang/XServiceInfo.hpp> 53 #include <com/sun/star/lang/XSingleServiceFactory.hpp> 54 #include <com/sun/star/registry/XSimpleRegistry.hpp> 55 #include <com/sun/star/registry/XRegistryKey.hpp> 56 #include <com/sun/star/reflection/InvocationTargetException.hpp> 57 #include "com/sun/star/uno/RuntimeException.hpp" 58 59 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 60 61 #define SERVICENAME "com.sun.star.script.InvocationAdapterFactory" 62 #define IMPLNAME "com.sun.star.comp.stoc.InvocationAdapterFactory" 63 64 65 using namespace ::std; 66 using namespace ::rtl; 67 using namespace ::osl; 68 using namespace ::com::sun::star; 69 using namespace ::com::sun::star::uno; 70 71 namespace stoc_invadp 72 { 73 74 static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; 75 76 static Sequence< OUString > invadp_getSupportedServiceNames() 77 { 78 static Sequence < OUString > *pNames = 0; 79 if( ! pNames ) 80 { 81 MutexGuard guard( Mutex::getGlobalMutex() ); 82 if( !pNames ) 83 { 84 static Sequence< OUString > seqNames(1); 85 seqNames.getArray()[0] = 86 OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); 87 pNames = &seqNames; 88 } 89 } 90 return *pNames; 91 } 92 93 static OUString invadp_getImplementationName() 94 { 95 static OUString *pImplName = 0; 96 if( ! pImplName ) 97 { 98 MutexGuard guard( Mutex::getGlobalMutex() ); 99 if( ! pImplName ) 100 { 101 static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); 102 pImplName = &implName; 103 } 104 } 105 return *pImplName; 106 } 107 108 struct hash_ptr 109 { 110 inline size_t operator() ( void * p ) const 111 { return (size_t)p; } 112 }; 113 typedef hash_set< void *, hash_ptr, equal_to< void * > > t_ptr_set; 114 typedef hash_map< void *, t_ptr_set, hash_ptr, equal_to< void * > > t_ptr_map; 115 116 //============================================================================== 117 class FactoryImpl 118 : public ::cppu::WeakImplHelper3< lang::XServiceInfo, 119 script::XInvocationAdapterFactory, 120 script::XInvocationAdapterFactory2 > 121 { 122 public: 123 Mapping m_aUno2Cpp; 124 Mapping m_aCpp2Uno; 125 uno_Interface * m_pConverter; 126 127 typelib_TypeDescription * m_pInvokMethodTD; 128 typelib_TypeDescription * m_pSetValueTD; 129 typelib_TypeDescription * m_pGetValueTD; 130 typelib_TypeDescription * m_pAnySeqTD; 131 typelib_TypeDescription * m_pShortSeqTD; 132 typelib_TypeDescription * m_pConvertToTD; 133 134 Mutex m_mutex; 135 t_ptr_map m_receiver2adapters; 136 137 FactoryImpl( Reference< XComponentContext > const & xContext ) 138 SAL_THROW( (RuntimeException) ); 139 virtual ~FactoryImpl() SAL_THROW( () ); 140 141 // XServiceInfo 142 virtual OUString SAL_CALL getImplementationName() 143 throw (RuntimeException); 144 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) 145 throw (RuntimeException); 146 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() 147 throw (RuntimeException); 148 149 // XInvocationAdapterFactory 150 virtual Reference< XInterface > SAL_CALL createAdapter( 151 const Reference< script::XInvocation > & xReceiver, const Type & rType ) 152 throw (RuntimeException); 153 // XInvocationAdapterFactory2 154 virtual Reference< XInterface > SAL_CALL createAdapter( 155 const Reference< script::XInvocation > & xReceiver, 156 const Sequence< Type > & rTypes ) 157 throw (RuntimeException); 158 }; 159 struct AdapterImpl; 160 //============================================================================== 161 struct InterfaceAdapterImpl : public uno_Interface 162 { 163 AdapterImpl * m_pAdapter; 164 typelib_InterfaceTypeDescription * m_pTypeDescr; 165 }; 166 //============================================================================== 167 struct AdapterImpl 168 { 169 oslInterlockedCount m_nRef; 170 FactoryImpl * m_pFactory; 171 void * m_key; // map key 172 uno_Interface * m_pReceiver; // XInvocation receiver 173 174 sal_Int32 m_nInterfaces; 175 InterfaceAdapterImpl * m_pInterfaces; 176 177 // XInvocation calls 178 void getValue( 179 const typelib_TypeDescription * pMemberType, 180 void * pReturn, void * pArgs[], uno_Any ** ppException ); 181 void setValue( 182 const typelib_TypeDescription * pMemberType, 183 void * pReturn, void * pArgs[], uno_Any ** ppException ); 184 void invoke( 185 const typelib_TypeDescription * pMemberType, 186 void * pReturn, void * pArgs[], uno_Any ** ppException ); 187 188 bool coerce_assign( 189 void * pDest, typelib_TypeDescriptionReference * pType, 190 uno_Any * pSource, uno_Any * pExc ); 191 inline bool coerce_construct( 192 void * pDest, typelib_TypeDescriptionReference * pType, 193 uno_Any * pSource, uno_Any * pExc ); 194 195 inline void acquire() 196 SAL_THROW( () ); 197 inline void release() 198 SAL_THROW( () ); 199 inline ~AdapterImpl() 200 SAL_THROW( () ); 201 inline AdapterImpl( 202 void * key, Reference< script::XInvocation > const & xReceiver, 203 const Sequence< Type > & rTypes, 204 FactoryImpl * pFactory ) 205 SAL_THROW( (RuntimeException) ); 206 }; 207 //______________________________________________________________________________ 208 inline AdapterImpl::~AdapterImpl() 209 SAL_THROW( () ) 210 { 211 for ( sal_Int32 nPos = m_nInterfaces; nPos--; ) 212 { 213 ::typelib_typedescription_release( 214 (typelib_TypeDescription *)m_pInterfaces[ nPos ].m_pTypeDescr ); 215 } 216 delete [] m_pInterfaces; 217 // 218 (*m_pReceiver->release)( m_pReceiver ); 219 m_pFactory->release(); 220 } 221 //______________________________________________________________________________ 222 inline void AdapterImpl::acquire() 223 SAL_THROW( () ) 224 { 225 ::osl_incrementInterlockedCount( &m_nRef ); 226 } 227 //______________________________________________________________________________ 228 inline void AdapterImpl::release() 229 SAL_THROW( () ) 230 { 231 bool delete_this = false; 232 { 233 MutexGuard guard( m_pFactory->m_mutex ); 234 if (! ::osl_decrementInterlockedCount( &m_nRef )) 235 { 236 t_ptr_map::iterator iFind( 237 m_pFactory->m_receiver2adapters.find( m_key ) ); 238 OSL_ASSERT( m_pFactory->m_receiver2adapters.end() != iFind ); 239 t_ptr_set & adapter_set = iFind->second; 240 if (adapter_set.erase( this ) != 1) { 241 OSL_ASSERT( false ); 242 } 243 if (adapter_set.empty()) 244 { 245 m_pFactory->m_receiver2adapters.erase( iFind ); 246 } 247 delete_this = true; 248 } 249 } 250 if (delete_this) 251 delete this; 252 } 253 254 //------------------------------------------------------------------------------ 255 static inline void constructRuntimeException( 256 uno_Any * pExc, const OUString & rMsg ) 257 { 258 RuntimeException exc( rMsg, Reference< XInterface >() ); 259 // no conversion neeeded due to binary compatibility + no convertable type 260 ::uno_type_any_construct( 261 pExc, &exc, ::getCppuType( &exc ).getTypeLibType(), 0 ); 262 } 263 264 //------------------------------------------------------------------------------ 265 static inline sal_Bool type_equals( 266 typelib_TypeDescriptionReference * pType1, 267 typelib_TypeDescriptionReference * pType2 ) 268 SAL_THROW( () ) 269 { 270 return (pType1 == pType2 || 271 (pType1->pTypeName->length == pType2->pTypeName->length && 272 0 == ::rtl_ustr_compare( 273 pType1->pTypeName->buffer, pType2->pTypeName->buffer ))); 274 } 275 276 //______________________________________________________________________________ 277 bool AdapterImpl::coerce_assign( 278 void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource, 279 uno_Any * pOutExc ) 280 { 281 if (typelib_TypeClass_ANY == pType->eTypeClass) 282 { 283 ::uno_type_any_assign( 284 (uno_Any *)pDest, pSource->pData, pSource->pType, 0, 0 ); 285 return true; 286 } 287 if (::uno_type_assignData( 288 pDest, pType, pSource->pData, pSource->pType, 0, 0, 0 )) 289 { 290 return true; 291 } 292 else // try type converter 293 { 294 uno_Any ret; 295 void * args[ 2 ]; 296 args[ 0 ] = pSource; 297 args[ 1 ] = &pType; 298 uno_Any exc; 299 uno_Any * p_exc = &exc; 300 301 // converTo() 302 (*m_pFactory->m_pConverter->pDispatcher)( 303 m_pFactory->m_pConverter, 304 m_pFactory->m_pConvertToTD, &ret, args, &p_exc ); 305 306 if (p_exc) // exception occured 307 { 308 OSL_ASSERT( 309 p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION ); 310 if (typelib_typedescriptionreference_isAssignableFrom( 311 ::getCppuType( 312 (RuntimeException const *) 0 ).getTypeLibType(), 313 p_exc->pType )) 314 { 315 // is RuntimeException or derived: rethrow 316 uno_type_any_construct( 317 pOutExc, p_exc->pData, p_exc->pType, 0 ); 318 } 319 else 320 { 321 // set runtime exception 322 constructRuntimeException( 323 pOutExc, OUSTR("type coercion failed: ") + 324 reinterpret_cast< Exception const * >( 325 p_exc->pData )->Message ); 326 } 327 ::uno_any_destruct( p_exc, 0 ); 328 // pOutExc constructed 329 return false; 330 } 331 else 332 { 333 bool succ = (sal_False != ::uno_type_assignData( 334 pDest, pType, ret.pData, ret.pType, 0, 0, 0 )); 335 ::uno_any_destruct( &ret, 0 ); 336 OSL_ENSURE( 337 succ, "### conversion succeeded, but assignment failed!?" ); 338 if (! succ) 339 { 340 // set runtime exception 341 constructRuntimeException( 342 pOutExc, 343 OUSTR("type coercion failed: " 344 "conversion succeeded, but assignment failed?!") ); 345 } 346 return succ; 347 } 348 } 349 } 350 //______________________________________________________________________________ 351 inline bool AdapterImpl::coerce_construct( 352 void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource, 353 uno_Any * pExc ) 354 { 355 if (typelib_TypeClass_ANY == pType->eTypeClass) 356 { 357 ::uno_type_copyData( pDest, pSource, pType, 0 ); 358 return true; 359 } 360 if (type_equals( pType, pSource->pType)) 361 { 362 ::uno_type_copyData( pDest, pSource->pData, pType, 0 ); 363 return true; 364 } 365 ::uno_type_constructData( pDest, pType ); 366 return coerce_assign( pDest, pType, pSource, pExc ); 367 } 368 369 //------------------------------------------------------------------------------ 370 static void handleInvokExc( uno_Any * pDest, uno_Any * pSource ) 371 { 372 OUString const & name = 373 *reinterpret_cast< OUString const * >( &pSource->pType->pTypeName ); 374 375 if (name.equalsAsciiL( 376 RTL_CONSTASCII_STRINGPARAM( 377 "com.sun.star.reflection.InvocationTargetException") )) 378 { 379 // unwrap invocation target exception 380 uno_Any * target_exc = 381 &reinterpret_cast< reflection::InvocationTargetException * >( 382 pSource->pData )->TargetException; 383 ::uno_type_any_construct( 384 pDest, target_exc->pData, target_exc->pType, 0 ); 385 } 386 else // all other exceptions are wrapped to RuntimeException 387 { 388 if (typelib_TypeClass_EXCEPTION == pSource->pType->eTypeClass) 389 { 390 constructRuntimeException( 391 pDest, ((Exception const *)pSource->pData)->Message ); 392 } 393 else 394 { 395 constructRuntimeException( 396 pDest, OUSTR("no exception has been thrown via invocation?!") ); 397 } 398 } 399 } 400 //______________________________________________________________________________ 401 void AdapterImpl::getValue( 402 const typelib_TypeDescription * pMemberType, 403 void * pReturn, void * [], uno_Any ** ppException ) 404 { 405 uno_Any aInvokRet; 406 void * pInvokArgs[1]; 407 pInvokArgs[0] = 408 &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName; 409 uno_Any aInvokExc; 410 uno_Any * pInvokExc = &aInvokExc; 411 412 // getValue() 413 (*m_pReceiver->pDispatcher)( 414 m_pReceiver, m_pFactory->m_pGetValueTD, 415 &aInvokRet, pInvokArgs, &pInvokExc ); 416 417 if (pInvokExc) // getValue() call exception 418 { 419 handleInvokExc( *ppException, pInvokExc ); 420 ::uno_any_destruct( pInvokExc, 0 ); // cleanup 421 } 422 else // invocation call succeeded 423 { 424 if (coerce_construct( 425 pReturn, 426 ((typelib_InterfaceAttributeTypeDescription *) 427 pMemberType)->pAttributeTypeRef, 428 &aInvokRet, *ppException )) 429 { 430 *ppException = 0; // no exceptions be thrown 431 } 432 ::uno_any_destruct( &aInvokRet, 0 ); 433 } 434 } 435 //______________________________________________________________________________ 436 void AdapterImpl::setValue( 437 const typelib_TypeDescription * pMemberType, 438 void *, void * pArgs[], uno_Any ** ppException ) 439 { 440 uno_Any aInvokVal; 441 ::uno_type_any_construct( 442 &aInvokVal, pArgs[0], 443 ((typelib_InterfaceAttributeTypeDescription *) 444 pMemberType)->pAttributeTypeRef, 0 ); 445 446 void * pInvokArgs[2]; 447 pInvokArgs[0] = 448 &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName; 449 pInvokArgs[1] = &aInvokVal; 450 uno_Any aInvokExc; 451 uno_Any * pInvokExc = &aInvokExc; 452 453 // setValue() 454 (*m_pReceiver->pDispatcher)( 455 m_pReceiver, m_pFactory->m_pSetValueTD, 0, pInvokArgs, &pInvokExc ); 456 457 if (pInvokExc) // setValue() call exception 458 { 459 handleInvokExc( *ppException, pInvokExc ); 460 ::uno_any_destruct( pInvokExc, 0 ); // cleanup 461 } 462 else // invocation call succeeded 463 { 464 *ppException = 0; // no exceptions be thrown 465 } 466 467 ::uno_any_destruct( &aInvokVal, 0 ); // cleanup 468 } 469 //______________________________________________________________________________ 470 void AdapterImpl::invoke( 471 const typelib_TypeDescription * pMemberType, 472 void * pReturn, void * pArgs[], uno_Any ** ppException ) 473 { 474 sal_Int32 nParams = 475 ((typelib_InterfaceMethodTypeDescription *)pMemberType)->nParams; 476 typelib_MethodParameter * pFormalParams = 477 ((typelib_InterfaceMethodTypeDescription *)pMemberType)->pParams; 478 479 // in params 480 uno_Sequence * pInParamsSeq = 0; 481 ::uno_sequence_construct( 482 &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0, nParams, 0 ); 483 uno_Any * pInAnys = (uno_Any *)pInParamsSeq->elements; 484 sal_Int32 nOutParams = 0; 485 sal_Int32 nPos; 486 for ( nPos = nParams; nPos--; ) 487 { 488 typelib_MethodParameter const & rParam = pFormalParams[nPos]; 489 if (rParam.bIn) // is in/inout param 490 { 491 ::uno_type_any_assign( 492 &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef, 0, 0 ); 493 } 494 // else: pure out is empty any 495 496 if (rParam.bOut) 497 ++nOutParams; 498 } 499 500 // out params, out indices 501 uno_Sequence * pOutIndices; 502 uno_Sequence * pOutParams; 503 // return value 504 uno_Any aInvokRet; 505 // perform call 506 void * pInvokArgs[4]; 507 pInvokArgs[0] = 508 &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName; 509 pInvokArgs[1] = &pInParamsSeq; 510 pInvokArgs[2] = &pOutIndices; 511 pInvokArgs[3] = &pOutParams; 512 uno_Any aInvokExc; 513 uno_Any * pInvokExc = &aInvokExc; 514 515 // invoke() call 516 (*m_pReceiver->pDispatcher)( 517 m_pReceiver, m_pFactory->m_pInvokMethodTD, 518 &aInvokRet, pInvokArgs, &pInvokExc ); 519 520 if (pInvokExc) 521 { 522 handleInvokExc( *ppException, pInvokExc ); 523 ::uno_any_destruct( pInvokExc, 0 ); // cleanup 524 } 525 else // no invocation exception 526 { 527 // write changed out params 528 OSL_ENSURE( 529 pOutParams->nElements == nOutParams && 530 pOutIndices->nElements == nOutParams, 531 "### out params lens differ!" ); 532 if (pOutParams->nElements == nOutParams && 533 pOutIndices->nElements == nOutParams) 534 { 535 sal_Int16 * pIndices = (sal_Int16 *)pOutIndices->elements; 536 uno_Any * pOut = (uno_Any *)pOutParams->elements; 537 for ( nPos = 0; nPos < nOutParams; ++nPos ) 538 { 539 sal_Int32 nIndex = pIndices[nPos]; 540 OSL_ENSURE( nIndex < nParams, "### illegal index!" ); 541 typelib_MethodParameter const & rParam = pFormalParams[nIndex]; 542 bool succ; 543 if (rParam.bIn) // is in/inout param 544 { 545 succ = coerce_assign( 546 pArgs[nIndex], rParam.pTypeRef, &pOut[nPos], 547 *ppException ); 548 } 549 else // pure out 550 { 551 succ = coerce_construct( 552 pArgs[nIndex], rParam.pTypeRef, &pOut[nPos], 553 *ppException ); 554 } 555 if (! succ) // cleanup of out params 556 { 557 for ( sal_Int32 n = 0; n <= nPos; ++n ) 558 { 559 sal_Int32 nIndex2 = pIndices[n]; 560 OSL_ENSURE( nIndex2 < nParams, "### illegal index!" ); 561 typelib_MethodParameter const & rParam2 = 562 pFormalParams[nIndex2]; 563 if (! rParam2.bIn) // is pure out param 564 { 565 ::uno_type_destructData( 566 pArgs[nIndex2], rParam2.pTypeRef, 0 ); 567 } 568 } 569 } 570 } 571 if (nPos == pOutIndices->nElements) 572 { 573 // out param copy ok; write return value 574 if (coerce_construct( 575 pReturn, 576 ((typelib_InterfaceMethodTypeDescription *) 577 pMemberType)->pReturnTypeRef, 578 &aInvokRet, *ppException )) 579 { 580 *ppException = 0; // no exception 581 } 582 } 583 } 584 else 585 { 586 // set runtime exception 587 constructRuntimeException( 588 *ppException, 589 OUSTR("out params lengths differ after invocation call!") ); 590 } 591 // cleanup invok out params 592 ::uno_destructData( &pOutIndices, m_pFactory->m_pShortSeqTD, 0 ); 593 ::uno_destructData( &pOutParams, m_pFactory->m_pAnySeqTD, 0 ); 594 // cleanup invok return value 595 ::uno_any_destruct( &aInvokRet, 0 ); 596 } 597 // cleanup constructed in params 598 ::uno_destructData( &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0 ); 599 } 600 601 extern "C" 602 { 603 //______________________________________________________________________________ 604 static void SAL_CALL adapter_acquire( uno_Interface * pUnoI ) 605 { 606 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire(); 607 } 608 //______________________________________________________________________________ 609 static void SAL_CALL adapter_release( uno_Interface * pUnoI ) 610 { 611 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release(); 612 } 613 //______________________________________________________________________________ 614 static void SAL_CALL adapter_dispatch( 615 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType, 616 void * pReturn, void * pArgs[], uno_Any ** ppException ) 617 { 618 // query to emulated interface 619 switch (((typelib_InterfaceMemberTypeDescription *)pMemberType)->nPosition) 620 { 621 case 0: // queryInterface() 622 { 623 AdapterImpl * that = 624 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter; 625 *ppException = 0; // no exc 626 typelib_TypeDescriptionReference * pDemanded = 627 *(typelib_TypeDescriptionReference **)pArgs[0]; 628 // pInterfaces[0] is XInterface 629 for ( sal_Int32 nPos = 0; nPos < that->m_nInterfaces; ++nPos ) 630 { 631 typelib_InterfaceTypeDescription * pTD = 632 that->m_pInterfaces[nPos].m_pTypeDescr; 633 while (pTD) 634 { 635 if (type_equals( 636 ((typelib_TypeDescription *)pTD)->pWeakRef, pDemanded )) 637 { 638 uno_Interface * pUnoI2 = &that->m_pInterfaces[nPos]; 639 ::uno_any_construct( 640 (uno_Any *)pReturn, &pUnoI2, 641 (typelib_TypeDescription *)pTD, 0 ); 642 return; 643 } 644 pTD = pTD->pBaseTypeDescription; 645 } 646 } 647 ::uno_any_construct( (uno_Any *)pReturn, 0, 0, 0 ); // clear() 648 break; 649 } 650 case 1: // acquire() 651 *ppException = 0; // no exc 652 adapter_acquire( pUnoI ); 653 break; 654 case 2: // release() 655 *ppException = 0; // no exc 656 adapter_release( pUnoI ); 657 break; 658 659 default: 660 { 661 AdapterImpl * that = 662 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter; 663 if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD) 664 { 665 that->invoke( pMemberType, pReturn, pArgs, ppException ); 666 } 667 else // attribute 668 { 669 if (pReturn) 670 that->getValue( pMemberType, pReturn, pArgs, ppException ); 671 else 672 that->setValue( pMemberType, pReturn, pArgs, ppException ); 673 } 674 } 675 } 676 } 677 } 678 //______________________________________________________________________________ 679 AdapterImpl::AdapterImpl( 680 void * key, Reference< script::XInvocation > const & xReceiver, 681 const Sequence< Type > & rTypes, 682 FactoryImpl * pFactory ) 683 SAL_THROW( (RuntimeException) ) 684 : m_nRef( 1 ), 685 m_pFactory( pFactory ), 686 m_key( key ) 687 { 688 // init adapters 689 m_nInterfaces = rTypes.getLength(); 690 m_pInterfaces = new InterfaceAdapterImpl[ rTypes.getLength() ]; 691 const Type * pTypes = rTypes.getConstArray(); 692 for ( sal_Int32 nPos = rTypes.getLength(); nPos--; ) 693 { 694 InterfaceAdapterImpl * pInterface = &m_pInterfaces[nPos]; 695 pInterface->acquire = adapter_acquire; 696 pInterface->release = adapter_release; 697 pInterface->pDispatcher = adapter_dispatch; 698 pInterface->m_pAdapter = this; 699 pInterface->m_pTypeDescr = 0; 700 pTypes[nPos].getDescription( 701 (typelib_TypeDescription **)&pInterface->m_pTypeDescr ); 702 OSL_ASSERT( pInterface->m_pTypeDescr ); 703 if (! pInterface->m_pTypeDescr) 704 { 705 for ( sal_Int32 n = 0; n < nPos; ++n ) 706 { 707 ::typelib_typedescription_release( 708 (typelib_TypeDescription *) 709 m_pInterfaces[ n ].m_pTypeDescr ); 710 } 711 delete [] m_pInterfaces; 712 throw RuntimeException( 713 OUSTR("cannot retrieve all interface type infos!"), 714 Reference< XInterface >() ); 715 } 716 } 717 718 // map receiver 719 m_pReceiver = (uno_Interface *)m_pFactory->m_aCpp2Uno.mapInterface( 720 xReceiver.get(), ::getCppuType( &xReceiver ) ); 721 OSL_ASSERT( 0 != m_pReceiver ); 722 if (! m_pReceiver) 723 { 724 throw RuntimeException( 725 OUSTR("cannot map receiver!"), Reference< XInterface >() ); 726 } 727 728 m_pFactory->acquire(); 729 } 730 731 //______________________________________________________________________________ 732 FactoryImpl::FactoryImpl( Reference< XComponentContext > const & xContext ) 733 SAL_THROW( (RuntimeException) ) 734 : m_pInvokMethodTD( 0 ), 735 m_pSetValueTD( 0 ), 736 m_pGetValueTD( 0 ), 737 m_pAnySeqTD( 0 ), 738 m_pShortSeqTD( 0 ), 739 m_pConvertToTD( 0 ) 740 { 741 // C++/UNO bridge 742 OUString aCppEnvTypeName = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME); 743 OUString aUnoEnvTypeName = OUSTR(UNO_LB_UNO); 744 m_aUno2Cpp = Mapping( aUnoEnvTypeName, aCppEnvTypeName ); 745 m_aCpp2Uno = Mapping( aCppEnvTypeName, aUnoEnvTypeName ); 746 OSL_ENSURE( 747 m_aUno2Cpp.is() && m_aCpp2Uno.is(), "### no uno / C++ mappings!" ); 748 749 // type converter 750 Reference< script::XTypeConverter > xConverter( 751 xContext->getServiceManager()->createInstanceWithContext( 752 OUString( 753 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter") ), 754 xContext ), 755 UNO_QUERY_THROW ); 756 m_pConverter = (uno_Interface *)m_aCpp2Uno.mapInterface( 757 xConverter.get(), ::getCppuType( &xConverter ) ); 758 OSL_ASSERT( 0 != m_pConverter ); 759 760 // some type info: 761 // sequence< any > 762 Type const & rAnySeqType = ::getCppuType( (const Sequence< Any > *)0 ); 763 rAnySeqType.getDescription( &m_pAnySeqTD ); 764 // sequence< short > 765 const Type & rShortSeqType = 766 ::getCppuType( (const Sequence< sal_Int16 > *)0 ); 767 rShortSeqType.getDescription( &m_pShortSeqTD ); 768 // script.XInvocation 769 typelib_TypeDescription * pTD = 0; 770 const Type & rInvType = ::getCppuType( 771 (const Reference< script::XInvocation > *)0 ); 772 TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() ); 773 typelib_InterfaceTypeDescription * pITD; 774 pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD); 775 if( ! pITD->aBase.bComplete ) 776 typelib_typedescription_complete( &pTD ); 777 ::typelib_typedescriptionreference_getDescription( 778 &m_pInvokMethodTD, pITD->ppMembers[ 1 ] ); // invoke() 779 ::typelib_typedescriptionreference_getDescription( 780 &m_pSetValueTD, pITD->ppMembers[ 2 ] ); // setValue() 781 ::typelib_typedescriptionreference_getDescription( 782 &m_pGetValueTD, pITD->ppMembers[ 3 ] ); // getValue() 783 // script.XTypeConverter 784 const Type & rTCType = 785 ::getCppuType( (const Reference< script::XTypeConverter > *)0 ); 786 TYPELIB_DANGER_GET( &pTD, rTCType.getTypeLibType() ); 787 pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD); 788 ::typelib_typedescriptionreference_getDescription( 789 &m_pConvertToTD, pITD->ppMembers[ 0 ] ); // convertTo() 790 TYPELIB_DANGER_RELEASE( pTD ); 791 792 if (!m_pInvokMethodTD || !m_pSetValueTD || !m_pGetValueTD || 793 !m_pConvertToTD || 794 !m_pAnySeqTD || !m_pShortSeqTD) 795 { 796 throw RuntimeException( 797 OUSTR("missing type descriptions!"), Reference< XInterface >() ); 798 } 799 800 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 801 } 802 //______________________________________________________________________________ 803 FactoryImpl::~FactoryImpl() SAL_THROW( () ) 804 { 805 ::typelib_typedescription_release( m_pInvokMethodTD ); 806 ::typelib_typedescription_release( m_pSetValueTD ); 807 ::typelib_typedescription_release( m_pGetValueTD ); 808 ::typelib_typedescription_release( m_pAnySeqTD ); 809 ::typelib_typedescription_release( m_pShortSeqTD ); 810 ::typelib_typedescription_release( m_pConvertToTD ); 811 812 (*m_pConverter->release)( m_pConverter ); 813 814 #if OSL_DEBUG_LEVEL > 1 815 OSL_ENSURE( m_receiver2adapters.empty(), "### still adapters out there!?" ); 816 #endif 817 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 818 } 819 820 //------------------------------------------------------------------------------ 821 static inline AdapterImpl * lookup_adapter( 822 t_ptr_set ** pp_adapter_set, 823 t_ptr_map & map, void * key, Sequence< Type > const & rTypes ) 824 SAL_THROW( () ) 825 { 826 t_ptr_set & adapters_set = map[ key ]; 827 *pp_adapter_set = &adapters_set; 828 if (adapters_set.empty()) 829 return 0; // shortcut 830 // find matching adapter 831 Type const * pTypes = rTypes.getConstArray(); 832 sal_Int32 nTypes = rTypes.getLength(); 833 t_ptr_set::const_iterator iPos( adapters_set.begin() ); 834 t_ptr_set::const_iterator const iEnd( adapters_set.end() ); 835 while (iEnd != iPos) 836 { 837 AdapterImpl * that = reinterpret_cast< AdapterImpl * >( *iPos ); 838 // iterate thru all types if that is a matching adapter 839 sal_Int32 nPosTypes; 840 for ( nPosTypes = nTypes; nPosTypes--; ) 841 { 842 Type const & rType = pTypes[ nPosTypes ]; 843 // find in adapter's type list 844 sal_Int32 nPos; 845 for ( nPos = that->m_nInterfaces; nPos--; ) 846 { 847 if (::typelib_typedescriptionreference_isAssignableFrom( 848 rType.getTypeLibType(), 849 ((typelib_TypeDescription *)that-> 850 m_pInterfaces[ nPos ].m_pTypeDescr)->pWeakRef )) 851 { 852 // found 853 break; 854 } 855 } 856 if (nPos < 0) // type not found => next adapter 857 break; 858 } 859 if (nPosTypes < 0) // all types found 860 return that; 861 ++iPos; 862 } 863 return 0; 864 } 865 866 // XInvocationAdapterFactory2 impl 867 //______________________________________________________________________________ 868 Reference< XInterface > FactoryImpl::createAdapter( 869 const Reference< script::XInvocation > & xReceiver, 870 const Sequence< Type > & rTypes ) 871 throw (RuntimeException) 872 { 873 Reference< XInterface > xRet; 874 if (xReceiver.is() && rTypes.getLength()) 875 { 876 t_ptr_set * adapter_set; 877 AdapterImpl * that; 878 Reference< XInterface > xKey( xReceiver, UNO_QUERY ); 879 { 880 ClearableMutexGuard guard( m_mutex ); 881 that = lookup_adapter( 882 &adapter_set, m_receiver2adapters, xKey.get(), rTypes ); 883 if (0 == that) // no entry 884 { 885 guard.clear(); 886 // create adapter; already acquired: m_nRef == 1 887 AdapterImpl * pNew = 888 new AdapterImpl( xKey.get(), xReceiver, rTypes, this ); 889 // lookup again 890 ClearableMutexGuard guard2( m_mutex ); 891 that = lookup_adapter( 892 &adapter_set, m_receiver2adapters, xKey.get(), rTypes ); 893 if (0 == that) // again no entry 894 { 895 pair< t_ptr_set::iterator, bool > insertion( 896 adapter_set->insert( pNew ) ); 897 OSL_ASSERT( insertion.second ); 898 that = pNew; 899 } 900 else 901 { 902 that->acquire(); 903 guard2.clear(); 904 delete pNew; // has never been inserted 905 } 906 } 907 else // found adapter 908 { 909 that->acquire(); 910 } 911 } 912 // map one interface to C++ 913 uno_Interface * pUnoI = &that->m_pInterfaces[ 0 ]; 914 m_aUno2Cpp.mapInterface( 915 (void **)&xRet, pUnoI, ::getCppuType( &xRet ) ); 916 that->release(); 917 OSL_ASSERT( xRet.is() ); 918 if (! xRet.is()) 919 { 920 throw RuntimeException( 921 OUSTR("mapping UNO to C++ failed!"), 922 Reference< XInterface >() ); 923 } 924 } 925 return xRet; 926 } 927 // XInvocationAdapterFactory impl 928 //______________________________________________________________________________ 929 Reference< XInterface > FactoryImpl::createAdapter( 930 const Reference< script::XInvocation > & xReceiver, const Type & rType ) 931 throw (RuntimeException) 932 { 933 return createAdapter( xReceiver, Sequence< Type >( &rType, 1 ) ); 934 } 935 936 // XServiceInfo 937 //______________________________________________________________________________ 938 OUString FactoryImpl::getImplementationName() 939 throw (RuntimeException) 940 { 941 return invadp_getImplementationName(); 942 } 943 //______________________________________________________________________________ 944 sal_Bool FactoryImpl::supportsService( const OUString & rServiceName ) 945 throw (RuntimeException) 946 { 947 const Sequence< OUString > & rSNL = getSupportedServiceNames(); 948 const OUString * pArray = rSNL.getConstArray(); 949 for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) 950 { 951 if (pArray[nPos].equals( rServiceName )) 952 return sal_True; 953 } 954 return sal_False; 955 } 956 //______________________________________________________________________________ 957 Sequence< OUString > FactoryImpl::getSupportedServiceNames() 958 throw (RuntimeException) 959 { 960 return invadp_getSupportedServiceNames(); 961 } 962 963 //============================================================================== 964 static Reference< XInterface > SAL_CALL FactoryImpl_create( 965 const Reference< XComponentContext > & xContext ) 966 throw (Exception) 967 { 968 Reference< XInterface > rRet; 969 { 970 MutexGuard guard( Mutex::getGlobalMutex() ); 971 static WeakReference < XInterface > rwInstance; 972 rRet = rwInstance; 973 974 if( ! rRet.is() ) 975 { 976 rRet = (::cppu::OWeakObject *)new FactoryImpl( xContext ); 977 rwInstance = rRet; 978 } 979 } 980 return rRet; 981 } 982 983 } 984 985 986 //############################################################################## 987 //############################################################################## 988 //############################################################################## 989 990 static struct ::cppu::ImplementationEntry g_entries[] = 991 { 992 { 993 ::stoc_invadp::FactoryImpl_create, 994 ::stoc_invadp::invadp_getImplementationName, 995 ::stoc_invadp::invadp_getSupportedServiceNames, 996 ::cppu::createSingleComponentFactory, 997 &::stoc_invadp::g_moduleCount.modCnt , 0 998 }, 999 { 0, 0, 0, 0, 0, 0 } 1000 }; 1001 1002 extern "C" 1003 { 1004 sal_Bool SAL_CALL component_canUnload( 1005 TimeValue *pTime ) 1006 { 1007 return ::stoc_invadp::g_moduleCount.canUnload( 1008 &::stoc_invadp::g_moduleCount, pTime ); 1009 } 1010 1011 //============================================================================== 1012 void SAL_CALL component_getImplementationEnvironment( 1013 const sal_Char ** ppEnvTypeName, uno_Environment ** ) 1014 { 1015 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 1016 } 1017 1018 //============================================================================== 1019 void * SAL_CALL component_getFactory( 1020 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) 1021 { 1022 return ::cppu::component_getFactoryHelper( 1023 pImplName, pServiceManager, pRegistryKey , g_entries ); 1024 } 1025 } 1026