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>
46 #include <unordered_set>
49 using namespace ::std
;
50 using namespace ::osl
;
51 using namespace ::com::sun::star
;
52 using namespace css::uno
;
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
;
74 : public ::cppu::WeakImplHelper
< lang::XServiceInfo
,
75 script::XInvocationAdapterFactory
,
76 script::XInvocationAdapterFactory2
>
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
;
91 t_ptr_map m_receiver2adapters
;
93 explicit FactoryImpl( Reference
< XComponentContext
> const & xContext
);
94 virtual ~FactoryImpl() override
;
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
;
111 struct InterfaceAdapterImpl
: public uno_Interface
113 AdapterImpl
* m_pAdapter
;
114 typelib_InterfaceTypeDescription
* m_pTypeDescr
;
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
;
128 const typelib_TypeDescription
* pMemberType
,
129 void * pReturn
, uno_Any
** ppException
);
131 const typelib_TypeDescription
* pMemberType
,
132 void * pArgs
[], uno_Any
** ppException
);
134 const typelib_TypeDescription
* pMemberType
,
135 void * pReturn
, void * pArgs
[], uno_Any
** ppException
);
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();
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) {
190 if (adapter_set
.empty())
192 m_pFactory
->m_receiver2adapters
.erase( iFind
);
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
,
227 if (typelib_TypeClass_ANY
== pType
->eTypeClass
)
229 ::uno_type_any_assign(
230 static_cast<uno_Any
*>(pDest
), pSource
->pData
, pSource
->pType
, nullptr, nullptr );
233 if (::uno_type_assignData(
234 pDest
, pType
, pSource
->pData
, pSource
->pType
, nullptr, nullptr, nullptr ))
238 else // try type converter
245 uno_Any
* p_exc
= &exc
;
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
255 p_exc
->pType
->eTypeClass
== typelib_TypeClass_EXCEPTION
);
256 if (typelib_typedescriptionreference_isAssignableFrom( cppu::UnoType
<RuntimeException
>::get().getTypeLibType(),
259 // is RuntimeException or derived: rethrow
260 uno_type_any_construct(
261 pOutExc
, p_exc
->pData
, p_exc
->pType
, nullptr );
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
277 bool succ
= ::uno_type_assignData(
278 pDest
, pType
, ret
.pData
, ret
.pType
, nullptr, nullptr, nullptr );
279 ::uno_any_destruct( &ret
, nullptr );
281 succ
, "### conversion succeeded, but assignment failed!?" );
284 // set runtime exception
285 constructRuntimeException(
287 "type coercion failed: "
288 "conversion succeeded, but assignment failed?!" );
295 inline bool AdapterImpl::coerce_construct(
296 void * pDest
, typelib_TypeDescriptionReference
* pType
, uno_Any
* pSource
,
299 if (typelib_TypeClass_ANY
== pType
->eTypeClass
)
301 ::uno_type_copyData( pDest
, pSource
, pType
, nullptr );
304 if (type_equals( pType
, pSource
->pType
))
306 ::uno_type_copyData( pDest
, pSource
->pData
, pType
, nullptr );
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
);
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
)
348 void * pInvokArgs
[1];
349 pInvokArgs
[0] = const_cast<rtl_uString
**>(
350 &reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *>(pMemberType
)->pMemberName
);
352 uno_Any
* pInvokExc
= &aInvokExc
;
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(
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
)
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
;
393 uno_Any
* pInvokExc
= &aInvokExc
;
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
)
417 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(pMemberType
)->nParams
;
418 typelib_MethodParameter
* pFormalParams
=
419 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(pMemberType
)->pParams
;
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;
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
442 // out params, out indices
443 uno_Sequence
* pOutIndices
;
444 uno_Sequence
* pOutParams
;
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
;
455 uno_Any
* pInvokExc
= &aInvokExc
;
458 (*m_pReceiver
->pDispatcher
)(
459 m_pReceiver
, m_pFactory
->m_pInvokMethodTD
,
460 &aInvokRet
, pInvokArgs
, &pInvokExc
);
464 handleInvokExc( *ppException
, pInvokExc
);
465 ::uno_any_destruct( pInvokExc
, nullptr ); // cleanup
467 else // no invocation exception
469 // write changed out params
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
];
485 if (rParam
.bIn
) // is in/inout param
487 succ
= coerce_assign(
488 pArgs
[nIndex
], rParam
.pTypeRef
, &pOut
[nPos
],
493 succ
= coerce_construct(
494 pArgs
[nIndex
], rParam
.pTypeRef
, &pOut
[nPos
],
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(
518 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(
519 pMemberType
)->pReturnTypeRef
,
520 &aInvokRet
, *ppException
))
522 *ppException
= nullptr; // no exception
528 // set runtime exception
529 constructRuntimeException(
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 );
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()
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
;
577 if (type_equals( pTD
->aBase
.pWeakRef
, pDemanded
))
579 uno_Interface
* pUnoI2
= &that
->m_vInterfaces
[nPos
];
581 static_cast<uno_Any
*>(pReturn
), &pUnoI2
,
582 &pTD
->aBase
, nullptr );
585 pTD
= pTD
->pBaseTypeDescription
;
588 ::uno_any_construct( static_cast<uno_Any
*>(pReturn
), nullptr, nullptr, nullptr ); // clear()
592 *ppException
= nullptr; // no exc
593 adapter_acquire( pUnoI
);
596 *ppException
= nullptr; // no exc
597 adapter_release( pUnoI
);
603 static_cast< InterfaceAdapterImpl
* >( pUnoI
)->m_pAdapter
;
604 if (pMemberType
->eTypeClass
== typelib_TypeClass_INTERFACE_METHOD
)
606 that
->invoke( pMemberType
, pReturn
, pArgs
, ppException
);
611 that
->getValue( pMemberType
, pReturn
, ppException
);
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
)
625 m_pFactory( pFactory
),
627 m_vInterfaces( rTypes
.getLength() )
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!" );
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
);
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 )
679 m_aUno2Cpp
.is() && m_aCpp2Uno
.is(), "### no uno / C++ mappings!" );
682 Reference
< script::XTypeConverter
> xConverter(
683 xContext
->getServiceManager()->createInstanceWithContext(
684 "com.sun.star.script.Converter",
687 m_pConverter
= static_cast<uno_Interface
*>(m_aCpp2Uno
.mapInterface(
688 xConverter
.get(), cppu::UnoType
<decltype(xConverter
)>::get() ));
689 OSL_ASSERT( nullptr != m_pConverter
);
693 Type
const & rAnySeqType
= cppu::UnoType
<Sequence
< Any
>>::get();
694 rAnySeqType
.getDescription( &m_pAnySeqTD
);
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
||
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!?");
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
763 for ( nPosTypes
= nTypes
; nPosTypes
--; )
765 Type
const & rType
= pTypes
[ nPosTypes
];
766 // find in adapter's type list
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
))
778 if (nPos
< 0) // type not found => next adapter
781 if (nPosTypes
< 0) // all types found
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
;
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
806 // create adapter; already acquired: m_nRef == 1
808 new AdapterImpl( xKey
.get(), xReceiver
, rTypes
, this );
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
));
818 "set already contains " << *(i
.first
) << " != " << pNew
);
825 delete pNew
; // has never been inserted
828 else // found adapter
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() );
838 OSL_ASSERT( xRet
.is() );
841 throw RuntimeException( "mapping UNO to C++ failed!" );
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 ) );
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: */