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 <sal/log.hxx>
26 #include <uno/dispatcher.h>
29 #include <uno/lbnames.h>
30 #include <uno/mapping.hxx>
32 #include <cppuhelper/factory.hxx>
33 #include <cppuhelper/implbase.hxx>
34 #include <cppuhelper/implementationentry.hxx>
35 #include <cppuhelper/supportsservice.hxx>
37 #include <com/sun/star/uno/XAggregation.hpp>
38 #include <com/sun/star/script/XTypeConverter.hpp>
39 #include <com/sun/star/script/XInvocationAdapterFactory.hpp>
40 #include <com/sun/star/script/XInvocationAdapterFactory2.hpp>
41 #include <com/sun/star/script/XInvocation.hpp>
42 #include <com/sun/star/lang/XServiceInfo.hpp>
43 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
44 #include <com/sun/star/registry/XSimpleRegistry.hpp>
45 #include <com/sun/star/registry/XRegistryKey.hpp>
46 #include <com/sun/star/reflection/InvocationTargetException.hpp>
47 #include <com/sun/star/uno/RuntimeException.hpp>
49 #include <unordered_map>
50 #include <unordered_set>
52 #define IMPLNAME "com.sun.star.comp.stoc.InvocationAdapterFactory"
54 using namespace ::std
;
55 using namespace ::osl
;
56 using namespace ::com::sun::star
;
57 using namespace css::uno
;
62 static Sequence
< OUString
> invadp_getSupportedServiceNames()
64 Sequence
< OUString
> seqNames
{ "com.sun.star.script.InvocationAdapterFactory" };
68 static OUString
invadp_getImplementationName()
70 return OUString(IMPLNAME
);
75 size_t operator() ( void * p
) const
76 { return reinterpret_cast<size_t>(p
); }
78 typedef std::unordered_set
< void *, hash_ptr
> t_ptr_set
;
79 typedef std::unordered_map
< void *, t_ptr_set
, hash_ptr
> t_ptr_map
;
83 : public ::cppu::WeakImplHelper
< lang::XServiceInfo
,
84 script::XInvocationAdapterFactory
,
85 script::XInvocationAdapterFactory2
>
90 uno_Interface
* m_pConverter
;
92 typelib_TypeDescription
* m_pInvokMethodTD
;
93 typelib_TypeDescription
* m_pSetValueTD
;
94 typelib_TypeDescription
* m_pGetValueTD
;
95 typelib_TypeDescription
* m_pAnySeqTD
;
96 typelib_TypeDescription
* m_pShortSeqTD
;
97 typelib_TypeDescription
* m_pConvertToTD
;
100 t_ptr_map m_receiver2adapters
;
102 explicit FactoryImpl( Reference
< XComponentContext
> const & xContext
);
103 virtual ~FactoryImpl() override
;
106 virtual OUString SAL_CALL
getImplementationName() override
;
107 virtual sal_Bool SAL_CALL
supportsService( const OUString
& rServiceName
) override
;
108 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
110 // XInvocationAdapterFactory
111 virtual Reference
< XInterface
> SAL_CALL
createAdapter(
112 const Reference
< script::XInvocation
> & xReceiver
, const Type
& rType
) override
;
113 // XInvocationAdapterFactory2
114 virtual Reference
< XInterface
> SAL_CALL
createAdapter(
115 const Reference
< script::XInvocation
> & xReceiver
,
116 const Sequence
< Type
> & rTypes
) override
;
120 struct InterfaceAdapterImpl
: public uno_Interface
122 AdapterImpl
* m_pAdapter
;
123 typelib_InterfaceTypeDescription
* m_pTypeDescr
;
128 oslInterlockedCount m_nRef
;
129 FactoryImpl
* m_pFactory
;
130 void * m_key
; // map key
131 uno_Interface
* m_pReceiver
; // XInvocation receiver
133 sal_Int32 m_nInterfaces
;
134 InterfaceAdapterImpl
* m_pInterfaces
;
138 const typelib_TypeDescription
* pMemberType
,
139 void * pReturn
, uno_Any
** ppException
);
141 const typelib_TypeDescription
* pMemberType
,
142 void * pArgs
[], uno_Any
** ppException
);
144 const typelib_TypeDescription
* pMemberType
,
145 void * pReturn
, void * pArgs
[], uno_Any
** ppException
);
148 void * pDest
, typelib_TypeDescriptionReference
* pType
,
149 uno_Any
* pSource
, uno_Any
* pExc
);
150 inline bool coerce_construct(
151 void * pDest
, typelib_TypeDescriptionReference
* pType
,
152 uno_Any
* pSource
, uno_Any
* pExc
);
154 inline void acquire();
155 inline void release();
156 inline ~AdapterImpl();
158 void * key
, Reference
< script::XInvocation
> const & xReceiver
,
159 const Sequence
< Type
> & rTypes
,
160 FactoryImpl
* pFactory
);
162 // Copy assignment is forbidden and not implemented.
163 AdapterImpl (const AdapterImpl
&) = delete;
164 AdapterImpl
& operator= (const AdapterImpl
&) = delete;
167 inline AdapterImpl::~AdapterImpl()
169 for ( sal_Int32 nPos
= m_nInterfaces
; nPos
--; )
171 ::typelib_typedescription_release(
172 &m_pInterfaces
[ nPos
].m_pTypeDescr
->aBase
);
174 delete [] m_pInterfaces
;
176 (*m_pReceiver
->release
)( m_pReceiver
);
177 m_pFactory
->release();
180 inline void AdapterImpl::acquire()
182 osl_atomic_increment( &m_nRef
);
185 inline void AdapterImpl::release()
187 bool delete_this
= false;
189 MutexGuard
guard( m_pFactory
->m_mutex
);
190 if (! osl_atomic_decrement( &m_nRef
))
192 t_ptr_map::iterator
iFind(
193 m_pFactory
->m_receiver2adapters
.find( m_key
) );
194 OSL_ASSERT( m_pFactory
->m_receiver2adapters
.end() != iFind
);
195 t_ptr_set
& adapter_set
= iFind
->second
;
196 if (adapter_set
.erase( this ) != 1) {
199 if (adapter_set
.empty())
201 m_pFactory
->m_receiver2adapters
.erase( iFind
);
211 static inline void constructRuntimeException(
212 uno_Any
* pExc
, const OUString
& rMsg
)
214 RuntimeException
exc( rMsg
);
215 // no conversion needed due to binary compatibility + no convertible type
216 ::uno_type_any_construct(
217 pExc
, &exc
, cppu::UnoType
<decltype(exc
)>::get().getTypeLibType(), nullptr );
221 static inline bool type_equals(
222 typelib_TypeDescriptionReference
* pType1
,
223 typelib_TypeDescriptionReference
* pType2
)
225 return (pType1
== pType2
||
226 (pType1
->pTypeName
->length
== pType2
->pTypeName
->length
&&
227 0 == ::rtl_ustr_compare(
228 pType1
->pTypeName
->buffer
, pType2
->pTypeName
->buffer
)));
232 bool AdapterImpl::coerce_assign(
233 void * pDest
, typelib_TypeDescriptionReference
* pType
, uno_Any
* pSource
,
236 if (typelib_TypeClass_ANY
== pType
->eTypeClass
)
238 ::uno_type_any_assign(
239 static_cast<uno_Any
*>(pDest
), pSource
->pData
, pSource
->pType
, nullptr, nullptr );
242 if (::uno_type_assignData(
243 pDest
, pType
, pSource
->pData
, pSource
->pType
, nullptr, nullptr, nullptr ))
247 else // try type converter
254 uno_Any
* p_exc
= &exc
;
257 (*m_pFactory
->m_pConverter
->pDispatcher
)(
258 m_pFactory
->m_pConverter
,
259 m_pFactory
->m_pConvertToTD
, &ret
, args
, &p_exc
);
261 if (p_exc
) // exception occurred
264 p_exc
->pType
->eTypeClass
== typelib_TypeClass_EXCEPTION
);
265 if (typelib_typedescriptionreference_isAssignableFrom( cppu::UnoType
<RuntimeException
>::get().getTypeLibType(),
268 // is RuntimeException or derived: rethrow
269 uno_type_any_construct(
270 pOutExc
, p_exc
->pData
, p_exc
->pType
, nullptr );
274 // set runtime exception
275 constructRuntimeException(
276 pOutExc
, "type coercion failed: " +
277 static_cast< Exception
const * >(
278 p_exc
->pData
)->Message
);
280 ::uno_any_destruct( p_exc
, nullptr );
281 // pOutExc constructed
286 bool succ
= ::uno_type_assignData(
287 pDest
, pType
, ret
.pData
, ret
.pType
, nullptr, nullptr, nullptr );
288 ::uno_any_destruct( &ret
, nullptr );
290 succ
, "### conversion succeeded, but assignment failed!?" );
293 // set runtime exception
294 constructRuntimeException(
296 "type coercion failed: "
297 "conversion succeeded, but assignment failed?!" );
304 inline bool AdapterImpl::coerce_construct(
305 void * pDest
, typelib_TypeDescriptionReference
* pType
, uno_Any
* pSource
,
308 if (typelib_TypeClass_ANY
== pType
->eTypeClass
)
310 ::uno_type_copyData( pDest
, pSource
, pType
, nullptr );
313 if (type_equals( pType
, pSource
->pType
))
315 ::uno_type_copyData( pDest
, pSource
->pData
, pType
, nullptr );
318 ::uno_type_constructData( pDest
, pType
);
319 return coerce_assign( pDest
, pType
, pSource
, pExc
);
323 static void handleInvokExc( uno_Any
* pDest
, uno_Any
* pSource
)
325 OUString
const & name
=
326 OUString::unacquired( &pSource
->pType
->pTypeName
);
328 if ( name
== "com.sun.star.reflection.InvocationTargetException" )
330 // unwrap invocation target exception
331 uno_Any
* target_exc
=
332 &static_cast< reflection::InvocationTargetException
* >(
333 pSource
->pData
)->TargetException
;
334 ::uno_type_any_construct(
335 pDest
, target_exc
->pData
, target_exc
->pType
, nullptr );
337 else // all other exceptions are wrapped to RuntimeException
339 if (typelib_TypeClass_EXCEPTION
== pSource
->pType
->eTypeClass
)
341 constructRuntimeException(
342 pDest
, static_cast<Exception
const *>(pSource
->pData
)->Message
);
346 constructRuntimeException(
347 pDest
, "no exception has been thrown via invocation?!" );
352 void AdapterImpl::getValue(
353 const typelib_TypeDescription
* pMemberType
,
354 void * pReturn
, uno_Any
** ppException
)
357 void * pInvokArgs
[1];
358 pInvokArgs
[0] = const_cast<rtl_uString
**>(
359 &reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *>(pMemberType
)->pMemberName
);
361 uno_Any
* pInvokExc
= &aInvokExc
;
364 (*m_pReceiver
->pDispatcher
)(
365 m_pReceiver
, m_pFactory
->m_pGetValueTD
,
366 &aInvokRet
, pInvokArgs
, &pInvokExc
);
368 if (pInvokExc
) // getValue() call exception
370 handleInvokExc( *ppException
, pInvokExc
);
371 ::uno_any_destruct( pInvokExc
, nullptr ); // cleanup
373 else // invocation call succeeded
375 if (coerce_construct(
377 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(
378 pMemberType
)->pAttributeTypeRef
,
379 &aInvokRet
, *ppException
))
381 *ppException
= nullptr; // no exceptions be thrown
383 ::uno_any_destruct( &aInvokRet
, nullptr );
387 void AdapterImpl::setValue(
388 const typelib_TypeDescription
* pMemberType
,
389 void * pArgs
[], uno_Any
** ppException
)
392 ::uno_type_any_construct(
393 &aInvokVal
, pArgs
[0],
394 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(
395 pMemberType
)->pAttributeTypeRef
, nullptr );
397 void * pInvokArgs
[2];
398 pInvokArgs
[0] = const_cast<rtl_uString
**>(
399 &reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *>(pMemberType
)->pMemberName
);
400 pInvokArgs
[1] = &aInvokVal
;
402 uno_Any
* pInvokExc
= &aInvokExc
;
405 (*m_pReceiver
->pDispatcher
)(
406 m_pReceiver
, m_pFactory
->m_pSetValueTD
, nullptr, pInvokArgs
, &pInvokExc
);
408 if (pInvokExc
) // setValue() call exception
410 handleInvokExc( *ppException
, pInvokExc
);
411 ::uno_any_destruct( pInvokExc
, nullptr ); // cleanup
413 else // invocation call succeeded
415 *ppException
= nullptr; // no exceptions be thrown
418 ::uno_any_destruct( &aInvokVal
, nullptr ); // cleanup
421 void AdapterImpl::invoke(
422 const typelib_TypeDescription
* pMemberType
,
423 void * pReturn
, void * pArgs
[], uno_Any
** ppException
)
426 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(pMemberType
)->nParams
;
427 typelib_MethodParameter
* pFormalParams
=
428 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(pMemberType
)->pParams
;
431 uno_Sequence
* pInParamsSeq
= nullptr;
432 ::uno_sequence_construct(
433 &pInParamsSeq
, m_pFactory
->m_pAnySeqTD
, nullptr, nParams
, nullptr );
434 uno_Any
* pInAnys
= reinterpret_cast<uno_Any
*>(pInParamsSeq
->elements
);
435 sal_Int32 nOutParams
= 0;
437 for ( nPos
= nParams
; nPos
--; )
439 typelib_MethodParameter
const & rParam
= pFormalParams
[nPos
];
440 if (rParam
.bIn
) // is in/inout param
442 ::uno_type_any_assign(
443 &pInAnys
[nPos
], pArgs
[nPos
], rParam
.pTypeRef
, nullptr, nullptr );
445 // else: pure out is empty any
451 // out params, out indices
452 uno_Sequence
* pOutIndices
;
453 uno_Sequence
* pOutParams
;
457 void * pInvokArgs
[4];
458 pInvokArgs
[0] = const_cast<rtl_uString
**>(
459 &reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *>(pMemberType
)->pMemberName
);
460 pInvokArgs
[1] = &pInParamsSeq
;
461 pInvokArgs
[2] = &pOutIndices
;
462 pInvokArgs
[3] = &pOutParams
;
464 uno_Any
* pInvokExc
= &aInvokExc
;
467 (*m_pReceiver
->pDispatcher
)(
468 m_pReceiver
, m_pFactory
->m_pInvokMethodTD
,
469 &aInvokRet
, pInvokArgs
, &pInvokExc
);
473 handleInvokExc( *ppException
, pInvokExc
);
474 ::uno_any_destruct( pInvokExc
, nullptr ); // cleanup
476 else // no invocation exception
478 // write changed out params
480 pOutParams
->nElements
== nOutParams
&&
481 pOutIndices
->nElements
== nOutParams
,
482 "### out params lens differ!" );
483 if (pOutParams
->nElements
== nOutParams
&&
484 pOutIndices
->nElements
== nOutParams
)
486 sal_Int16
* pIndices
= reinterpret_cast<sal_Int16
*>(pOutIndices
->elements
);
487 uno_Any
* pOut
= reinterpret_cast<uno_Any
*>(pOutParams
->elements
);
488 for ( nPos
= 0; nPos
< nOutParams
; ++nPos
)
490 sal_Int32 nIndex
= pIndices
[nPos
];
491 OSL_ENSURE( nIndex
< nParams
, "### illegal index!" );
492 typelib_MethodParameter
const & rParam
= pFormalParams
[nIndex
];
494 if (rParam
.bIn
) // is in/inout param
496 succ
= coerce_assign(
497 pArgs
[nIndex
], rParam
.pTypeRef
, &pOut
[nPos
],
502 succ
= coerce_construct(
503 pArgs
[nIndex
], rParam
.pTypeRef
, &pOut
[nPos
],
506 if (! succ
) // cleanup of out params
508 for ( sal_Int32 n
= 0; n
<= nPos
; ++n
)
510 sal_Int32 nIndex2
= pIndices
[n
];
511 OSL_ENSURE( nIndex2
< nParams
, "### illegal index!" );
512 typelib_MethodParameter
const & rParam2
=
513 pFormalParams
[nIndex2
];
514 if (! rParam2
.bIn
) // is pure out param
516 ::uno_type_destructData(
517 pArgs
[nIndex2
], rParam2
.pTypeRef
, nullptr );
522 if (nPos
== pOutIndices
->nElements
)
524 // out param copy ok; write return value
525 if (coerce_construct(
527 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(
528 pMemberType
)->pReturnTypeRef
,
529 &aInvokRet
, *ppException
))
531 *ppException
= nullptr; // no exception
537 // set runtime exception
538 constructRuntimeException(
540 "out params lengths differ after invocation call!" );
542 // cleanup invok out params
543 ::uno_destructData( &pOutIndices
, m_pFactory
->m_pShortSeqTD
, nullptr );
544 ::uno_destructData( &pOutParams
, m_pFactory
->m_pAnySeqTD
, nullptr );
545 // cleanup invok return value
546 ::uno_any_destruct( &aInvokRet
, nullptr );
548 // cleanup constructed in params
549 ::uno_destructData( &pInParamsSeq
, m_pFactory
->m_pAnySeqTD
, nullptr );
555 static void SAL_CALL
adapter_acquire( uno_Interface
* pUnoI
)
557 static_cast< InterfaceAdapterImpl
* >( pUnoI
)->m_pAdapter
->acquire();
560 static void SAL_CALL
adapter_release( uno_Interface
* pUnoI
)
562 static_cast< InterfaceAdapterImpl
* >( pUnoI
)->m_pAdapter
->release();
565 static void SAL_CALL
adapter_dispatch(
566 uno_Interface
* pUnoI
, const typelib_TypeDescription
* pMemberType
,
567 void * pReturn
, void * pArgs
[], uno_Any
** ppException
)
569 // query to emulated interface
570 switch (reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *>(pMemberType
)->nPosition
)
572 case 0: // queryInterface()
575 static_cast< InterfaceAdapterImpl
* >( pUnoI
)->m_pAdapter
;
576 *ppException
= nullptr; // no exc
577 typelib_TypeDescriptionReference
* pDemanded
=
578 *static_cast<typelib_TypeDescriptionReference
**>(pArgs
[0]);
579 // pInterfaces[0] is XInterface
580 for ( sal_Int32 nPos
= 0; nPos
< that
->m_nInterfaces
; ++nPos
)
582 typelib_InterfaceTypeDescription
* pTD
=
583 that
->m_pInterfaces
[nPos
].m_pTypeDescr
;
586 if (type_equals( pTD
->aBase
.pWeakRef
, pDemanded
))
588 uno_Interface
* pUnoI2
= &that
->m_pInterfaces
[nPos
];
590 static_cast<uno_Any
*>(pReturn
), &pUnoI2
,
591 &pTD
->aBase
, nullptr );
594 pTD
= pTD
->pBaseTypeDescription
;
597 ::uno_any_construct( static_cast<uno_Any
*>(pReturn
), nullptr, nullptr, nullptr ); // clear()
601 *ppException
= nullptr; // no exc
602 adapter_acquire( pUnoI
);
605 *ppException
= nullptr; // no exc
606 adapter_release( pUnoI
);
612 static_cast< InterfaceAdapterImpl
* >( pUnoI
)->m_pAdapter
;
613 if (pMemberType
->eTypeClass
== typelib_TypeClass_INTERFACE_METHOD
)
615 that
->invoke( pMemberType
, pReturn
, pArgs
, ppException
);
620 that
->getValue( pMemberType
, pReturn
, ppException
);
622 that
->setValue( pMemberType
, pArgs
, ppException
);
629 AdapterImpl::AdapterImpl(
630 void * key
, Reference
< script::XInvocation
> const & xReceiver
,
631 const Sequence
< Type
> & rTypes
,
632 FactoryImpl
* pFactory
)
634 m_pFactory( pFactory
),
638 m_nInterfaces
= rTypes
.getLength();
639 m_pInterfaces
= new InterfaceAdapterImpl
[ rTypes
.getLength() ];
640 const Type
* pTypes
= rTypes
.getConstArray();
641 for ( sal_Int32 nPos
= rTypes
.getLength(); nPos
--; )
643 InterfaceAdapterImpl
* pInterface
= &m_pInterfaces
[nPos
];
644 pInterface
->acquire
= adapter_acquire
;
645 pInterface
->release
= adapter_release
;
646 pInterface
->pDispatcher
= adapter_dispatch
;
647 pInterface
->m_pAdapter
= this;
648 pInterface
->m_pTypeDescr
= nullptr;
649 pTypes
[nPos
].getDescription(
650 reinterpret_cast<typelib_TypeDescription
**>(&pInterface
->m_pTypeDescr
) );
651 OSL_ASSERT( pInterface
->m_pTypeDescr
);
652 if (! pInterface
->m_pTypeDescr
)
654 for ( sal_Int32 n
= 0; n
< nPos
; ++n
)
656 ::typelib_typedescription_release(
657 &m_pInterfaces
[ n
].m_pTypeDescr
->aBase
);
659 delete [] m_pInterfaces
;
660 throw RuntimeException(
661 "cannot retrieve all interface type infos!" );
666 m_pReceiver
= static_cast<uno_Interface
*>(m_pFactory
->m_aCpp2Uno
.mapInterface(
667 xReceiver
.get(), cppu::UnoType
<decltype(xReceiver
)>::get() ));
668 OSL_ASSERT( nullptr != m_pReceiver
);
671 throw RuntimeException( "cannot map receiver!" );
674 m_pFactory
->acquire();
678 FactoryImpl::FactoryImpl( Reference
< XComponentContext
> const & xContext
)
679 : m_pInvokMethodTD( nullptr ),
680 m_pSetValueTD( nullptr ),
681 m_pGetValueTD( nullptr ),
682 m_pAnySeqTD( nullptr ),
683 m_pShortSeqTD( nullptr ),
684 m_pConvertToTD( nullptr )
687 OUString aCppEnvTypeName
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
688 OUString aUnoEnvTypeName
= UNO_LB_UNO
;
689 m_aUno2Cpp
= Mapping( aUnoEnvTypeName
, aCppEnvTypeName
);
690 m_aCpp2Uno
= Mapping( aCppEnvTypeName
, aUnoEnvTypeName
);
692 m_aUno2Cpp
.is() && m_aCpp2Uno
.is(), "### no uno / C++ mappings!" );
695 Reference
< script::XTypeConverter
> xConverter(
696 xContext
->getServiceManager()->createInstanceWithContext(
697 "com.sun.star.script.Converter",
700 m_pConverter
= static_cast<uno_Interface
*>(m_aCpp2Uno
.mapInterface(
701 xConverter
.get(), cppu::UnoType
<decltype(xConverter
)>::get() ));
702 OSL_ASSERT( nullptr != m_pConverter
);
706 Type
const & rAnySeqType
= cppu::UnoType
<Sequence
< Any
>>::get();
707 rAnySeqType
.getDescription( &m_pAnySeqTD
);
709 const Type
& rShortSeqType
=
710 cppu::UnoType
<Sequence
< sal_Int16
>>::get();
711 rShortSeqType
.getDescription( &m_pShortSeqTD
);
712 // script.XInvocation
713 typelib_TypeDescription
* pTD
= nullptr;
714 const Type
& rInvType
= cppu::UnoType
<script::XInvocation
>::get();
715 TYPELIB_DANGER_GET( &pTD
, rInvType
.getTypeLibType() );
716 typelib_InterfaceTypeDescription
* pITD
;
717 pITD
= reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTD
);
718 if( ! pITD
->aBase
.bComplete
)
719 typelib_typedescription_complete( &pTD
);
720 ::typelib_typedescriptionreference_getDescription(
721 &m_pInvokMethodTD
, pITD
->ppMembers
[ 1 ] ); // invoke()
722 ::typelib_typedescriptionreference_getDescription(
723 &m_pSetValueTD
, pITD
->ppMembers
[ 2 ] ); // setValue()
724 ::typelib_typedescriptionreference_getDescription(
725 &m_pGetValueTD
, pITD
->ppMembers
[ 3 ] ); // getValue()
726 // script.XTypeConverter
727 const Type
& rTCType
=
728 cppu::UnoType
<script::XTypeConverter
>::get();
729 TYPELIB_DANGER_GET( &pTD
, rTCType
.getTypeLibType() );
730 pITD
= reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTD
);
731 ::typelib_typedescriptionreference_getDescription(
732 &m_pConvertToTD
, pITD
->ppMembers
[ 0 ] ); // convertTo()
733 TYPELIB_DANGER_RELEASE( pTD
);
735 if (!m_pInvokMethodTD
|| !m_pSetValueTD
|| !m_pGetValueTD
||
737 !m_pAnySeqTD
|| !m_pShortSeqTD
)
739 throw RuntimeException( "missing type descriptions!" );
743 FactoryImpl::~FactoryImpl()
745 ::typelib_typedescription_release( m_pInvokMethodTD
);
746 ::typelib_typedescription_release( m_pSetValueTD
);
747 ::typelib_typedescription_release( m_pGetValueTD
);
748 ::typelib_typedescription_release( m_pAnySeqTD
);
749 ::typelib_typedescription_release( m_pShortSeqTD
);
750 ::typelib_typedescription_release( m_pConvertToTD
);
752 (*m_pConverter
->release
)( m_pConverter
);
754 #if OSL_DEBUG_LEVEL > 0
755 assert(m_receiver2adapters
.empty() && "still adapters out there!?");
760 static inline AdapterImpl
* lookup_adapter(
761 t_ptr_set
** pp_adapter_set
,
762 t_ptr_map
& map
, void * key
, Sequence
< Type
> const & rTypes
)
764 t_ptr_set
& adapters_set
= map
[ key
];
765 *pp_adapter_set
= &adapters_set
;
766 if (adapters_set
.empty())
767 return nullptr; // shortcut
768 // find matching adapter
769 Type
const * pTypes
= rTypes
.getConstArray();
770 sal_Int32 nTypes
= rTypes
.getLength();
771 t_ptr_set::const_iterator
iPos( adapters_set
.begin() );
772 t_ptr_set::const_iterator
const iEnd( adapters_set
.end() );
775 AdapterImpl
* that
= static_cast< AdapterImpl
* >( *iPos
);
776 // iterate through all types if that is a matching adapter
778 for ( nPosTypes
= nTypes
; nPosTypes
--; )
780 Type
const & rType
= pTypes
[ nPosTypes
];
781 // find in adapter's type list
783 for ( nPos
= that
->m_nInterfaces
; nPos
--; )
785 if (::typelib_typedescriptionreference_isAssignableFrom(
786 rType
.getTypeLibType(),
787 that
->m_pInterfaces
[ nPos
].m_pTypeDescr
->aBase
.pWeakRef
))
793 if (nPos
< 0) // type not found => next adapter
796 if (nPosTypes
< 0) // all types found
803 // XInvocationAdapterFactory2 impl
805 Reference
< XInterface
> FactoryImpl::createAdapter(
806 const Reference
< script::XInvocation
> & xReceiver
,
807 const Sequence
< Type
> & rTypes
)
809 Reference
< XInterface
> xRet
;
810 if (xReceiver
.is() && rTypes
.getLength())
812 t_ptr_set
* adapter_set
;
814 Reference
< XInterface
> xKey( xReceiver
, UNO_QUERY
);
816 ClearableMutexGuard
guard( m_mutex
);
817 that
= lookup_adapter(
818 &adapter_set
, m_receiver2adapters
, xKey
.get(), rTypes
);
819 if (nullptr == that
) // no entry
822 // create adapter; already acquired: m_nRef == 1
824 new AdapterImpl( xKey
.get(), xReceiver
, rTypes
, this );
826 ClearableMutexGuard
guard2( m_mutex
);
827 that
= lookup_adapter(
828 &adapter_set
, m_receiver2adapters
, xKey
.get(), rTypes
);
829 if (nullptr == that
) // again no entry
831 pair
< t_ptr_set::iterator
, bool > i(adapter_set
->insert(pNew
));
834 "set already contains " << *(i
.first
) << " != " << pNew
);
841 delete pNew
; // has never been inserted
844 else // found adapter
849 // map one interface to C++
850 uno_Interface
* pUnoI
= &that
->m_pInterfaces
[ 0 ];
851 m_aUno2Cpp
.mapInterface(
852 reinterpret_cast<void **>(&xRet
), pUnoI
, cppu::UnoType
<decltype(xRet
)>::get() );
854 OSL_ASSERT( xRet
.is() );
857 throw RuntimeException( "mapping UNO to C++ failed!" );
862 // XInvocationAdapterFactory impl
864 Reference
< XInterface
> FactoryImpl::createAdapter(
865 const Reference
< script::XInvocation
> & xReceiver
, const Type
& rType
)
867 return createAdapter( xReceiver
, Sequence
< Type
>( &rType
, 1 ) );
872 OUString
FactoryImpl::getImplementationName()
874 return invadp_getImplementationName();
877 sal_Bool
FactoryImpl::supportsService( const OUString
& rServiceName
)
879 return cppu::supportsService(this, rServiceName
);
882 Sequence
< OUString
> FactoryImpl::getSupportedServiceNames()
884 return invadp_getSupportedServiceNames();
887 /// @throws Exception
888 static Reference
< XInterface
> SAL_CALL
FactoryImpl_create(
889 const Reference
< XComponentContext
> & xContext
)
891 return static_cast<cppu::OWeakObject
*>(new FactoryImpl( xContext
));
897 static const struct ::cppu::ImplementationEntry g_entries
[] =
900 ::stoc_invadp::FactoryImpl_create
,
901 ::stoc_invadp::invadp_getImplementationName
,
902 ::stoc_invadp::invadp_getSupportedServiceNames
,
903 ::cppu::createOneInstanceComponentFactory
,
906 { nullptr, nullptr, nullptr, nullptr, nullptr, 0 }
909 extern "C" SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
invocadapt_component_getFactory(
910 const sal_Char
* pImplName
, void * pServiceManager
, void * pRegistryKey
)
912 return ::cppu::component_getFactoryHelper(
913 pImplName
, pServiceManager
, pRegistryKey
, g_entries
);
916 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */