LibreOffice Module stoc (master) 1
iafactory.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
21#include <osl/diagnose.h>
22#include <osl/interlck.h>
23#include <osl/mutex.hxx>
25#include <sal/log.hxx>
26
27#include <uno/dispatcher.h>
28#include <uno/data.h>
29#include <uno/any2.h>
30#include <uno/lbnames.h>
31#include <uno/mapping.hxx>
32
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>
44
45#include <unordered_map>
46#include <vector>
47
48using namespace ::osl;
49using namespace ::com::sun::star;
50using namespace css::uno;
51
52namespace stoc_invadp
53{
54
55
56namespace {
57
58struct hash_ptr
59{
60 size_t operator() ( void * p ) const
61 { return reinterpret_cast<size_t>(p); }
62};
63
64}
65
67typedef std::unordered_map< void *, t_ptr_set, hash_ptr > t_ptr_map;
68
69namespace {
70
71class FactoryImpl
72 : public ::cppu::WeakImplHelper< lang::XServiceInfo,
73 script::XInvocationAdapterFactory,
74 script::XInvocationAdapterFactory2 >
75{
76public:
79 uno_Interface * m_pConverter;
80
87
88 Mutex m_mutex;
90
91 explicit FactoryImpl( Reference< XComponentContext > const & xContext );
92 virtual ~FactoryImpl() override;
93
94 // XServiceInfo
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;
98
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;
106};
107struct AdapterImpl;
108
109struct InterfaceAdapterImpl : public uno_Interface
110{
111 AdapterImpl * m_pAdapter;
112 typelib_InterfaceTypeDescription * m_pTypeDescr;
113};
114
115struct AdapterImpl
116{
117 oslInterlockedCount m_nRef;
118 FactoryImpl * m_pFactory;
119 void * m_key; // map key
120 uno_Interface * m_pReceiver; // XInvocation receiver
121
122 std::vector<InterfaceAdapterImpl> m_vInterfaces;
123
124 // XInvocation calls
125 void getValue(
126 const typelib_TypeDescription * pMemberType,
127 void * pReturn, uno_Any ** ppException );
128 void setValue(
129 const typelib_TypeDescription * pMemberType,
130 void * pArgs[], uno_Any ** ppException );
131 void invoke(
132 const typelib_TypeDescription * pMemberType,
133 void * pReturn, void * pArgs[], uno_Any ** ppException );
134
135 bool coerce_assign(
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 );
141
142 inline void acquire();
143 inline void release();
144 inline ~AdapterImpl();
145 inline AdapterImpl(
146 void * key, Reference< script::XInvocation > const & xReceiver,
147 const Sequence< Type > & rTypes,
148 FactoryImpl * pFactory );
149
150 // Copy assignment is forbidden and not implemented.
151 AdapterImpl (const AdapterImpl &) = delete;
152 AdapterImpl & operator= (const AdapterImpl &) = delete;
153};
154
155}
156
157inline AdapterImpl::~AdapterImpl()
158{
159 for ( size_t nPos = m_vInterfaces.size(); nPos--; )
160 {
161 ::typelib_typedescription_release(
162 &m_vInterfaces[ nPos ].m_pTypeDescr->aBase );
163 }
164
165 (*m_pReceiver->release)( m_pReceiver );
166 m_pFactory->release();
167}
168
169inline void AdapterImpl::acquire()
170{
171 osl_atomic_increment( &m_nRef );
172}
173
174inline void AdapterImpl::release()
175{
176 bool delete_this = false;
177 {
178 MutexGuard guard( m_pFactory->m_mutex );
179 if (! osl_atomic_decrement( &m_nRef ))
180 {
181 t_ptr_map::iterator iFind(
182 m_pFactory->m_receiver2adapters.find( m_key ) );
183 OSL_ASSERT( m_pFactory->m_receiver2adapters.end() != iFind );
184 t_ptr_set & adapter_set = iFind->second;
185 if (adapter_set.erase( this ) != 1) {
186 OSL_ASSERT( false );
187 }
188 if (adapter_set.empty())
189 {
190 m_pFactory->m_receiver2adapters.erase( iFind );
191 }
192 delete_this = true;
193 }
194 }
195 if (delete_this)
196 delete this;
197}
198
199
201 uno_Any * pExc, const OUString & rMsg )
202{
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 );
207}
208
209
210static bool type_equals(
211 typelib_TypeDescriptionReference * pType1,
212 typelib_TypeDescriptionReference * pType2 )
213{
214 return (pType1 == pType2 ||
215 (pType1->pTypeName->length == pType2->pTypeName->length &&
216 0 == ::rtl_ustr_compare(
217 pType1->pTypeName->buffer, pType2->pTypeName->buffer )));
218}
219
220
222 void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
223 uno_Any * pOutExc )
224{
225 if (typelib_TypeClass_ANY == pType->eTypeClass)
226 {
227 ::uno_type_any_assign(
228 static_cast<uno_Any *>(pDest), pSource->pData, pSource->pType, nullptr, nullptr );
229 return true;
230 }
231 if (::uno_type_assignData(
232 pDest, pType, pSource->pData, pSource->pType, nullptr, nullptr, nullptr ))
233 {
234 return true;
235 }
236 else // try type converter
237 {
238 uno_Any ret;
239 void * args[ 2 ];
240 args[ 0 ] = pSource;
241 args[ 1 ] = &pType;
242 uno_Any exc;
243 uno_Any * p_exc = &exc;
244
245 // converTo()
246 (*m_pFactory->m_pConverter->pDispatcher)(
247 m_pFactory->m_pConverter,
248 m_pFactory->m_pConvertToTD, &ret, args, &p_exc );
249
250 if (p_exc) // exception occurred
251 {
252 OSL_ASSERT(
253 p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
255 p_exc->pType ))
256 {
257 // is RuntimeException or derived: rethrow
259 pOutExc, p_exc->pData, p_exc->pType, nullptr );
260 }
261 else
262 {
263 // set runtime exception
265 pOutExc, "type coercion failed: " +
266 static_cast< Exception const * >(
267 p_exc->pData )->Message );
268 }
269 ::uno_any_destruct( p_exc, nullptr );
270 // pOutExc constructed
271 return false;
272 }
273 else
274 {
275 bool succ = ::uno_type_assignData(
276 pDest, pType, ret.pData, ret.pType, nullptr, nullptr, nullptr );
277 ::uno_any_destruct( &ret, nullptr );
278 OSL_ENSURE(
279 succ, "### conversion succeeded, but assignment failed!?" );
280 if (! succ)
281 {
282 // set runtime exception
284 pOutExc,
285 "type coercion failed: "
286 "conversion succeeded, but assignment failed?!" );
287 }
288 return succ;
289 }
290 }
291}
292
293inline bool AdapterImpl::coerce_construct(
294 void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
295 uno_Any * pExc )
296{
297 if (typelib_TypeClass_ANY == pType->eTypeClass)
298 {
299 ::uno_type_copyData( pDest, pSource, pType, nullptr );
300 return true;
301 }
302 if (type_equals( pType, pSource->pType))
303 {
304 ::uno_type_copyData( pDest, pSource->pData, pType, nullptr );
305 return true;
306 }
307 ::uno_type_constructData( pDest, pType );
308 return coerce_assign( pDest, pType, pSource, pExc );
309}
310
311
312static void handleInvokExc( uno_Any * pDest, uno_Any * pSource )
313{
314 OUString const & name =
315 OUString::unacquired( &pSource->pType->pTypeName );
316
317 if ( name == "com.sun.star.reflection.InvocationTargetException" )
318 {
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 );
325 }
326 else // all other exceptions are wrapped to RuntimeException
327 {
328 if (typelib_TypeClass_EXCEPTION == pSource->pType->eTypeClass)
329 {
331 pDest, static_cast<Exception const *>(pSource->pData)->Message );
332 }
333 else
334 {
336 pDest, "no exception has been thrown via invocation?!" );
337 }
338 }
339}
340
341void AdapterImpl::getValue(
342 const typelib_TypeDescription * pMemberType,
343 void * pReturn, uno_Any ** ppException )
344{
345 uno_Any aInvokRet;
346 void * pInvokArgs[1];
347 pInvokArgs[0] = const_cast<rtl_uString **>(
348 &reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->pMemberName);
349 uno_Any aInvokExc;
350 uno_Any * pInvokExc = &aInvokExc;
351
352 // getValue()
353 (*m_pReceiver->pDispatcher)(
354 m_pReceiver, m_pFactory->m_pGetValueTD,
355 &aInvokRet, pInvokArgs, &pInvokExc );
356
357 if (pInvokExc) // getValue() call exception
358 {
359 handleInvokExc( *ppException, pInvokExc );
360 ::uno_any_destruct( pInvokExc, nullptr ); // cleanup
361 }
362 else // invocation call succeeded
363 {
364 if (coerce_construct(
365 pReturn,
366 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
367 pMemberType)->pAttributeTypeRef,
368 &aInvokRet, *ppException ))
369 {
370 *ppException = nullptr; // no exceptions be thrown
371 }
372 ::uno_any_destruct( &aInvokRet, nullptr );
373 }
374}
375
376void AdapterImpl::setValue(
377 const typelib_TypeDescription * pMemberType,
378 void * pArgs[], uno_Any ** ppException )
379{
380 uno_Any aInvokVal;
381 ::uno_type_any_construct(
382 &aInvokVal, pArgs[0],
383 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
384 pMemberType)->pAttributeTypeRef, nullptr );
385
386 void * pInvokArgs[2];
387 pInvokArgs[0] = const_cast<rtl_uString **>(
388 &reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->pMemberName);
389 pInvokArgs[1] = &aInvokVal;
390 uno_Any aInvokExc;
391 uno_Any * pInvokExc = &aInvokExc;
392
393 // setValue()
394 (*m_pReceiver->pDispatcher)(
395 m_pReceiver, m_pFactory->m_pSetValueTD, nullptr, pInvokArgs, &pInvokExc );
396
397 if (pInvokExc) // setValue() call exception
398 {
399 handleInvokExc( *ppException, pInvokExc );
400 ::uno_any_destruct( pInvokExc, nullptr ); // cleanup
401 }
402 else // invocation call succeeded
403 {
404 *ppException = nullptr; // no exceptions be thrown
405 }
406
407 ::uno_any_destruct( &aInvokVal, nullptr ); // cleanup
408}
409
410void AdapterImpl::invoke(
411 const typelib_TypeDescription * pMemberType,
412 void * pReturn, void * pArgs[], uno_Any ** ppException )
413{
414 sal_Int32 nParams =
415 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType)->nParams;
416 typelib_MethodParameter * pFormalParams =
417 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType)->pParams;
418
419 // in params
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;
425 sal_Int32 nPos;
426 for ( nPos = nParams; nPos--; )
427 {
428 typelib_MethodParameter const & rParam = pFormalParams[nPos];
429 if (rParam.bIn) // is in/inout param
430 {
431 ::uno_type_any_assign(
432 &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef, nullptr, nullptr );
433 }
434 // else: pure out is empty any
435
436 if (rParam.bOut)
437 ++nOutParams;
438 }
439
440 // out params, out indices
441 uno_Sequence * pOutIndices;
442 uno_Sequence * pOutParams;
443 // return value
444 uno_Any aInvokRet;
445 // perform call
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;
452 uno_Any aInvokExc;
453 uno_Any * pInvokExc = &aInvokExc;
454
455 // invoke() call
456 (*m_pReceiver->pDispatcher)(
457 m_pReceiver, m_pFactory->m_pInvokMethodTD,
458 &aInvokRet, pInvokArgs, &pInvokExc );
459
460 if (pInvokExc)
461 {
462 handleInvokExc( *ppException, pInvokExc );
463 ::uno_any_destruct( pInvokExc, nullptr ); // cleanup
464 }
465 else // no invocation exception
466 {
467 // write changed out params
468 OSL_ENSURE(
469 pOutParams->nElements == nOutParams &&
470 pOutIndices->nElements == nOutParams,
471 "### out params lens differ!" );
472 if (pOutParams->nElements == nOutParams &&
473 pOutIndices->nElements == nOutParams)
474 {
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 )
478 {
479 sal_Int32 nIndex = pIndices[nPos];
480 OSL_ENSURE( nIndex < nParams, "### illegal index!" );
481 typelib_MethodParameter const & rParam = pFormalParams[nIndex];
482 bool succ;
483 if (rParam.bIn) // is in/inout param
484 {
485 succ = coerce_assign(
486 pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
487 *ppException );
488 }
489 else // pure out
490 {
491 succ = coerce_construct(
492 pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
493 *ppException );
494 }
495 if (! succ) // cleanup of out params
496 {
497 for ( sal_Int32 n = 0; n <= nPos; ++n )
498 {
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
504 {
505 ::uno_type_destructData(
506 pArgs[nIndex2], rParam2.pTypeRef, nullptr );
507 }
508 }
509 }
510 }
511 if (nPos == pOutIndices->nElements)
512 {
513 // out param copy ok; write return value
514 if (coerce_construct(
515 pReturn,
516 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(
517 pMemberType)->pReturnTypeRef,
518 &aInvokRet, *ppException ))
519 {
520 *ppException = nullptr; // no exception
521 }
522 }
523 }
524 else
525 {
526 // set runtime exception
528 *ppException,
529 "out params lengths differ after invocation call!" );
530 }
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 );
536 }
537 // cleanup constructed in params
538 ::uno_destructData( &pInParamsSeq, m_pFactory->m_pAnySeqTD, nullptr );
539}
540
541extern "C"
542{
543
544static void adapter_acquire( uno_Interface * pUnoI )
545{
546 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire();
547}
548
549static void adapter_release( uno_Interface * pUnoI )
550{
551 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release();
552}
553
555 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType,
556 void * pReturn, void * pArgs[], uno_Any ** ppException )
557{
558 // query to emulated interface
559 switch (reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberType)->nPosition)
560 {
561 case 0: // queryInterface()
562 {
563 AdapterImpl * that =
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 )
570 {
571 typelib_InterfaceTypeDescription * pTD =
572 that->m_vInterfaces[nPos].m_pTypeDescr;
573 while (pTD)
574 {
575 if (type_equals( pTD->aBase.pWeakRef, pDemanded ))
576 {
577 uno_Interface * pUnoI2 = &that->m_vInterfaces[nPos];
578 ::uno_any_construct(
579 static_cast<uno_Any *>(pReturn), &pUnoI2,
580 &pTD->aBase, nullptr );
581 return;
582 }
583 pTD = pTD->pBaseTypeDescription;
584 }
585 }
586 ::uno_any_construct( static_cast<uno_Any *>(pReturn), nullptr, nullptr, nullptr ); // clear()
587 break;
588 }
589 case 1: // acquire()
590 *ppException = nullptr; // no exc
591 adapter_acquire( pUnoI );
592 break;
593 case 2: // release()
594 *ppException = nullptr; // no exc
595 adapter_release( pUnoI );
596 break;
597
598 default:
599 {
600 AdapterImpl * that =
601 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
602 if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
603 {
604 that->invoke( pMemberType, pReturn, pArgs, ppException );
605 }
606 else // attribute
607 {
608 if (pReturn)
609 that->getValue( pMemberType, pReturn, ppException );
610 else
611 that->setValue( pMemberType, pArgs, ppException );
612 }
613 }
614 }
615}
616}
617
618AdapterImpl::AdapterImpl(
619 void * key, Reference< script::XInvocation > const & xReceiver,
620 const Sequence< Type > & rTypes,
621 FactoryImpl * pFactory )
622 : m_nRef( 1 ),
623 m_pFactory( pFactory ),
624 m_key( key ),
625 m_vInterfaces( rTypes.getLength() )
626{
627 // init adapters
628 const Type * pTypes = rTypes.getConstArray();
629 for ( sal_Int32 nPos = rTypes.getLength(); nPos--; )
630 {
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)
641 {
642 for ( sal_Int32 n = 0; n < nPos; ++n )
643 {
644 ::typelib_typedescription_release(
645 &m_vInterfaces[ n ].m_pTypeDescr->aBase );
646 }
647 throw RuntimeException(
648 "cannot retrieve all interface type infos!" );
649 }
650 }
651
652 // map receiver
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 );
656 if (! m_pReceiver)
657 {
658 throw RuntimeException( "cannot map receiver!" );
659 }
660
661 m_pFactory->acquire();
662}
663
664
665FactoryImpl::FactoryImpl( Reference< XComponentContext > const & xContext )
666 : m_aUno2Cpp(Mapping( UNO_LB_UNO, CPPU_CURRENT_LANGUAGE_BINDING_NAME )),
667 m_aCpp2Uno(Mapping( CPPU_CURRENT_LANGUAGE_BINDING_NAME, UNO_LB_UNO)),
668 m_pInvokMethodTD( nullptr ),
669 m_pSetValueTD( nullptr ),
670 m_pGetValueTD( nullptr ),
671 m_pAnySeqTD( nullptr ),
672 m_pShortSeqTD( nullptr ),
673 m_pConvertToTD( nullptr )
674{
675 // C++/UNO bridge
676 OSL_ENSURE(
677 m_aUno2Cpp.is() && m_aCpp2Uno.is(), "### no uno / C++ mappings!" );
678
679 // type converter
680 Reference< script::XTypeConverter > xConverter(
681 xContext->getServiceManager()->createInstanceWithContext(
682 "com.sun.star.script.Converter",
683 xContext ),
684 UNO_QUERY_THROW );
685 m_pConverter = static_cast<uno_Interface *>(m_aCpp2Uno.mapInterface(
686 xConverter.get(), cppu::UnoType<decltype(xConverter)>::get() ));
687 OSL_ASSERT( nullptr != m_pConverter );
688
689 // some type info:
690 // sequence< any >
691 Type const & rAnySeqType = cppu::UnoType<Sequence< Any >>::get();
692 rAnySeqType.getDescription( &m_pAnySeqTD );
693 // sequence< short >
694 const Type & rShortSeqType =
696 rShortSeqType.getDescription( &m_pShortSeqTD );
697 // script.XInvocation
698 typelib_TypeDescription * pTD = nullptr;
700 TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() );
701 typelib_InterfaceTypeDescription * pITD;
702 pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
703 if( ! pITD->aBase.bComplete )
705 ::typelib_typedescriptionreference_getDescription(
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 =
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 );
719
723 {
724 throw RuntimeException( "missing type descriptions!" );
725 }
726}
727
728FactoryImpl::~FactoryImpl()
729{
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 );
736
737 (*m_pConverter->release)( m_pConverter );
738
739#if OSL_DEBUG_LEVEL > 0
740 assert(m_receiver2adapters.empty() && "still adapters out there!?");
741#endif
742}
743
744
745static AdapterImpl * lookup_adapter(
746 t_ptr_set ** pp_adapter_set,
747 t_ptr_map & map, void * key, Sequence< Type > const & rTypes )
748{
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)
757 {
758 AdapterImpl * that = static_cast< AdapterImpl * >( rpAdapter );
759 // iterate through all types if that is a matching adapter
760 sal_Int32 nPosTypes;
761 for ( nPosTypes = nTypes; nPosTypes--; )
762 {
763 Type const & rType = pTypes[ nPosTypes ];
764 // find in adapter's type list
765 sal_Int32 nPos;
766 for ( nPos = that->m_vInterfaces.size(); nPos--; )
767 {
768 if (::typelib_typedescriptionreference_isAssignableFrom(
769 rType.getTypeLibType(),
770 that->m_vInterfaces[ nPos ].m_pTypeDescr->aBase.pWeakRef ))
771 {
772 // found
773 break;
774 }
775 }
776 if (nPos < 0) // type not found => next adapter
777 break;
778 }
779 if (nPosTypes < 0) // all types found
780 return that;
781 }
782 return nullptr;
783}
784
785// XInvocationAdapterFactory2 impl
786
787Reference< XInterface > FactoryImpl::createAdapter(
788 const Reference< script::XInvocation > & xReceiver,
789 const Sequence< Type > & rTypes )
790{
791 Reference< XInterface > xRet;
792 if (xReceiver.is() && rTypes.hasElements())
793 {
794 t_ptr_set * adapter_set;
795 AdapterImpl * that;
796 Reference< XInterface > xKey( xReceiver, UNO_QUERY );
797 {
798 ClearableMutexGuard guard( m_mutex );
799 that = lookup_adapter(
800 &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
801 if (nullptr == that) // no entry
802 {
803 guard.clear();
804 // create adapter; already acquired: m_nRef == 1
805 AdapterImpl * pNew =
806 new AdapterImpl( xKey.get(), xReceiver, rTypes, this );
807 // lookup again
808 ClearableMutexGuard guard2( m_mutex );
809 that = lookup_adapter(
810 &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
811 if (nullptr == that) // again no entry
812 {
813 std::pair< t_ptr_set::const_iterator, bool > i(adapter_set->insert(pNew));
815 !i.second, "stoc",
816 "set already contains " << *(i.first) << " != " << pNew);
817 that = pNew;
818 }
819 else
820 {
821 that->acquire();
822 guard2.clear();
823 delete pNew; // has never been inserted
824 }
825 }
826 else // found adapter
827 {
828 that->acquire();
829 }
830 }
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() );
835 that->release();
836 OSL_ASSERT( xRet.is() );
837 if (! xRet.is())
838 {
839 throw RuntimeException( "mapping UNO to C++ failed!" );
840 }
841 }
842 return xRet;
843}
844// XInvocationAdapterFactory impl
845
846Reference< XInterface > FactoryImpl::createAdapter(
847 const Reference< script::XInvocation > & xReceiver, const Type & rType )
848{
849 return createAdapter( xReceiver, Sequence< Type >( &rType, 1 ) );
850}
851
852// XServiceInfo
853
854OUString FactoryImpl::getImplementationName()
855{
856 return "com.sun.star.comp.stoc.InvocationAdapterFactory";
857}
858
859sal_Bool FactoryImpl::supportsService( const OUString & rServiceName )
860{
861 return cppu::supportsService(this, rServiceName);
862}
863
864Sequence< OUString > FactoryImpl::getSupportedServiceNames()
865{
866 return { "com.sun.star.script.InvocationAdapterFactory" };
867}
868
869}
870
871
872extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
874 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
875{
876 return cppu::acquire(new stoc_invadp::FactoryImpl(context));
877}
878
879
880
881/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SAL_CALL uno_type_any_construct(uno_Any *pDest, void *pSource, typelib_TypeDescriptionReference *pType, uno_AcquireFunc acquire) SAL_THROW_EXTERN_C()
css::uno::Type const & get()
bool empty() const
Reference< XTypeConverter > xConverter
const char * name
AdapterImpl * m_pAdapter
Definition: iafactory.cxx:111
Mapping m_aUno2Cpp
Definition: iafactory.cxx:77
typelib_TypeDescription * m_pAnySeqTD
Definition: iafactory.cxx:84
oslInterlockedCount m_nRef
Definition: iafactory.cxx:117
FactoryImpl * m_pFactory
Definition: iafactory.cxx:118
Mutex m_mutex
Definition: iafactory.cxx:88
Mapping m_aCpp2Uno
Definition: iafactory.cxx:78
t_ptr_map m_receiver2adapters
Definition: iafactory.cxx:89
typelib_InterfaceTypeDescription * m_pTypeDescr
Definition: iafactory.cxx:112
std::vector< InterfaceAdapterImpl > m_vInterfaces
Definition: iafactory.cxx:122
typelib_TypeDescription * m_pInvokMethodTD
Definition: iafactory.cxx:81
uno_Interface * m_pConverter
Definition: iafactory.cxx:79
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * stoc_invocation_adapter_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Definition: iafactory.cxx:873
typelib_TypeDescription * m_pSetValueTD
Definition: iafactory.cxx:82
typelib_TypeDescription * m_pShortSeqTD
Definition: iafactory.cxx:85
uno_Interface * m_pReceiver
Definition: iafactory.cxx:120
typelib_TypeDescription * m_pConvertToTD
Definition: iafactory.cxx:86
void * m_key
Definition: iafactory.cxx:119
typelib_TypeDescription * m_pGetValueTD
Definition: iafactory.cxx:83
sal_Int32 nIndex
Definition: invocation.cxx:697
void * p
sal_Int64 n
sal_uInt16 nPos
#define SAL_WARN_IF(condition, area, stream)
struct _typelib_TypeDescription typelib_TypeDescription
struct _uno_Any uno_Any
double getLength(const B2DPolygon &rCandidate)
@ Exception
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
Type
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
css::beans::Optional< css::uno::Any > getValue(std::u16string_view id)
args
bool coerce_assign(void *pDest, typelib_TypeDescription *pTD, const css::uno::Any &rSource, IdlReflectionServiceImpl *pRefl)
Definition: base.hxx:363
static void constructRuntimeException(uno_Any *pExc, const OUString &rMsg)
Definition: iafactory.cxx:200
static AdapterImpl * lookup_adapter(t_ptr_set **pp_adapter_set, t_ptr_map &map, void *key, Sequence< Type > const &rTypes)
Definition: iafactory.cxx:745
static void adapter_dispatch(uno_Interface *pUnoI, const typelib_TypeDescription *pMemberType, void *pReturn, void *pArgs[], uno_Any **ppException)
Definition: iafactory.cxx:554
std::unordered_map< void *, t_ptr_set, hash_ptr > t_ptr_map
Definition: iafactory.cxx:67
static void handleInvokExc(uno_Any *pDest, uno_Any *pSource)
Definition: iafactory.cxx:312
o3tl::sorted_vector< void * > t_ptr_set
Definition: iafactory.cxx:66
static bool type_equals(typelib_TypeDescriptionReference *pType1, typelib_TypeDescriptionReference *pType2)
Definition: iafactory.cxx:210
static void adapter_acquire(uno_Interface *pUnoI)
Definition: iafactory.cxx:544
static void adapter_release(uno_Interface *pUnoI)
Definition: iafactory.cxx:549
def invoke(object, methodname, argTuple)
RegError REGISTRY_CALLTYPE setValue(RegKeyHandle hKey, rtl_uString *keyName, RegValueType valueType, RegValue pData, sal_uInt32 valueSize)
std::map< OUString, rtl::Reference< Entity > > map
sal_Bool SAL_CALL typelib_typedescription_complete(typelib_TypeDescription **ppTypeDescr) SAL_THROW_EXTERN_C()
sal_Bool SAL_CALL typelib_typedescriptionreference_isAssignableFrom(typelib_TypeDescriptionReference *pAssignable, typelib_TypeDescriptionReference *pFrom) SAL_THROW_EXTERN_C()
unsigned char sal_Bool
oslFileHandle & pOut