21#include <osl/diagnose.h>
22#include <osl/interlck.h>
23#include <osl/mutex.hxx>
27#include <uno/dispatcher.h>
30#include <uno/lbnames.h>
31#include <uno/mapping.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>
50using namespace css::uno;
60 size_t operator() (
void *
p )
const
61 {
return reinterpret_cast<size_t>(
p); }
67typedef std::unordered_map< void *, t_ptr_set, hash_ptr >
t_ptr_map;
72 :
public ::cppu::WeakImplHelper< lang::XServiceInfo,
73 script::XInvocationAdapterFactory,
74 script::XInvocationAdapterFactory2 >
91 explicit FactoryImpl( Reference< XComponentContext >
const & xContext );
92 virtual ~FactoryImpl()
override;
100 virtual Reference< XInterface > SAL_CALL createAdapter(
101 const Reference< script::XInvocation > & xReceiver,
const Type & rType )
override;
103 virtual Reference< XInterface > SAL_CALL createAdapter(
104 const Reference< script::XInvocation > & xReceiver,
105 const Sequence< Type > & rTypes )
override;
109struct InterfaceAdapterImpl :
public uno_Interface
127 void * pReturn,
uno_Any ** ppException );
130 void * pArgs[],
uno_Any ** ppException );
133 void * pReturn,
void * pArgs[],
uno_Any ** ppException );
136 void * pDest, typelib_TypeDescriptionReference * pType,
138 inline bool coerce_construct(
139 void * pDest, typelib_TypeDescriptionReference * pType,
142 inline void acquire();
143 inline void release();
144 inline ~AdapterImpl();
146 void * key, Reference< script::XInvocation >
const & xReceiver,
147 const Sequence< Type > & rTypes,
148 FactoryImpl * pFactory );
151 AdapterImpl (
const AdapterImpl &) =
delete;
152 AdapterImpl & operator= (
const AdapterImpl &) =
delete;
157inline AdapterImpl::~AdapterImpl()
161 ::typelib_typedescription_release(
169inline void AdapterImpl::acquire()
171 osl_atomic_increment( &
m_nRef );
174inline void AdapterImpl::release()
176 bool delete_this =
false;
179 if (! osl_atomic_decrement( &
m_nRef ))
181 t_ptr_map::iterator iFind(
183 OSL_ASSERT(
m_pFactory->m_receiver2adapters.end() != iFind );
185 if (adapter_set.erase(
this ) != 1) {
188 if (adapter_set.empty())
190 m_pFactory->m_receiver2adapters.erase( iFind );
201 uno_Any * pExc,
const OUString & rMsg )
205 ::uno_type_any_construct(
206 pExc, &exc,
cppu::UnoType<
decltype(exc)>::get().getTypeLibType(),
nullptr );
211 typelib_TypeDescriptionReference * pType1,
212 typelib_TypeDescriptionReference * pType2 )
214 return (pType1 == pType2 ||
215 (pType1->pTypeName->length == pType2->pTypeName->length &&
216 0 == ::rtl_ustr_compare(
217 pType1->pTypeName->buffer, pType2->pTypeName->buffer )));
222 void * pDest, typelib_TypeDescriptionReference * pType,
uno_Any * pSource,
225 if (typelib_TypeClass_ANY == pType->eTypeClass)
227 ::uno_type_any_assign(
228 static_cast<uno_Any *
>(pDest), pSource->pData, pSource->pType,
nullptr,
nullptr );
231 if (::uno_type_assignData(
232 pDest, pType, pSource->pData, pSource->pType,
nullptr,
nullptr,
nullptr ))
248 m_pFactory->m_pConvertToTD, &ret, args, &p_exc );
253 p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
259 pOutExc, p_exc->pData, p_exc->pType,
nullptr );
265 pOutExc,
"type coercion failed: " +
267 p_exc->pData )->Message );
269 ::uno_any_destruct( p_exc,
nullptr );
275 bool succ = ::uno_type_assignData(
276 pDest, pType, ret.pData, ret.pType,
nullptr,
nullptr,
nullptr );
277 ::uno_any_destruct( &ret,
nullptr );
279 succ,
"### conversion succeeded, but assignment failed!?" );
285 "type coercion failed: "
286 "conversion succeeded, but assignment failed?!" );
293inline bool AdapterImpl::coerce_construct(
294 void * pDest, typelib_TypeDescriptionReference * pType,
uno_Any * pSource,
297 if (typelib_TypeClass_ANY == pType->eTypeClass)
299 ::uno_type_copyData( pDest, pSource, pType,
nullptr );
304 ::uno_type_copyData( pDest, pSource->pData, pType,
nullptr );
307 ::uno_type_constructData( pDest, pType );
314 OUString
const &
name =
315 OUString::unacquired( &pSource->pType->pTypeName );
317 if (
name ==
"com.sun.star.reflection.InvocationTargetException" )
321 &
static_cast< reflection::InvocationTargetException *
>(
322 pSource->pData )->TargetException;
323 ::uno_type_any_construct(
324 pDest, target_exc->pData, target_exc->pType,
nullptr );
328 if (typelib_TypeClass_EXCEPTION == pSource->pType->eTypeClass)
331 pDest,
static_cast<Exception const *
>(pSource->pData)->Message );
336 pDest,
"no exception has been thrown via invocation?!" );
341void AdapterImpl::getValue(
343 void * pReturn,
uno_Any ** ppException )
346 void * pInvokArgs[1];
347 pInvokArgs[0] =
const_cast<rtl_uString **
>(
348 &
reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *
>(pMemberType)->pMemberName);
350 uno_Any * pInvokExc = &aInvokExc;
355 &aInvokRet, pInvokArgs, &pInvokExc );
360 ::uno_any_destruct( pInvokExc,
nullptr );
364 if (coerce_construct(
366 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *
>(
367 pMemberType)->pAttributeTypeRef,
368 &aInvokRet, *ppException ))
370 *ppException =
nullptr;
372 ::uno_any_destruct( &aInvokRet,
nullptr );
376void AdapterImpl::setValue(
378 void * pArgs[],
uno_Any ** ppException )
381 ::uno_type_any_construct(
382 &aInvokVal, pArgs[0],
383 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *
>(
384 pMemberType)->pAttributeTypeRef,
nullptr );
386 void * pInvokArgs[2];
387 pInvokArgs[0] =
const_cast<rtl_uString **
>(
388 &
reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *
>(pMemberType)->pMemberName);
389 pInvokArgs[1] = &aInvokVal;
391 uno_Any * pInvokExc = &aInvokExc;
400 ::uno_any_destruct( pInvokExc,
nullptr );
404 *ppException =
nullptr;
407 ::uno_any_destruct( &aInvokVal,
nullptr );
410void AdapterImpl::invoke(
412 void * pReturn,
void * pArgs[],
uno_Any ** ppException )
415 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *
>(pMemberType)->nParams;
416 typelib_MethodParameter * pFormalParams =
417 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *
>(pMemberType)->pParams;
420 uno_Sequence * pInParamsSeq =
nullptr;
421 ::uno_sequence_construct(
422 &pInParamsSeq,
m_pFactory->m_pAnySeqTD,
nullptr, nParams,
nullptr );
423 uno_Any * pInAnys =
reinterpret_cast<uno_Any *
>(pInParamsSeq->elements);
424 sal_Int32 nOutParams = 0;
426 for ( nPos = nParams;
nPos--; )
428 typelib_MethodParameter
const & rParam = pFormalParams[
nPos];
431 ::uno_type_any_assign(
432 &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef,
nullptr,
nullptr );
441 uno_Sequence * pOutIndices;
442 uno_Sequence * pOutParams;
446 void * pInvokArgs[4];
447 pInvokArgs[0] =
const_cast<rtl_uString **
>(
448 &
reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *
>(pMemberType)->pMemberName);
449 pInvokArgs[1] = &pInParamsSeq;
450 pInvokArgs[2] = &pOutIndices;
451 pInvokArgs[3] = &pOutParams;
453 uno_Any * pInvokExc = &aInvokExc;
458 &aInvokRet, pInvokArgs, &pInvokExc );
463 ::uno_any_destruct( pInvokExc,
nullptr );
469 pOutParams->nElements == nOutParams &&
470 pOutIndices->nElements == nOutParams,
471 "### out params lens differ!" );
472 if (pOutParams->nElements == nOutParams &&
473 pOutIndices->nElements == nOutParams)
475 sal_Int16 * pIndices =
reinterpret_cast<sal_Int16 *
>(pOutIndices->elements);
477 for ( nPos = 0;
nPos < nOutParams; ++
nPos )
480 OSL_ENSURE(
nIndex < nParams,
"### illegal index!" );
481 typelib_MethodParameter
const & rParam = pFormalParams[
nIndex];
486 pArgs[
nIndex], rParam.pTypeRef, &pOut[nPos],
491 succ = coerce_construct(
492 pArgs[
nIndex], rParam.pTypeRef, &pOut[nPos],
497 for ( sal_Int32 n = 0;
n <=
nPos; ++
n )
499 sal_Int32 nIndex2 = pIndices[
n];
500 OSL_ENSURE( nIndex2 < nParams,
"### illegal index!" );
501 typelib_MethodParameter
const & rParam2 =
502 pFormalParams[nIndex2];
505 ::uno_type_destructData(
506 pArgs[nIndex2], rParam2.pTypeRef,
nullptr );
511 if (nPos == pOutIndices->nElements)
514 if (coerce_construct(
516 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *
>(
517 pMemberType)->pReturnTypeRef,
518 &aInvokRet, *ppException ))
520 *ppException =
nullptr;
529 "out params lengths differ after invocation call!" );
532 ::uno_destructData( &pOutIndices,
m_pFactory->m_pShortSeqTD,
nullptr );
533 ::uno_destructData( &pOutParams,
m_pFactory->m_pAnySeqTD,
nullptr );
535 ::uno_any_destruct( &aInvokRet,
nullptr );
538 ::uno_destructData( &pInParamsSeq,
m_pFactory->m_pAnySeqTD,
nullptr );
546 static_cast< InterfaceAdapterImpl *
>( pUnoI )->
m_pAdapter->acquire();
551 static_cast< InterfaceAdapterImpl *
>( pUnoI )->
m_pAdapter->release();
556 void * pReturn,
void * pArgs[],
uno_Any ** ppException )
559 switch (
reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *
>(pMemberType)->nPosition)
564 static_cast< InterfaceAdapterImpl *
>( pUnoI )->
m_pAdapter;
565 *ppException =
nullptr;
566 typelib_TypeDescriptionReference * pDemanded =
567 *
static_cast<typelib_TypeDescriptionReference **
>(pArgs[0]);
569 for (
size_t nPos = 0;
nPos < that->m_vInterfaces.size(); ++
nPos )
571 typelib_InterfaceTypeDescription * pTD =
572 that->m_vInterfaces[
nPos].m_pTypeDescr;
577 uno_Interface * pUnoI2 = &that->m_vInterfaces[
nPos];
579 static_cast<uno_Any *
>(pReturn), &pUnoI2,
580 &pTD->aBase,
nullptr );
583 pTD = pTD->pBaseTypeDescription;
586 ::uno_any_construct(
static_cast<uno_Any *
>(pReturn),
nullptr,
nullptr,
nullptr );
590 *ppException =
nullptr;
594 *ppException =
nullptr;
601 static_cast< InterfaceAdapterImpl *
>( pUnoI )->
m_pAdapter;
602 if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
604 that->invoke( pMemberType, pReturn, pArgs, ppException );
609 that->getValue( pMemberType, pReturn, ppException );
611 that->setValue( pMemberType, pArgs, ppException );
618AdapterImpl::AdapterImpl(
619 void * key, Reference< script::XInvocation >
const & xReceiver,
620 const Sequence< Type > & rTypes,
621 FactoryImpl * pFactory )
628 const Type * pTypes = rTypes.getConstArray();
629 for ( sal_Int32 nPos = rTypes.getLength(); nPos--; )
635 pInterface->m_pAdapter =
this;
636 pInterface->m_pTypeDescr =
nullptr;
637 pTypes[
nPos].getDescription(
639 OSL_ASSERT( pInterface->m_pTypeDescr );
640 if (! pInterface->m_pTypeDescr)
642 for ( sal_Int32 n = 0;
n <
nPos; ++
n )
644 ::typelib_typedescription_release(
648 "cannot retrieve all interface type infos!" );
654 xReceiver.get(),
cppu::UnoType<
decltype(xReceiver)>::get() ));
665FactoryImpl::FactoryImpl( Reference< XComponentContext >
const & xContext )
680 Reference< script::XTypeConverter >
xConverter(
681 xContext->getServiceManager()->createInstanceWithContext(
682 "com.sun.star.script.Converter",
694 const Type & rShortSeqType =
700 TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() );
701 typelib_InterfaceTypeDescription * pITD;
702 pITD =
reinterpret_cast<typelib_InterfaceTypeDescription*
>(pTD);
703 if( ! pITD->aBase.bComplete )
705 ::typelib_typedescriptionreference_getDescription(
707 ::typelib_typedescriptionreference_getDescription(
709 ::typelib_typedescriptionreference_getDescription(
712 const Type & rTCType =
714 TYPELIB_DANGER_GET( &pTD, rTCType.getTypeLibType() );
715 pITD =
reinterpret_cast<typelib_InterfaceTypeDescription*
>(pTD);
716 ::typelib_typedescriptionreference_getDescription(
718 TYPELIB_DANGER_RELEASE( pTD );
728FactoryImpl::~FactoryImpl()
739#if OSL_DEBUG_LEVEL > 0
747 t_ptr_map & map,
void * key, Sequence< Type >
const & rTypes )
750 *pp_adapter_set = &adapters_set;
751 if (adapters_set.
empty())
754 Type const * pTypes = rTypes.getConstArray();
755 sal_Int32 nTypes = rTypes.getLength();
756 for (
const auto& rpAdapter : adapters_set)
758 AdapterImpl * that =
static_cast< AdapterImpl *
>( rpAdapter );
761 for ( nPosTypes = nTypes; nPosTypes--; )
763 Type const & rType = pTypes[ nPosTypes ];
766 for (
nPos = that->m_vInterfaces.size();
nPos--; )
768 if (::typelib_typedescriptionreference_isAssignableFrom(
769 rType.getTypeLibType(),
770 that->m_vInterfaces[
nPos ].m_pTypeDescr->aBase.pWeakRef ))
787Reference< XInterface > FactoryImpl::createAdapter(
788 const Reference< script::XInvocation > & xReceiver,
789 const Sequence< Type > & rTypes )
791 Reference< XInterface > xRet;
792 if (xReceiver.is() && rTypes.hasElements())
796 Reference< XInterface > xKey( xReceiver, UNO_QUERY );
798 ClearableMutexGuard guard(
m_mutex );
806 new AdapterImpl( xKey.get(), xReceiver, rTypes,
this );
808 ClearableMutexGuard guard2(
m_mutex );
813 std::pair< t_ptr_set::const_iterator, bool >
i(adapter_set->insert(pNew));
816 "set already contains " << *(
i.first) <<
" != " << pNew);
832 uno_Interface * pUnoI = that->m_vInterfaces.data();
834 reinterpret_cast<void **
>(&xRet), pUnoI,
cppu::UnoType<
decltype(xRet)>::get() );
836 OSL_ASSERT( xRet.is() );
846Reference< XInterface > FactoryImpl::createAdapter(
847 const Reference< script::XInvocation > & xReceiver,
const Type & rType )
849 return createAdapter( xReceiver, Sequence< Type >( &rType, 1 ) );
854OUString FactoryImpl::getImplementationName()
856 return "com.sun.star.comp.stoc.InvocationAdapterFactory";
859sal_Bool FactoryImpl::supportsService(
const OUString & rServiceName )
864Sequence< OUString > FactoryImpl::getSupportedServiceNames()
866 return {
"com.sun.star.script.InvocationAdapterFactory" };
872extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
874 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any>
const&)
876 return cppu::acquire(
new stoc_invadp::FactoryImpl(context));
void SAL_CALL uno_type_any_construct(uno_Any *pDest, void *pSource, typelib_TypeDescriptionReference *pType, uno_AcquireFunc acquire) SAL_THROW_EXTERN_C()
css::uno::Type const & get()
Reference< XTypeConverter > xConverter
typelib_TypeDescription * m_pAnySeqTD
oslInterlockedCount m_nRef
t_ptr_map m_receiver2adapters
typelib_InterfaceTypeDescription * m_pTypeDescr
std::vector< InterfaceAdapterImpl > m_vInterfaces
typelib_TypeDescription * m_pInvokMethodTD
uno_Interface * m_pConverter
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * stoc_invocation_adapter_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
typelib_TypeDescription * m_pSetValueTD
typelib_TypeDescription * m_pShortSeqTD
uno_Interface * m_pReceiver
typelib_TypeDescription * m_pConvertToTD
typelib_TypeDescription * m_pGetValueTD
#define SAL_WARN_IF(condition, area, stream)
struct _typelib_TypeDescription typelib_TypeDescription
double getLength(const B2DPolygon &rCandidate)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
css::beans::Optional< css::uno::Any > getValue(std::u16string_view id)
bool coerce_assign(void *pDest, typelib_TypeDescription *pTD, const css::uno::Any &rSource, IdlReflectionServiceImpl *pRefl)
static void constructRuntimeException(uno_Any *pExc, const OUString &rMsg)
static AdapterImpl * lookup_adapter(t_ptr_set **pp_adapter_set, t_ptr_map &map, void *key, Sequence< Type > const &rTypes)
static void adapter_dispatch(uno_Interface *pUnoI, const typelib_TypeDescription *pMemberType, void *pReturn, void *pArgs[], uno_Any **ppException)
std::unordered_map< void *, t_ptr_set, hash_ptr > t_ptr_map
static void handleInvokExc(uno_Any *pDest, uno_Any *pSource)
o3tl::sorted_vector< void * > t_ptr_set
static bool type_equals(typelib_TypeDescriptionReference *pType1, typelib_TypeDescriptionReference *pType2)
static void adapter_acquire(uno_Interface *pUnoI)
static void adapter_release(uno_Interface *pUnoI)
def invoke(object, methodname, argTuple)
RegError REGISTRY_CALLTYPE setValue(RegKeyHandle hKey, rtl_uString *keyName, RegValueType valueType, RegValue pData, sal_uInt32 valueSize)
std::map< OUString, rtl::Reference< Entity > > map
sal_Bool SAL_CALL typelib_typedescription_complete(typelib_TypeDescription **ppTypeDescr) SAL_THROW_EXTERN_C()
sal_Bool SAL_CALL typelib_typedescriptionreference_isAssignableFrom(typelib_TypeDescriptionReference *pAssignable, typelib_TypeDescriptionReference *pFrom) SAL_THROW_EXTERN_C()