Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / stoc / source / invocation_adapterfactory / iafactory.cxx
blobb7b3620a5d61b8cda123aadc1d9cdea8c4d29146
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 <sal/log.hxx>
26 #include <uno/dispatcher.h>
27 #include <uno/data.h>
28 #include <uno/any2.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;
59 namespace stoc_invadp
62 static Sequence< OUString > invadp_getSupportedServiceNames()
64 Sequence< OUString > seqNames { "com.sun.star.script.InvocationAdapterFactory" };
65 return seqNames;
68 static OUString invadp_getImplementationName()
70 return OUString(IMPLNAME);
73 struct hash_ptr
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;
82 class FactoryImpl
83 : public ::cppu::WeakImplHelper< lang::XServiceInfo,
84 script::XInvocationAdapterFactory,
85 script::XInvocationAdapterFactory2 >
87 public:
88 Mapping m_aUno2Cpp;
89 Mapping m_aCpp2Uno;
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;
99 Mutex m_mutex;
100 t_ptr_map m_receiver2adapters;
102 explicit FactoryImpl( Reference< XComponentContext > const & xContext );
103 virtual ~FactoryImpl() override;
105 // XServiceInfo
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;
118 struct AdapterImpl;
120 struct InterfaceAdapterImpl : public uno_Interface
122 AdapterImpl * m_pAdapter;
123 typelib_InterfaceTypeDescription * m_pTypeDescr;
126 struct AdapterImpl
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;
136 // XInvocation calls
137 void getValue(
138 const typelib_TypeDescription * pMemberType,
139 void * pReturn, uno_Any ** ppException );
140 void setValue(
141 const typelib_TypeDescription * pMemberType,
142 void * pArgs[], uno_Any ** ppException );
143 void invoke(
144 const typelib_TypeDescription * pMemberType,
145 void * pReturn, void * pArgs[], uno_Any ** ppException );
147 bool coerce_assign(
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();
157 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) {
197 OSL_ASSERT( false );
199 if (adapter_set.empty())
201 m_pFactory->m_receiver2adapters.erase( iFind );
203 delete_this = true;
206 if (delete_this)
207 delete this;
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,
234 uno_Any * pOutExc )
236 if (typelib_TypeClass_ANY == pType->eTypeClass)
238 ::uno_type_any_assign(
239 static_cast<uno_Any *>(pDest), pSource->pData, pSource->pType, nullptr, nullptr );
240 return true;
242 if (::uno_type_assignData(
243 pDest, pType, pSource->pData, pSource->pType, nullptr, nullptr, nullptr ))
245 return true;
247 else // try type converter
249 uno_Any ret;
250 void * args[ 2 ];
251 args[ 0 ] = pSource;
252 args[ 1 ] = &pType;
253 uno_Any exc;
254 uno_Any * p_exc = &exc;
256 // converTo()
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
263 OSL_ASSERT(
264 p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
265 if (typelib_typedescriptionreference_isAssignableFrom( cppu::UnoType<RuntimeException>::get().getTypeLibType(),
266 p_exc->pType ))
268 // is RuntimeException or derived: rethrow
269 uno_type_any_construct(
270 pOutExc, p_exc->pData, p_exc->pType, nullptr );
272 else
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
282 return false;
284 else
286 bool succ = ::uno_type_assignData(
287 pDest, pType, ret.pData, ret.pType, nullptr, nullptr, nullptr );
288 ::uno_any_destruct( &ret, nullptr );
289 OSL_ENSURE(
290 succ, "### conversion succeeded, but assignment failed!?" );
291 if (! succ)
293 // set runtime exception
294 constructRuntimeException(
295 pOutExc,
296 "type coercion failed: "
297 "conversion succeeded, but assignment failed?!" );
299 return succ;
304 inline bool AdapterImpl::coerce_construct(
305 void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
306 uno_Any * pExc )
308 if (typelib_TypeClass_ANY == pType->eTypeClass)
310 ::uno_type_copyData( pDest, pSource, pType, nullptr );
311 return true;
313 if (type_equals( pType, pSource->pType))
315 ::uno_type_copyData( pDest, pSource->pData, pType, nullptr );
316 return true;
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 );
344 else
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 )
356 uno_Any aInvokRet;
357 void * pInvokArgs[1];
358 pInvokArgs[0] = const_cast<rtl_uString **>(
359 &reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->pMemberName);
360 uno_Any aInvokExc;
361 uno_Any * pInvokExc = &aInvokExc;
363 // getValue()
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(
376 pReturn,
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 )
391 uno_Any aInvokVal;
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;
401 uno_Any aInvokExc;
402 uno_Any * pInvokExc = &aInvokExc;
404 // setValue()
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 )
425 sal_Int32 nParams =
426 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType)->nParams;
427 typelib_MethodParameter * pFormalParams =
428 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType)->pParams;
430 // in params
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;
436 sal_Int32 nPos;
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
447 if (rParam.bOut)
448 ++nOutParams;
451 // out params, out indices
452 uno_Sequence * pOutIndices;
453 uno_Sequence * pOutParams;
454 // return value
455 uno_Any aInvokRet;
456 // perform call
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;
463 uno_Any aInvokExc;
464 uno_Any * pInvokExc = &aInvokExc;
466 // invoke() call
467 (*m_pReceiver->pDispatcher)(
468 m_pReceiver, m_pFactory->m_pInvokMethodTD,
469 &aInvokRet, pInvokArgs, &pInvokExc );
471 if (pInvokExc)
473 handleInvokExc( *ppException, pInvokExc );
474 ::uno_any_destruct( pInvokExc, nullptr ); // cleanup
476 else // no invocation exception
478 // write changed out params
479 OSL_ENSURE(
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];
493 bool succ;
494 if (rParam.bIn) // is in/inout param
496 succ = coerce_assign(
497 pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
498 *ppException );
500 else // pure out
502 succ = coerce_construct(
503 pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
504 *ppException );
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(
526 pReturn,
527 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(
528 pMemberType)->pReturnTypeRef,
529 &aInvokRet, *ppException ))
531 *ppException = nullptr; // no exception
535 else
537 // set runtime exception
538 constructRuntimeException(
539 *ppException,
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 );
552 extern "C"
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()
574 AdapterImpl * that =
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;
584 while (pTD)
586 if (type_equals( pTD->aBase.pWeakRef, pDemanded ))
588 uno_Interface * pUnoI2 = &that->m_pInterfaces[nPos];
589 ::uno_any_construct(
590 static_cast<uno_Any *>(pReturn), &pUnoI2,
591 &pTD->aBase, nullptr );
592 return;
594 pTD = pTD->pBaseTypeDescription;
597 ::uno_any_construct( static_cast<uno_Any *>(pReturn), nullptr, nullptr, nullptr ); // clear()
598 break;
600 case 1: // acquire()
601 *ppException = nullptr; // no exc
602 adapter_acquire( pUnoI );
603 break;
604 case 2: // release()
605 *ppException = nullptr; // no exc
606 adapter_release( pUnoI );
607 break;
609 default:
611 AdapterImpl * that =
612 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
613 if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
615 that->invoke( pMemberType, pReturn, pArgs, ppException );
617 else // attribute
619 if (pReturn)
620 that->getValue( pMemberType, pReturn, ppException );
621 else
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 )
633 : m_nRef( 1 ),
634 m_pFactory( pFactory ),
635 m_key( key )
637 // init adapters
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!" );
665 // map receiver
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 );
669 if (! 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 )
686 // C++/UNO bridge
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 );
691 OSL_ENSURE(
692 m_aUno2Cpp.is() && m_aCpp2Uno.is(), "### no uno / C++ mappings!" );
694 // type converter
695 Reference< script::XTypeConverter > xConverter(
696 xContext->getServiceManager()->createInstanceWithContext(
697 "com.sun.star.script.Converter",
698 xContext ),
699 UNO_QUERY_THROW );
700 m_pConverter = static_cast<uno_Interface *>(m_aCpp2Uno.mapInterface(
701 xConverter.get(), cppu::UnoType<decltype(xConverter)>::get() ));
702 OSL_ASSERT( nullptr != m_pConverter );
704 // some type info:
705 // sequence< any >
706 Type const & rAnySeqType = cppu::UnoType<Sequence< Any >>::get();
707 rAnySeqType.getDescription( &m_pAnySeqTD );
708 // sequence< short >
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 ||
736 !m_pConvertToTD ||
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!?");
756 #endif
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() );
773 while (iEnd != iPos)
775 AdapterImpl * that = static_cast< AdapterImpl * >( *iPos );
776 // iterate through all types if that is a matching adapter
777 sal_Int32 nPosTypes;
778 for ( nPosTypes = nTypes; nPosTypes--; )
780 Type const & rType = pTypes[ nPosTypes ];
781 // find in adapter's type list
782 sal_Int32 nPos;
783 for ( nPos = that->m_nInterfaces; nPos--; )
785 if (::typelib_typedescriptionreference_isAssignableFrom(
786 rType.getTypeLibType(),
787 that->m_pInterfaces[ nPos ].m_pTypeDescr->aBase.pWeakRef ))
789 // found
790 break;
793 if (nPos < 0) // type not found => next adapter
794 break;
796 if (nPosTypes < 0) // all types found
797 return that;
798 ++iPos;
800 return nullptr;
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;
813 AdapterImpl * that;
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
821 guard.clear();
822 // create adapter; already acquired: m_nRef == 1
823 AdapterImpl * pNew =
824 new AdapterImpl( xKey.get(), xReceiver, rTypes, this );
825 // lookup again
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));
832 SAL_WARN_IF(
833 !i.second, "stoc",
834 "set already contains " << *(i.first) << " != " << pNew);
835 that = pNew;
837 else
839 that->acquire();
840 guard2.clear();
841 delete pNew; // has never been inserted
844 else // found adapter
846 that->acquire();
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() );
853 that->release();
854 OSL_ASSERT( xRet.is() );
855 if (! xRet.is())
857 throw RuntimeException( "mapping UNO to C++ failed!" );
860 return xRet;
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 ) );
870 // XServiceInfo
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,
904 nullptr, 0
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: */