1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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>
48 using namespace ::osl
;
49 using namespace ::com::sun::star
;
50 using namespace css::uno
;
60 size_t operator() ( void * p
) const
61 { return reinterpret_cast<size_t>(p
); }
66 typedef o3tl::sorted_vector
< void * > t_ptr_set
;
67 typedef std::unordered_map
< void *, t_ptr_set
, hash_ptr
> t_ptr_map
;
72 : public ::cppu::WeakImplHelper
< lang::XServiceInfo
,
73 script::XInvocationAdapterFactory
,
74 script::XInvocationAdapterFactory2
>
79 uno_Interface
* m_pConverter
;
81 typelib_TypeDescription
* m_pInvokMethodTD
;
82 typelib_TypeDescription
* m_pSetValueTD
;
83 typelib_TypeDescription
* m_pGetValueTD
;
84 typelib_TypeDescription
* m_pAnySeqTD
;
85 typelib_TypeDescription
* m_pShortSeqTD
;
86 typelib_TypeDescription
* m_pConvertToTD
;
89 t_ptr_map m_receiver2adapters
;
91 explicit FactoryImpl( Reference
< XComponentContext
> const & xContext
);
92 virtual ~FactoryImpl() override
;
95 virtual OUString SAL_CALL
getImplementationName() override
;
96 virtual sal_Bool SAL_CALL
supportsService( const OUString
& rServiceName
) override
;
97 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
99 // XInvocationAdapterFactory
100 virtual Reference
< XInterface
> SAL_CALL
createAdapter(
101 const Reference
< script::XInvocation
> & xReceiver
, const Type
& rType
) override
;
102 // XInvocationAdapterFactory2
103 virtual Reference
< XInterface
> SAL_CALL
createAdapter(
104 const Reference
< script::XInvocation
> & xReceiver
,
105 const Sequence
< Type
> & rTypes
) override
;
109 struct InterfaceAdapterImpl
: public uno_Interface
111 AdapterImpl
* m_pAdapter
;
112 typelib_InterfaceTypeDescription
* m_pTypeDescr
;
117 oslInterlockedCount m_nRef
;
118 FactoryImpl
* m_pFactory
;
119 void * m_key
; // map key
120 uno_Interface
* m_pReceiver
; // XInvocation receiver
122 std::vector
<InterfaceAdapterImpl
> m_vInterfaces
;
126 const typelib_TypeDescription
* pMemberType
,
127 void * pReturn
, uno_Any
** ppException
);
129 const typelib_TypeDescription
* pMemberType
,
130 void * pArgs
[], uno_Any
** ppException
);
132 const typelib_TypeDescription
* pMemberType
,
133 void * pReturn
, void * pArgs
[], uno_Any
** ppException
);
136 void * pDest
, typelib_TypeDescriptionReference
* pType
,
137 uno_Any
* pSource
, uno_Any
* pExc
);
138 inline bool coerce_construct(
139 void * pDest
, typelib_TypeDescriptionReference
* pType
,
140 uno_Any
* pSource
, uno_Any
* pExc
);
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
);
150 // Copy assignment is forbidden and not implemented.
151 AdapterImpl (const AdapterImpl
&) = delete;
152 AdapterImpl
& operator= (const AdapterImpl
&) = delete;
157 inline AdapterImpl::~AdapterImpl()
159 for ( size_t nPos
= m_vInterfaces
.size(); nPos
--; )
161 ::typelib_typedescription_release(
162 &m_vInterfaces
[ nPos
].m_pTypeDescr
->aBase
);
165 (*m_pReceiver
->release
)( m_pReceiver
);
166 m_pFactory
->release();
169 inline void AdapterImpl::acquire()
171 osl_atomic_increment( &m_nRef
);
174 inline void AdapterImpl::release()
176 bool delete_this
= false;
178 MutexGuard
guard( m_pFactory
->m_mutex
);
179 if (! osl_atomic_decrement( &m_nRef
))
181 t_ptr_map::iterator
iFind(
182 m_pFactory
->m_receiver2adapters
.find( m_key
) );
183 assert( m_pFactory
->m_receiver2adapters
.end() != iFind
);
184 t_ptr_set
& adapter_set
= iFind
->second
;
185 if (adapter_set
.erase( this ) != 1) {
188 if (adapter_set
.empty())
190 m_pFactory
->m_receiver2adapters
.erase( iFind
);
200 static void constructRuntimeException(
201 uno_Any
* pExc
, const OUString
& rMsg
)
203 RuntimeException
exc( rMsg
);
204 // no conversion needed due to binary compatibility + no convertible type
205 ::uno_type_any_construct(
206 pExc
, &exc
, cppu::UnoType
<decltype(exc
)>::get().getTypeLibType(), nullptr );
210 static bool type_equals(
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
)));
221 bool AdapterImpl::coerce_assign(
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 ))
236 else // try type converter
243 uno_Any
* p_exc
= &exc
;
246 (*m_pFactory
->m_pConverter
->pDispatcher
)(
247 m_pFactory
->m_pConverter
,
248 m_pFactory
->m_pConvertToTD
, &ret
, args
, &p_exc
);
250 if (p_exc
) // exception occurred
253 p_exc
->pType
->eTypeClass
== typelib_TypeClass_EXCEPTION
);
254 if (typelib_typedescriptionreference_isAssignableFrom( cppu::UnoType
<RuntimeException
>::get().getTypeLibType(),
257 // is RuntimeException or derived: rethrow
258 uno_type_any_construct(
259 pOutExc
, p_exc
->pData
, p_exc
->pType
, nullptr );
263 // set runtime exception
264 constructRuntimeException(
265 pOutExc
, "type coercion failed: " +
266 static_cast< Exception
const * >(
267 p_exc
->pData
)->Message
);
269 ::uno_any_destruct( p_exc
, nullptr );
270 // pOutExc constructed
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!?" );
282 // set runtime exception
283 constructRuntimeException(
285 u
"type coercion failed: "
286 "conversion succeeded, but assignment failed?!"_ustr
);
293 inline 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 );
302 if (type_equals( pType
, pSource
->pType
))
304 ::uno_type_copyData( pDest
, pSource
->pData
, pType
, nullptr );
307 ::uno_type_constructData( pDest
, pType
);
308 return coerce_assign( pDest
, pType
, pSource
, pExc
);
312 static void handleInvokExc( uno_Any
* pDest
, uno_Any
* pSource
)
314 OUString
const & name
=
315 OUString::unacquired( &pSource
->pType
->pTypeName
);
317 if ( name
== "com.sun.star.reflection.InvocationTargetException" )
319 // unwrap invocation target exception
320 uno_Any
* target_exc
=
321 &static_cast< reflection::InvocationTargetException
* >(
322 pSource
->pData
)->TargetException
;
323 ::uno_type_any_construct(
324 pDest
, target_exc
->pData
, target_exc
->pType
, nullptr );
326 else // all other exceptions are wrapped to RuntimeException
328 if (typelib_TypeClass_EXCEPTION
== pSource
->pType
->eTypeClass
)
330 constructRuntimeException(
331 pDest
, static_cast<Exception
const *>(pSource
->pData
)->Message
);
335 constructRuntimeException(
336 pDest
, u
"no exception has been thrown via invocation?!"_ustr
);
341 void AdapterImpl::getValue(
342 const typelib_TypeDescription
* pMemberType
,
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
;
353 (*m_pReceiver
->pDispatcher
)(
354 m_pReceiver
, m_pFactory
->m_pGetValueTD
,
355 &aInvokRet
, pInvokArgs
, &pInvokExc
);
357 if (pInvokExc
) // getValue() call exception
359 handleInvokExc( *ppException
, pInvokExc
);
360 ::uno_any_destruct( pInvokExc
, nullptr ); // cleanup
362 else // invocation call succeeded
364 if (coerce_construct(
366 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(
367 pMemberType
)->pAttributeTypeRef
,
368 &aInvokRet
, *ppException
))
370 *ppException
= nullptr; // no exceptions be thrown
372 ::uno_any_destruct( &aInvokRet
, nullptr );
376 void AdapterImpl::setValue(
377 const typelib_TypeDescription
* pMemberType
,
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
;
394 (*m_pReceiver
->pDispatcher
)(
395 m_pReceiver
, m_pFactory
->m_pSetValueTD
, nullptr, pInvokArgs
, &pInvokExc
);
397 if (pInvokExc
) // setValue() call exception
399 handleInvokExc( *ppException
, pInvokExc
);
400 ::uno_any_destruct( pInvokExc
, nullptr ); // cleanup
402 else // invocation call succeeded
404 *ppException
= nullptr; // no exceptions be thrown
407 ::uno_any_destruct( &aInvokVal
, nullptr ); // cleanup
410 void AdapterImpl::invoke(
411 const typelib_TypeDescription
* pMemberType
,
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
];
429 if (rParam
.bIn
) // is in/inout param
431 ::uno_type_any_assign(
432 &pInAnys
[nPos
], pArgs
[nPos
], rParam
.pTypeRef
, nullptr, nullptr );
434 // else: pure out is empty any
440 // out params, out indices
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
;
456 (*m_pReceiver
->pDispatcher
)(
457 m_pReceiver
, m_pFactory
->m_pInvokMethodTD
,
458 &aInvokRet
, pInvokArgs
, &pInvokExc
);
462 handleInvokExc( *ppException
, pInvokExc
);
463 ::uno_any_destruct( pInvokExc
, nullptr ); // cleanup
465 else // no invocation exception
467 // write changed out params
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
);
476 uno_Any
* pOut
= reinterpret_cast<uno_Any
*>(pOutParams
->elements
);
477 for ( nPos
= 0; nPos
< nOutParams
; ++nPos
)
479 sal_Int32 nIndex
= pIndices
[nPos
];
480 OSL_ENSURE( nIndex
< nParams
, "### illegal index!" );
481 typelib_MethodParameter
const & rParam
= pFormalParams
[nIndex
];
483 if (rParam
.bIn
) // is in/inout param
485 succ
= coerce_assign(
486 pArgs
[nIndex
], rParam
.pTypeRef
, &pOut
[nPos
],
491 succ
= coerce_construct(
492 pArgs
[nIndex
], rParam
.pTypeRef
, &pOut
[nPos
],
495 if (! succ
) // cleanup of out params
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
];
503 if (! rParam2
.bIn
) // is pure out param
505 ::uno_type_destructData(
506 pArgs
[nIndex2
], rParam2
.pTypeRef
, nullptr );
511 if (nPos
== pOutIndices
->nElements
)
513 // out param copy ok; write return value
514 if (coerce_construct(
516 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(
517 pMemberType
)->pReturnTypeRef
,
518 &aInvokRet
, *ppException
))
520 *ppException
= nullptr; // no exception
526 // set runtime exception
527 constructRuntimeException(
529 u
"out params lengths differ after invocation call!"_ustr
);
531 // cleanup invok out params
532 ::uno_destructData( &pOutIndices
, m_pFactory
->m_pShortSeqTD
, nullptr );
533 ::uno_destructData( &pOutParams
, m_pFactory
->m_pAnySeqTD
, nullptr );
534 // cleanup invok return value
535 ::uno_any_destruct( &aInvokRet
, nullptr );
537 // cleanup constructed in params
538 ::uno_destructData( &pInParamsSeq
, m_pFactory
->m_pAnySeqTD
, nullptr );
544 static void adapter_acquire( uno_Interface
* pUnoI
)
546 static_cast< InterfaceAdapterImpl
* >( pUnoI
)->m_pAdapter
->acquire();
549 static void adapter_release( uno_Interface
* pUnoI
)
551 static_cast< InterfaceAdapterImpl
* >( pUnoI
)->m_pAdapter
->release();
554 static void adapter_dispatch(
555 uno_Interface
* pUnoI
, const typelib_TypeDescription
* pMemberType
,
556 void * pReturn
, void * pArgs
[], uno_Any
** ppException
)
558 // query to emulated interface
559 switch (reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *>(pMemberType
)->nPosition
)
561 case 0: // queryInterface()
564 static_cast< InterfaceAdapterImpl
* >( pUnoI
)->m_pAdapter
;
565 *ppException
= nullptr; // no exc
566 typelib_TypeDescriptionReference
* pDemanded
=
567 *static_cast<typelib_TypeDescriptionReference
**>(pArgs
[0]);
568 // pInterfaces[0] is XInterface
569 for ( size_t nPos
= 0; nPos
< that
->m_vInterfaces
.size(); ++nPos
)
571 typelib_InterfaceTypeDescription
* pTD
=
572 that
->m_vInterfaces
[nPos
].m_pTypeDescr
;
575 if (type_equals( pTD
->aBase
.pWeakRef
, pDemanded
))
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 ); // clear()
590 *ppException
= nullptr; // no exc
591 adapter_acquire( pUnoI
);
594 *ppException
= nullptr; // no exc
595 adapter_release( pUnoI
);
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
);
618 AdapterImpl::AdapterImpl(
619 void * key
, Reference
< script::XInvocation
> const & xReceiver
,
620 const Sequence
< Type
> & rTypes
,
621 FactoryImpl
* pFactory
)
623 m_pFactory( pFactory
),
625 m_vInterfaces( rTypes
.getLength() )
628 const Type
* pTypes
= rTypes
.getConstArray();
629 for ( sal_Int32 nPos
= rTypes
.getLength(); nPos
--; )
631 InterfaceAdapterImpl
* pInterface
= &m_vInterfaces
[nPos
];
632 pInterface
->acquire
= adapter_acquire
;
633 pInterface
->release
= adapter_release
;
634 pInterface
->pDispatcher
= adapter_dispatch
;
635 pInterface
->m_pAdapter
= this;
636 pInterface
->m_pTypeDescr
= nullptr;
637 pTypes
[nPos
].getDescription(
638 reinterpret_cast<typelib_TypeDescription
**>(&pInterface
->m_pTypeDescr
) );
639 OSL_ASSERT( pInterface
->m_pTypeDescr
);
640 if (! pInterface
->m_pTypeDescr
)
642 for ( sal_Int32 n
= 0; n
< nPos
; ++n
)
644 ::typelib_typedescription_release(
645 &m_vInterfaces
[ n
].m_pTypeDescr
->aBase
);
647 throw RuntimeException(
648 u
"cannot retrieve all interface type infos!"_ustr
);
653 m_pReceiver
= static_cast<uno_Interface
*>(m_pFactory
->m_aCpp2Uno
.mapInterface(
654 xReceiver
.get(), cppu::UnoType
<decltype(xReceiver
)>::get() ));
655 OSL_ASSERT( nullptr != m_pReceiver
);
658 throw RuntimeException( u
"cannot map receiver!"_ustr
);
661 m_pFactory
->acquire();
665 FactoryImpl::FactoryImpl( Reference
< XComponentContext
> const & xContext
)
666 : m_aUno2Cpp(Mapping( u
"" UNO_LB_UNO
""_ustr
, CPPU_CURRENT_LANGUAGE_BINDING_NAME
)),
667 m_aCpp2Uno(Mapping( CPPU_CURRENT_LANGUAGE_BINDING_NAME
, u
"" UNO_LB_UNO
""_ustr
)),
668 m_pInvokMethodTD( nullptr ),
669 m_pSetValueTD( nullptr ),
670 m_pGetValueTD( nullptr ),
671 m_pAnySeqTD( nullptr ),
672 m_pShortSeqTD( nullptr ),
673 m_pConvertToTD( nullptr )
677 m_aUno2Cpp
.is() && m_aCpp2Uno
.is(), "### no uno / C++ mappings!" );
680 Reference
< script::XTypeConverter
> xConverter(
681 xContext
->getServiceManager()->createInstanceWithContext(
682 u
"com.sun.star.script.Converter"_ustr
,
685 m_pConverter
= static_cast<uno_Interface
*>(m_aCpp2Uno
.mapInterface(
686 xConverter
.get(), cppu::UnoType
<decltype(xConverter
)>::get() ));
687 OSL_ASSERT( nullptr != m_pConverter
);
691 Type
const & rAnySeqType
= cppu::UnoType
<Sequence
< Any
>>::get();
692 rAnySeqType
.getDescription( &m_pAnySeqTD
);
694 const Type
& rShortSeqType
=
695 cppu::UnoType
<Sequence
< sal_Int16
>>::get();
696 rShortSeqType
.getDescription( &m_pShortSeqTD
);
697 // script.XInvocation
698 typelib_TypeDescription
* pTD
= nullptr;
699 const Type
& rInvType
= cppu::UnoType
<script::XInvocation
>::get();
700 TYPELIB_DANGER_GET( &pTD
, rInvType
.getTypeLibType() );
701 typelib_InterfaceTypeDescription
* pITD
;
702 pITD
= reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTD
);
703 if( ! pITD
->aBase
.bComplete
)
704 typelib_typedescription_complete( &pTD
);
705 ::typelib_typedescriptionreference_getDescription(
706 &m_pInvokMethodTD
, pITD
->ppMembers
[ 1 ] ); // invoke()
707 ::typelib_typedescriptionreference_getDescription(
708 &m_pSetValueTD
, pITD
->ppMembers
[ 2 ] ); // setValue()
709 ::typelib_typedescriptionreference_getDescription(
710 &m_pGetValueTD
, pITD
->ppMembers
[ 3 ] ); // getValue()
711 // script.XTypeConverter
712 const Type
& rTCType
=
713 cppu::UnoType
<script::XTypeConverter
>::get();
714 TYPELIB_DANGER_GET( &pTD
, rTCType
.getTypeLibType() );
715 pITD
= reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTD
);
716 ::typelib_typedescriptionreference_getDescription(
717 &m_pConvertToTD
, pITD
->ppMembers
[ 0 ] ); // convertTo()
718 TYPELIB_DANGER_RELEASE( pTD
);
720 if (!m_pInvokMethodTD
|| !m_pSetValueTD
|| !m_pGetValueTD
||
722 !m_pAnySeqTD
|| !m_pShortSeqTD
)
724 throw RuntimeException( u
"missing type descriptions!"_ustr
);
728 FactoryImpl::~FactoryImpl()
730 ::typelib_typedescription_release( m_pInvokMethodTD
);
731 ::typelib_typedescription_release( m_pSetValueTD
);
732 ::typelib_typedescription_release( m_pGetValueTD
);
733 ::typelib_typedescription_release( m_pAnySeqTD
);
734 ::typelib_typedescription_release( m_pShortSeqTD
);
735 ::typelib_typedescription_release( m_pConvertToTD
);
737 (*m_pConverter
->release
)( m_pConverter
);
739 #if OSL_DEBUG_LEVEL > 0
740 assert(m_receiver2adapters
.empty() && "still adapters out there!?");
745 static AdapterImpl
* lookup_adapter(
746 t_ptr_set
** pp_adapter_set
,
747 t_ptr_map
& map
, void * key
, Sequence
< Type
> const & rTypes
)
749 t_ptr_set
& adapters_set
= map
[ key
];
750 *pp_adapter_set
= &adapters_set
;
751 if (adapters_set
.empty())
752 return nullptr; // shortcut
753 // find matching adapter
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
);
759 // iterate through all types if that is a matching adapter
761 for ( nPosTypes
= nTypes
; nPosTypes
--; )
763 Type
const & rType
= pTypes
[ nPosTypes
];
764 // find in adapter's type list
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
))
776 if (nPos
< 0) // type not found => next adapter
779 if (nPosTypes
< 0) // all types found
785 // XInvocationAdapterFactory2 impl
787 Reference
< XInterface
> FactoryImpl::createAdapter(
788 const Reference
< script::XInvocation
> & xReceiver
,
789 const Sequence
< Type
> & rTypes
)
791 Reference
< XInterface
> xRet
;
792 if (xReceiver
.is() && rTypes
.hasElements())
794 t_ptr_set
* adapter_set
;
796 Reference
< XInterface
> xKey( xReceiver
, UNO_QUERY
);
798 ClearableMutexGuard
guard( m_mutex
);
799 that
= lookup_adapter(
800 &adapter_set
, m_receiver2adapters
, xKey
.get(), rTypes
);
801 if (nullptr == that
) // no entry
804 // create adapter; already acquired: m_nRef == 1
806 new AdapterImpl( xKey
.get(), xReceiver
, rTypes
, this );
808 ClearableMutexGuard
guard2( m_mutex
);
809 that
= lookup_adapter(
810 &adapter_set
, m_receiver2adapters
, xKey
.get(), rTypes
);
811 if (nullptr == that
) // again no entry
813 std::pair
< t_ptr_set::const_iterator
, bool > i(adapter_set
->insert(pNew
));
816 "set already contains " << *(i
.first
) << " != " << pNew
);
823 delete pNew
; // has never been inserted
826 else // found adapter
831 // map one interface to C++
832 uno_Interface
* pUnoI
= that
->m_vInterfaces
.data();
833 m_aUno2Cpp
.mapInterface(
834 reinterpret_cast<void **>(&xRet
), pUnoI
, cppu::UnoType
<decltype(xRet
)>::get() );
836 OSL_ASSERT( xRet
.is() );
839 throw RuntimeException( u
"mapping UNO to C++ failed!"_ustr
);
844 // XInvocationAdapterFactory impl
846 Reference
< XInterface
> FactoryImpl::createAdapter(
847 const Reference
< script::XInvocation
> & xReceiver
, const Type
& rType
)
849 return createAdapter( xReceiver
, Sequence
< Type
>( &rType
, 1 ) );
854 OUString
FactoryImpl::getImplementationName()
856 return u
"com.sun.star.comp.stoc.InvocationAdapterFactory"_ustr
;
859 sal_Bool
FactoryImpl::supportsService( const OUString
& rServiceName
)
861 return cppu::supportsService(this, rServiceName
);
864 Sequence
< OUString
> FactoryImpl::getSupportedServiceNames()
866 return { u
"com.sun.star.script.InvocationAdapterFactory"_ustr
};
872 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
873 stoc_invocation_adapter_get_implementation(
874 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
876 return cppu::acquire(new stoc_invadp::FactoryImpl(context
));
881 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */