nss: upgrade to release 3.73
[LibreOffice.git] / stoc / source / invocation_adapterfactory / iafactory.cxx
blob126af1f828515131485cd41befb8f848431deacb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <osl/diagnose.h>
22 #include <osl/interlck.h>
23 #include <osl/mutex.hxx>
24 #include <o3tl/sorted_vector.hxx>
25 #include <sal/log.hxx>
27 #include <uno/dispatcher.h>
28 #include <uno/data.h>
29 #include <uno/any2.h>
30 #include <uno/lbnames.h>
31 #include <uno/mapping.hxx>
33 #include <cppuhelper/implbase.hxx>
34 #include <cppuhelper/supportsservice.hxx>
35 #include <cppuhelper/weak.hxx>
36 #include <com/sun/star/script/XTypeConverter.hpp>
37 #include <com/sun/star/script/XInvocationAdapterFactory.hpp>
38 #include <com/sun/star/script/XInvocationAdapterFactory2.hpp>
39 #include <com/sun/star/script/XInvocation.hpp>
40 #include <com/sun/star/lang/XServiceInfo.hpp>
41 #include <com/sun/star/reflection/InvocationTargetException.hpp>
42 #include <com/sun/star/uno/RuntimeException.hpp>
43 #include <com/sun/star/uno/XComponentContext.hpp>
45 #include <unordered_map>
46 #include <unordered_set>
47 #include <vector>
49 using namespace ::std;
50 using namespace ::osl;
51 using namespace ::com::sun::star;
52 using namespace css::uno;
54 namespace stoc_invadp
58 namespace {
60 struct hash_ptr
62 size_t operator() ( void * p ) const
63 { return reinterpret_cast<size_t>(p); }
68 typedef o3tl::sorted_vector< void * > t_ptr_set;
69 typedef std::unordered_map< void *, t_ptr_set, hash_ptr > t_ptr_map;
71 namespace {
73 class FactoryImpl
74 : public ::cppu::WeakImplHelper< lang::XServiceInfo,
75 script::XInvocationAdapterFactory,
76 script::XInvocationAdapterFactory2 >
78 public:
79 Mapping m_aUno2Cpp;
80 Mapping m_aCpp2Uno;
81 uno_Interface * m_pConverter;
83 typelib_TypeDescription * m_pInvokMethodTD;
84 typelib_TypeDescription * m_pSetValueTD;
85 typelib_TypeDescription * m_pGetValueTD;
86 typelib_TypeDescription * m_pAnySeqTD;
87 typelib_TypeDescription * m_pShortSeqTD;
88 typelib_TypeDescription * m_pConvertToTD;
90 Mutex m_mutex;
91 t_ptr_map m_receiver2adapters;
93 explicit FactoryImpl( Reference< XComponentContext > const & xContext );
94 virtual ~FactoryImpl() override;
96 // XServiceInfo
97 virtual OUString SAL_CALL getImplementationName() override;
98 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) override;
99 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
101 // XInvocationAdapterFactory
102 virtual Reference< XInterface > SAL_CALL createAdapter(
103 const Reference< script::XInvocation > & xReceiver, const Type & rType ) override;
104 // XInvocationAdapterFactory2
105 virtual Reference< XInterface > SAL_CALL createAdapter(
106 const Reference< script::XInvocation > & xReceiver,
107 const Sequence< Type > & rTypes ) override;
109 struct AdapterImpl;
111 struct InterfaceAdapterImpl : public uno_Interface
113 AdapterImpl * m_pAdapter;
114 typelib_InterfaceTypeDescription * m_pTypeDescr;
117 struct AdapterImpl
119 oslInterlockedCount m_nRef;
120 FactoryImpl * m_pFactory;
121 void * m_key; // map key
122 uno_Interface * m_pReceiver; // XInvocation receiver
124 std::vector<InterfaceAdapterImpl> m_vInterfaces;
126 // XInvocation calls
127 void getValue(
128 const typelib_TypeDescription * pMemberType,
129 void * pReturn, uno_Any ** ppException );
130 void setValue(
131 const typelib_TypeDescription * pMemberType,
132 void * pArgs[], uno_Any ** ppException );
133 void invoke(
134 const typelib_TypeDescription * pMemberType,
135 void * pReturn, void * pArgs[], uno_Any ** ppException );
137 bool coerce_assign(
138 void * pDest, typelib_TypeDescriptionReference * pType,
139 uno_Any * pSource, uno_Any * pExc );
140 inline bool coerce_construct(
141 void * pDest, typelib_TypeDescriptionReference * pType,
142 uno_Any * pSource, uno_Any * pExc );
144 inline void acquire();
145 inline void release();
146 inline ~AdapterImpl();
147 inline AdapterImpl(
148 void * key, Reference< script::XInvocation > const & xReceiver,
149 const Sequence< Type > & rTypes,
150 FactoryImpl * pFactory );
152 // Copy assignment is forbidden and not implemented.
153 AdapterImpl (const AdapterImpl &) = delete;
154 AdapterImpl & operator= (const AdapterImpl &) = delete;
159 inline AdapterImpl::~AdapterImpl()
161 for ( size_t nPos = m_vInterfaces.size(); nPos--; )
163 ::typelib_typedescription_release(
164 &m_vInterfaces[ nPos ].m_pTypeDescr->aBase );
167 (*m_pReceiver->release)( m_pReceiver );
168 m_pFactory->release();
171 inline void AdapterImpl::acquire()
173 osl_atomic_increment( &m_nRef );
176 inline void AdapterImpl::release()
178 bool delete_this = false;
180 MutexGuard guard( m_pFactory->m_mutex );
181 if (! osl_atomic_decrement( &m_nRef ))
183 t_ptr_map::iterator iFind(
184 m_pFactory->m_receiver2adapters.find( m_key ) );
185 OSL_ASSERT( m_pFactory->m_receiver2adapters.end() != iFind );
186 t_ptr_set & adapter_set = iFind->second;
187 if (adapter_set.erase( this ) != 1) {
188 OSL_ASSERT( false );
190 if (adapter_set.empty())
192 m_pFactory->m_receiver2adapters.erase( iFind );
194 delete_this = true;
197 if (delete_this)
198 delete this;
202 static void constructRuntimeException(
203 uno_Any * pExc, const OUString & rMsg )
205 RuntimeException exc( rMsg );
206 // no conversion needed due to binary compatibility + no convertible type
207 ::uno_type_any_construct(
208 pExc, &exc, cppu::UnoType<decltype(exc)>::get().getTypeLibType(), nullptr );
212 static bool type_equals(
213 typelib_TypeDescriptionReference * pType1,
214 typelib_TypeDescriptionReference * pType2 )
216 return (pType1 == pType2 ||
217 (pType1->pTypeName->length == pType2->pTypeName->length &&
218 0 == ::rtl_ustr_compare(
219 pType1->pTypeName->buffer, pType2->pTypeName->buffer )));
223 bool AdapterImpl::coerce_assign(
224 void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
225 uno_Any * pOutExc )
227 if (typelib_TypeClass_ANY == pType->eTypeClass)
229 ::uno_type_any_assign(
230 static_cast<uno_Any *>(pDest), pSource->pData, pSource->pType, nullptr, nullptr );
231 return true;
233 if (::uno_type_assignData(
234 pDest, pType, pSource->pData, pSource->pType, nullptr, nullptr, nullptr ))
236 return true;
238 else // try type converter
240 uno_Any ret;
241 void * args[ 2 ];
242 args[ 0 ] = pSource;
243 args[ 1 ] = &pType;
244 uno_Any exc;
245 uno_Any * p_exc = &exc;
247 // converTo()
248 (*m_pFactory->m_pConverter->pDispatcher)(
249 m_pFactory->m_pConverter,
250 m_pFactory->m_pConvertToTD, &ret, args, &p_exc );
252 if (p_exc) // exception occurred
254 OSL_ASSERT(
255 p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
256 if (typelib_typedescriptionreference_isAssignableFrom( cppu::UnoType<RuntimeException>::get().getTypeLibType(),
257 p_exc->pType ))
259 // is RuntimeException or derived: rethrow
260 uno_type_any_construct(
261 pOutExc, p_exc->pData, p_exc->pType, nullptr );
263 else
265 // set runtime exception
266 constructRuntimeException(
267 pOutExc, "type coercion failed: " +
268 static_cast< Exception const * >(
269 p_exc->pData )->Message );
271 ::uno_any_destruct( p_exc, nullptr );
272 // pOutExc constructed
273 return false;
275 else
277 bool succ = ::uno_type_assignData(
278 pDest, pType, ret.pData, ret.pType, nullptr, nullptr, nullptr );
279 ::uno_any_destruct( &ret, nullptr );
280 OSL_ENSURE(
281 succ, "### conversion succeeded, but assignment failed!?" );
282 if (! succ)
284 // set runtime exception
285 constructRuntimeException(
286 pOutExc,
287 "type coercion failed: "
288 "conversion succeeded, but assignment failed?!" );
290 return succ;
295 inline bool AdapterImpl::coerce_construct(
296 void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
297 uno_Any * pExc )
299 if (typelib_TypeClass_ANY == pType->eTypeClass)
301 ::uno_type_copyData( pDest, pSource, pType, nullptr );
302 return true;
304 if (type_equals( pType, pSource->pType))
306 ::uno_type_copyData( pDest, pSource->pData, pType, nullptr );
307 return true;
309 ::uno_type_constructData( pDest, pType );
310 return coerce_assign( pDest, pType, pSource, pExc );
314 static void handleInvokExc( uno_Any * pDest, uno_Any * pSource )
316 OUString const & name =
317 OUString::unacquired( &pSource->pType->pTypeName );
319 if ( name == "com.sun.star.reflection.InvocationTargetException" )
321 // unwrap invocation target exception
322 uno_Any * target_exc =
323 &static_cast< reflection::InvocationTargetException * >(
324 pSource->pData )->TargetException;
325 ::uno_type_any_construct(
326 pDest, target_exc->pData, target_exc->pType, nullptr );
328 else // all other exceptions are wrapped to RuntimeException
330 if (typelib_TypeClass_EXCEPTION == pSource->pType->eTypeClass)
332 constructRuntimeException(
333 pDest, static_cast<Exception const *>(pSource->pData)->Message );
335 else
337 constructRuntimeException(
338 pDest, "no exception has been thrown via invocation?!" );
343 void AdapterImpl::getValue(
344 const typelib_TypeDescription * pMemberType,
345 void * pReturn, uno_Any ** ppException )
347 uno_Any aInvokRet;
348 void * pInvokArgs[1];
349 pInvokArgs[0] = const_cast<rtl_uString **>(
350 &reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->pMemberName);
351 uno_Any aInvokExc;
352 uno_Any * pInvokExc = &aInvokExc;
354 // getValue()
355 (*m_pReceiver->pDispatcher)(
356 m_pReceiver, m_pFactory->m_pGetValueTD,
357 &aInvokRet, pInvokArgs, &pInvokExc );
359 if (pInvokExc) // getValue() call exception
361 handleInvokExc( *ppException, pInvokExc );
362 ::uno_any_destruct( pInvokExc, nullptr ); // cleanup
364 else // invocation call succeeded
366 if (coerce_construct(
367 pReturn,
368 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
369 pMemberType)->pAttributeTypeRef,
370 &aInvokRet, *ppException ))
372 *ppException = nullptr; // no exceptions be thrown
374 ::uno_any_destruct( &aInvokRet, nullptr );
378 void AdapterImpl::setValue(
379 const typelib_TypeDescription * pMemberType,
380 void * pArgs[], uno_Any ** ppException )
382 uno_Any aInvokVal;
383 ::uno_type_any_construct(
384 &aInvokVal, pArgs[0],
385 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
386 pMemberType)->pAttributeTypeRef, nullptr );
388 void * pInvokArgs[2];
389 pInvokArgs[0] = const_cast<rtl_uString **>(
390 &reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->pMemberName);
391 pInvokArgs[1] = &aInvokVal;
392 uno_Any aInvokExc;
393 uno_Any * pInvokExc = &aInvokExc;
395 // setValue()
396 (*m_pReceiver->pDispatcher)(
397 m_pReceiver, m_pFactory->m_pSetValueTD, nullptr, pInvokArgs, &pInvokExc );
399 if (pInvokExc) // setValue() call exception
401 handleInvokExc( *ppException, pInvokExc );
402 ::uno_any_destruct( pInvokExc, nullptr ); // cleanup
404 else // invocation call succeeded
406 *ppException = nullptr; // no exceptions be thrown
409 ::uno_any_destruct( &aInvokVal, nullptr ); // cleanup
412 void AdapterImpl::invoke(
413 const typelib_TypeDescription * pMemberType,
414 void * pReturn, void * pArgs[], uno_Any ** ppException )
416 sal_Int32 nParams =
417 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType)->nParams;
418 typelib_MethodParameter * pFormalParams =
419 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType)->pParams;
421 // in params
422 uno_Sequence * pInParamsSeq = nullptr;
423 ::uno_sequence_construct(
424 &pInParamsSeq, m_pFactory->m_pAnySeqTD, nullptr, nParams, nullptr );
425 uno_Any * pInAnys = reinterpret_cast<uno_Any *>(pInParamsSeq->elements);
426 sal_Int32 nOutParams = 0;
427 sal_Int32 nPos;
428 for ( nPos = nParams; nPos--; )
430 typelib_MethodParameter const & rParam = pFormalParams[nPos];
431 if (rParam.bIn) // is in/inout param
433 ::uno_type_any_assign(
434 &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef, nullptr, nullptr );
436 // else: pure out is empty any
438 if (rParam.bOut)
439 ++nOutParams;
442 // out params, out indices
443 uno_Sequence * pOutIndices;
444 uno_Sequence * pOutParams;
445 // return value
446 uno_Any aInvokRet;
447 // perform call
448 void * pInvokArgs[4];
449 pInvokArgs[0] = const_cast<rtl_uString **>(
450 &reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->pMemberName);
451 pInvokArgs[1] = &pInParamsSeq;
452 pInvokArgs[2] = &pOutIndices;
453 pInvokArgs[3] = &pOutParams;
454 uno_Any aInvokExc;
455 uno_Any * pInvokExc = &aInvokExc;
457 // invoke() call
458 (*m_pReceiver->pDispatcher)(
459 m_pReceiver, m_pFactory->m_pInvokMethodTD,
460 &aInvokRet, pInvokArgs, &pInvokExc );
462 if (pInvokExc)
464 handleInvokExc( *ppException, pInvokExc );
465 ::uno_any_destruct( pInvokExc, nullptr ); // cleanup
467 else // no invocation exception
469 // write changed out params
470 OSL_ENSURE(
471 pOutParams->nElements == nOutParams &&
472 pOutIndices->nElements == nOutParams,
473 "### out params lens differ!" );
474 if (pOutParams->nElements == nOutParams &&
475 pOutIndices->nElements == nOutParams)
477 sal_Int16 * pIndices = reinterpret_cast<sal_Int16 *>(pOutIndices->elements);
478 uno_Any * pOut = reinterpret_cast<uno_Any *>(pOutParams->elements);
479 for ( nPos = 0; nPos < nOutParams; ++nPos )
481 sal_Int32 nIndex = pIndices[nPos];
482 OSL_ENSURE( nIndex < nParams, "### illegal index!" );
483 typelib_MethodParameter const & rParam = pFormalParams[nIndex];
484 bool succ;
485 if (rParam.bIn) // is in/inout param
487 succ = coerce_assign(
488 pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
489 *ppException );
491 else // pure out
493 succ = coerce_construct(
494 pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
495 *ppException );
497 if (! succ) // cleanup of out params
499 for ( sal_Int32 n = 0; n <= nPos; ++n )
501 sal_Int32 nIndex2 = pIndices[n];
502 OSL_ENSURE( nIndex2 < nParams, "### illegal index!" );
503 typelib_MethodParameter const & rParam2 =
504 pFormalParams[nIndex2];
505 if (! rParam2.bIn) // is pure out param
507 ::uno_type_destructData(
508 pArgs[nIndex2], rParam2.pTypeRef, nullptr );
513 if (nPos == pOutIndices->nElements)
515 // out param copy ok; write return value
516 if (coerce_construct(
517 pReturn,
518 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(
519 pMemberType)->pReturnTypeRef,
520 &aInvokRet, *ppException ))
522 *ppException = nullptr; // no exception
526 else
528 // set runtime exception
529 constructRuntimeException(
530 *ppException,
531 "out params lengths differ after invocation call!" );
533 // cleanup invok out params
534 ::uno_destructData( &pOutIndices, m_pFactory->m_pShortSeqTD, nullptr );
535 ::uno_destructData( &pOutParams, m_pFactory->m_pAnySeqTD, nullptr );
536 // cleanup invok return value
537 ::uno_any_destruct( &aInvokRet, nullptr );
539 // cleanup constructed in params
540 ::uno_destructData( &pInParamsSeq, m_pFactory->m_pAnySeqTD, nullptr );
543 extern "C"
546 static void adapter_acquire( uno_Interface * pUnoI )
548 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire();
551 static void adapter_release( uno_Interface * pUnoI )
553 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release();
556 static void adapter_dispatch(
557 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType,
558 void * pReturn, void * pArgs[], uno_Any ** ppException )
560 // query to emulated interface
561 switch (reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->nPosition)
563 case 0: // queryInterface()
565 AdapterImpl * that =
566 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
567 *ppException = nullptr; // no exc
568 typelib_TypeDescriptionReference * pDemanded =
569 *static_cast<typelib_TypeDescriptionReference **>(pArgs[0]);
570 // pInterfaces[0] is XInterface
571 for ( size_t nPos = 0; nPos < that->m_vInterfaces.size(); ++nPos )
573 typelib_InterfaceTypeDescription * pTD =
574 that->m_vInterfaces[nPos].m_pTypeDescr;
575 while (pTD)
577 if (type_equals( pTD->aBase.pWeakRef, pDemanded ))
579 uno_Interface * pUnoI2 = &that->m_vInterfaces[nPos];
580 ::uno_any_construct(
581 static_cast<uno_Any *>(pReturn), &pUnoI2,
582 &pTD->aBase, nullptr );
583 return;
585 pTD = pTD->pBaseTypeDescription;
588 ::uno_any_construct( static_cast<uno_Any *>(pReturn), nullptr, nullptr, nullptr ); // clear()
589 break;
591 case 1: // acquire()
592 *ppException = nullptr; // no exc
593 adapter_acquire( pUnoI );
594 break;
595 case 2: // release()
596 *ppException = nullptr; // no exc
597 adapter_release( pUnoI );
598 break;
600 default:
602 AdapterImpl * that =
603 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
604 if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
606 that->invoke( pMemberType, pReturn, pArgs, ppException );
608 else // attribute
610 if (pReturn)
611 that->getValue( pMemberType, pReturn, ppException );
612 else
613 that->setValue( pMemberType, pArgs, ppException );
620 AdapterImpl::AdapterImpl(
621 void * key, Reference< script::XInvocation > const & xReceiver,
622 const Sequence< Type > & rTypes,
623 FactoryImpl * pFactory )
624 : m_nRef( 1 ),
625 m_pFactory( pFactory ),
626 m_key( key ),
627 m_vInterfaces( rTypes.getLength() )
629 // init adapters
630 const Type * pTypes = rTypes.getConstArray();
631 for ( sal_Int32 nPos = rTypes.getLength(); nPos--; )
633 InterfaceAdapterImpl * pInterface = &m_vInterfaces[nPos];
634 pInterface->acquire = adapter_acquire;
635 pInterface->release = adapter_release;
636 pInterface->pDispatcher = adapter_dispatch;
637 pInterface->m_pAdapter = this;
638 pInterface->m_pTypeDescr = nullptr;
639 pTypes[nPos].getDescription(
640 reinterpret_cast<typelib_TypeDescription **>(&pInterface->m_pTypeDescr) );
641 OSL_ASSERT( pInterface->m_pTypeDescr );
642 if (! pInterface->m_pTypeDescr)
644 for ( sal_Int32 n = 0; n < nPos; ++n )
646 ::typelib_typedescription_release(
647 &m_vInterfaces[ n ].m_pTypeDescr->aBase );
649 throw RuntimeException(
650 "cannot retrieve all interface type infos!" );
654 // map receiver
655 m_pReceiver = static_cast<uno_Interface *>(m_pFactory->m_aCpp2Uno.mapInterface(
656 xReceiver.get(), cppu::UnoType<decltype(xReceiver)>::get() ));
657 OSL_ASSERT( nullptr != m_pReceiver );
658 if (! m_pReceiver)
660 throw RuntimeException( "cannot map receiver!" );
663 m_pFactory->acquire();
667 FactoryImpl::FactoryImpl( Reference< XComponentContext > const & xContext )
668 : m_aUno2Cpp(Mapping( UNO_LB_UNO, CPPU_CURRENT_LANGUAGE_BINDING_NAME )),
669 m_aCpp2Uno(Mapping( CPPU_CURRENT_LANGUAGE_BINDING_NAME, UNO_LB_UNO)),
670 m_pInvokMethodTD( nullptr ),
671 m_pSetValueTD( nullptr ),
672 m_pGetValueTD( nullptr ),
673 m_pAnySeqTD( nullptr ),
674 m_pShortSeqTD( nullptr ),
675 m_pConvertToTD( nullptr )
677 // C++/UNO bridge
678 OSL_ENSURE(
679 m_aUno2Cpp.is() && m_aCpp2Uno.is(), "### no uno / C++ mappings!" );
681 // type converter
682 Reference< script::XTypeConverter > xConverter(
683 xContext->getServiceManager()->createInstanceWithContext(
684 "com.sun.star.script.Converter",
685 xContext ),
686 UNO_QUERY_THROW );
687 m_pConverter = static_cast<uno_Interface *>(m_aCpp2Uno.mapInterface(
688 xConverter.get(), cppu::UnoType<decltype(xConverter)>::get() ));
689 OSL_ASSERT( nullptr != m_pConverter );
691 // some type info:
692 // sequence< any >
693 Type const & rAnySeqType = cppu::UnoType<Sequence< Any >>::get();
694 rAnySeqType.getDescription( &m_pAnySeqTD );
695 // sequence< short >
696 const Type & rShortSeqType =
697 cppu::UnoType<Sequence< sal_Int16 >>::get();
698 rShortSeqType.getDescription( &m_pShortSeqTD );
699 // script.XInvocation
700 typelib_TypeDescription * pTD = nullptr;
701 const Type & rInvType = cppu::UnoType<script::XInvocation>::get();
702 TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() );
703 typelib_InterfaceTypeDescription * pITD;
704 pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
705 if( ! pITD->aBase.bComplete )
706 typelib_typedescription_complete( &pTD );
707 ::typelib_typedescriptionreference_getDescription(
708 &m_pInvokMethodTD, pITD->ppMembers[ 1 ] ); // invoke()
709 ::typelib_typedescriptionreference_getDescription(
710 &m_pSetValueTD, pITD->ppMembers[ 2 ] ); // setValue()
711 ::typelib_typedescriptionreference_getDescription(
712 &m_pGetValueTD, pITD->ppMembers[ 3 ] ); // getValue()
713 // script.XTypeConverter
714 const Type & rTCType =
715 cppu::UnoType<script::XTypeConverter>::get();
716 TYPELIB_DANGER_GET( &pTD, rTCType.getTypeLibType() );
717 pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
718 ::typelib_typedescriptionreference_getDescription(
719 &m_pConvertToTD, pITD->ppMembers[ 0 ] ); // convertTo()
720 TYPELIB_DANGER_RELEASE( pTD );
722 if (!m_pInvokMethodTD || !m_pSetValueTD || !m_pGetValueTD ||
723 !m_pConvertToTD ||
724 !m_pAnySeqTD || !m_pShortSeqTD)
726 throw RuntimeException( "missing type descriptions!" );
730 FactoryImpl::~FactoryImpl()
732 ::typelib_typedescription_release( m_pInvokMethodTD );
733 ::typelib_typedescription_release( m_pSetValueTD );
734 ::typelib_typedescription_release( m_pGetValueTD );
735 ::typelib_typedescription_release( m_pAnySeqTD );
736 ::typelib_typedescription_release( m_pShortSeqTD );
737 ::typelib_typedescription_release( m_pConvertToTD );
739 (*m_pConverter->release)( m_pConverter );
741 #if OSL_DEBUG_LEVEL > 0
742 assert(m_receiver2adapters.empty() && "still adapters out there!?");
743 #endif
747 static AdapterImpl * lookup_adapter(
748 t_ptr_set ** pp_adapter_set,
749 t_ptr_map & map, void * key, Sequence< Type > const & rTypes )
751 t_ptr_set & adapters_set = map[ key ];
752 *pp_adapter_set = &adapters_set;
753 if (adapters_set.empty())
754 return nullptr; // shortcut
755 // find matching adapter
756 Type const * pTypes = rTypes.getConstArray();
757 sal_Int32 nTypes = rTypes.getLength();
758 for (const auto& rpAdapter : adapters_set)
760 AdapterImpl * that = static_cast< AdapterImpl * >( rpAdapter );
761 // iterate through all types if that is a matching adapter
762 sal_Int32 nPosTypes;
763 for ( nPosTypes = nTypes; nPosTypes--; )
765 Type const & rType = pTypes[ nPosTypes ];
766 // find in adapter's type list
767 sal_Int32 nPos;
768 for ( nPos = that->m_vInterfaces.size(); nPos--; )
770 if (::typelib_typedescriptionreference_isAssignableFrom(
771 rType.getTypeLibType(),
772 that->m_vInterfaces[ nPos ].m_pTypeDescr->aBase.pWeakRef ))
774 // found
775 break;
778 if (nPos < 0) // type not found => next adapter
779 break;
781 if (nPosTypes < 0) // all types found
782 return that;
784 return nullptr;
787 // XInvocationAdapterFactory2 impl
789 Reference< XInterface > FactoryImpl::createAdapter(
790 const Reference< script::XInvocation > & xReceiver,
791 const Sequence< Type > & rTypes )
793 Reference< XInterface > xRet;
794 if (xReceiver.is() && rTypes.hasElements())
796 t_ptr_set * adapter_set;
797 AdapterImpl * that;
798 Reference< XInterface > xKey( xReceiver, UNO_QUERY );
800 ClearableMutexGuard guard( m_mutex );
801 that = lookup_adapter(
802 &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
803 if (nullptr == that) // no entry
805 guard.clear();
806 // create adapter; already acquired: m_nRef == 1
807 AdapterImpl * pNew =
808 new AdapterImpl( xKey.get(), xReceiver, rTypes, this );
809 // lookup again
810 ClearableMutexGuard guard2( m_mutex );
811 that = lookup_adapter(
812 &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
813 if (nullptr == that) // again no entry
815 pair< t_ptr_set::const_iterator, bool > i(adapter_set->insert(pNew));
816 SAL_WARN_IF(
817 !i.second, "stoc",
818 "set already contains " << *(i.first) << " != " << pNew);
819 that = pNew;
821 else
823 that->acquire();
824 guard2.clear();
825 delete pNew; // has never been inserted
828 else // found adapter
830 that->acquire();
833 // map one interface to C++
834 uno_Interface * pUnoI = that->m_vInterfaces.data();
835 m_aUno2Cpp.mapInterface(
836 reinterpret_cast<void **>(&xRet), pUnoI, cppu::UnoType<decltype(xRet)>::get() );
837 that->release();
838 OSL_ASSERT( xRet.is() );
839 if (! xRet.is())
841 throw RuntimeException( "mapping UNO to C++ failed!" );
844 return xRet;
846 // XInvocationAdapterFactory impl
848 Reference< XInterface > FactoryImpl::createAdapter(
849 const Reference< script::XInvocation > & xReceiver, const Type & rType )
851 return createAdapter( xReceiver, Sequence< Type >( &rType, 1 ) );
854 // XServiceInfo
856 OUString FactoryImpl::getImplementationName()
858 return "com.sun.star.comp.stoc.InvocationAdapterFactory";
861 sal_Bool FactoryImpl::supportsService( const OUString & rServiceName )
863 return cppu::supportsService(this, rServiceName);
866 Sequence< OUString > FactoryImpl::getSupportedServiceNames()
868 return { "com.sun.star.script.InvocationAdapterFactory" };
874 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
875 stoc_invocation_adapter_get_implementation(
876 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
878 return cppu::acquire(static_cast<cppu::OWeakObject*>(new stoc_invadp::FactoryImpl(context)));
883 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */