fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / stoc / source / invocation_adapterfactory / iafactory.cxx
blobad7dbecb8125d30218e283bc6122b3030adaa67b
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 <boost/unordered_map.hpp>
22 #include <boost/unordered_set.hpp>
24 #include <osl/diagnose.h>
25 #include <osl/interlck.h>
26 #include <osl/mutex.hxx>
28 #include <uno/dispatcher.h>
29 #include <uno/data.h>
30 #include <uno/any2.h>
31 #include <uno/mapping.hxx>
33 #include <cppuhelper/factory.hxx>
34 #include <cppuhelper/implbase3.hxx>
35 #include <cppuhelper/implementationentry.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 #define SERVICENAME "com.sun.star.script.InvocationAdapterFactory"
50 #define IMPLNAME "com.sun.star.comp.stoc.InvocationAdapterFactory"
53 using namespace ::std;
54 using namespace ::rtl;
55 using namespace ::osl;
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::uno;
59 namespace stoc_invadp
62 static Sequence< OUString > invadp_getSupportedServiceNames()
64 Sequence< OUString > seqNames(1);
65 seqNames.getArray()[0] =
66 OUString(SERVICENAME);
67 return seqNames;
70 static OUString invadp_getImplementationName()
72 return OUString(IMPLNAME);
75 struct hash_ptr
77 inline size_t operator() ( void * p ) const
78 { return (size_t)p; }
80 typedef boost::unordered_set< void *, hash_ptr, equal_to< void * > > t_ptr_set;
81 typedef boost::unordered_map< void *, t_ptr_set, hash_ptr, equal_to< void * > > t_ptr_map;
83 //==============================================================================
84 class FactoryImpl
85 : public ::cppu::WeakImplHelper3< lang::XServiceInfo,
86 script::XInvocationAdapterFactory,
87 script::XInvocationAdapterFactory2 >
89 public:
90 Mapping m_aUno2Cpp;
91 Mapping m_aCpp2Uno;
92 uno_Interface * m_pConverter;
94 typelib_TypeDescription * m_pInvokMethodTD;
95 typelib_TypeDescription * m_pSetValueTD;
96 typelib_TypeDescription * m_pGetValueTD;
97 typelib_TypeDescription * m_pAnySeqTD;
98 typelib_TypeDescription * m_pShortSeqTD;
99 typelib_TypeDescription * m_pConvertToTD;
101 Mutex m_mutex;
102 t_ptr_map m_receiver2adapters;
104 FactoryImpl( Reference< XComponentContext > const & xContext )
105 SAL_THROW( (RuntimeException) );
106 virtual ~FactoryImpl() SAL_THROW(());
108 // XServiceInfo
109 virtual OUString SAL_CALL getImplementationName()
110 throw (RuntimeException);
111 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName )
112 throw (RuntimeException);
113 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
114 throw (RuntimeException);
116 // XInvocationAdapterFactory
117 virtual Reference< XInterface > SAL_CALL createAdapter(
118 const Reference< script::XInvocation > & xReceiver, const Type & rType )
119 throw (RuntimeException);
120 // XInvocationAdapterFactory2
121 virtual Reference< XInterface > SAL_CALL createAdapter(
122 const Reference< script::XInvocation > & xReceiver,
123 const Sequence< Type > & rTypes )
124 throw (RuntimeException);
126 struct AdapterImpl;
127 //==============================================================================
128 struct InterfaceAdapterImpl : public uno_Interface
130 AdapterImpl * m_pAdapter;
131 typelib_InterfaceTypeDescription * m_pTypeDescr;
133 //==============================================================================
134 struct AdapterImpl
136 oslInterlockedCount m_nRef;
137 FactoryImpl * m_pFactory;
138 void * m_key; // map key
139 uno_Interface * m_pReceiver; // XInvocation receiver
141 sal_Int32 m_nInterfaces;
142 InterfaceAdapterImpl * m_pInterfaces;
144 // XInvocation calls
145 void getValue(
146 const typelib_TypeDescription * pMemberType,
147 void * pReturn, uno_Any ** ppException );
148 void setValue(
149 const typelib_TypeDescription * pMemberType,
150 void * pArgs[], uno_Any ** ppException );
151 void invoke(
152 const typelib_TypeDescription * pMemberType,
153 void * pReturn, void * pArgs[], uno_Any ** ppException );
155 bool coerce_assign(
156 void * pDest, typelib_TypeDescriptionReference * pType,
157 uno_Any * pSource, uno_Any * pExc );
158 inline bool coerce_construct(
159 void * pDest, typelib_TypeDescriptionReference * pType,
160 uno_Any * pSource, uno_Any * pExc );
162 inline void acquire()
163 SAL_THROW(());
164 inline void release()
165 SAL_THROW(());
166 inline ~AdapterImpl()
167 SAL_THROW(());
168 inline AdapterImpl(
169 void * key, Reference< script::XInvocation > const & xReceiver,
170 const Sequence< Type > & rTypes,
171 FactoryImpl * pFactory )
172 SAL_THROW( (RuntimeException) );
174 //______________________________________________________________________________
175 inline AdapterImpl::~AdapterImpl()
176 SAL_THROW(())
178 for ( sal_Int32 nPos = m_nInterfaces; nPos--; )
180 ::typelib_typedescription_release(
181 (typelib_TypeDescription *)m_pInterfaces[ nPos ].m_pTypeDescr );
183 delete [] m_pInterfaces;
185 (*m_pReceiver->release)( m_pReceiver );
186 m_pFactory->release();
188 //______________________________________________________________________________
189 inline void AdapterImpl::acquire()
190 SAL_THROW(())
192 osl_atomic_increment( &m_nRef );
194 //______________________________________________________________________________
195 inline void AdapterImpl::release()
196 SAL_THROW(())
198 bool delete_this = false;
200 MutexGuard guard( m_pFactory->m_mutex );
201 if (! osl_atomic_decrement( &m_nRef ))
203 t_ptr_map::iterator iFind(
204 m_pFactory->m_receiver2adapters.find( m_key ) );
205 OSL_ASSERT( m_pFactory->m_receiver2adapters.end() != iFind );
206 t_ptr_set & adapter_set = iFind->second;
207 if (adapter_set.erase( this ) != 1) {
208 OSL_ASSERT( false );
210 if (adapter_set.empty())
212 m_pFactory->m_receiver2adapters.erase( iFind );
214 delete_this = true;
217 if (delete_this)
218 delete this;
221 //------------------------------------------------------------------------------
222 static inline void constructRuntimeException(
223 uno_Any * pExc, const OUString & rMsg )
225 RuntimeException exc( rMsg, Reference< XInterface >() );
226 // no conversion needed due to binary compatibility + no convertible type
227 ::uno_type_any_construct(
228 pExc, &exc, ::getCppuType( &exc ).getTypeLibType(), 0 );
231 //------------------------------------------------------------------------------
232 static inline sal_Bool type_equals(
233 typelib_TypeDescriptionReference * pType1,
234 typelib_TypeDescriptionReference * pType2 )
235 SAL_THROW(())
237 return (pType1 == pType2 ||
238 (pType1->pTypeName->length == pType2->pTypeName->length &&
239 0 == ::rtl_ustr_compare(
240 pType1->pTypeName->buffer, pType2->pTypeName->buffer )));
243 //______________________________________________________________________________
244 bool AdapterImpl::coerce_assign(
245 void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
246 uno_Any * pOutExc )
248 if (typelib_TypeClass_ANY == pType->eTypeClass)
250 ::uno_type_any_assign(
251 (uno_Any *)pDest, pSource->pData, pSource->pType, 0, 0 );
252 return true;
254 if (::uno_type_assignData(
255 pDest, pType, pSource->pData, pSource->pType, 0, 0, 0 ))
257 return true;
259 else // try type converter
261 uno_Any ret;
262 void * args[ 2 ];
263 args[ 0 ] = pSource;
264 args[ 1 ] = &pType;
265 uno_Any exc;
266 uno_Any * p_exc = &exc;
268 // converTo()
269 (*m_pFactory->m_pConverter->pDispatcher)(
270 m_pFactory->m_pConverter,
271 m_pFactory->m_pConvertToTD, &ret, args, &p_exc );
273 if (p_exc) // exception occurred
275 OSL_ASSERT(
276 p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
277 if (typelib_typedescriptionreference_isAssignableFrom(
278 ::getCppuType(
279 (RuntimeException const *) 0 ).getTypeLibType(),
280 p_exc->pType ))
282 // is RuntimeException or derived: rethrow
283 uno_type_any_construct(
284 pOutExc, p_exc->pData, p_exc->pType, 0 );
286 else
288 // set runtime exception
289 constructRuntimeException(
290 pOutExc, "type coercion failed: " +
291 reinterpret_cast< Exception const * >(
292 p_exc->pData )->Message );
294 ::uno_any_destruct( p_exc, 0 );
295 // pOutExc constructed
296 return false;
298 else
300 bool succ = (sal_False != ::uno_type_assignData(
301 pDest, pType, ret.pData, ret.pType, 0, 0, 0 ));
302 ::uno_any_destruct( &ret, 0 );
303 OSL_ENSURE(
304 succ, "### conversion succeeded, but assignment failed!?" );
305 if (! succ)
307 // set runtime exception
308 constructRuntimeException(
309 pOutExc,
310 "type coercion failed: "
311 "conversion succeeded, but assignment failed?!" );
313 return succ;
317 //______________________________________________________________________________
318 inline bool AdapterImpl::coerce_construct(
319 void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
320 uno_Any * pExc )
322 if (typelib_TypeClass_ANY == pType->eTypeClass)
324 ::uno_type_copyData( pDest, pSource, pType, 0 );
325 return true;
327 if (type_equals( pType, pSource->pType))
329 ::uno_type_copyData( pDest, pSource->pData, pType, 0 );
330 return true;
332 ::uno_type_constructData( pDest, pType );
333 return coerce_assign( pDest, pType, pSource, pExc );
336 //------------------------------------------------------------------------------
337 static void handleInvokExc( uno_Any * pDest, uno_Any * pSource )
339 OUString const & name =
340 *reinterpret_cast< OUString const * >( &pSource->pType->pTypeName );
342 if ( name == "com.sun.star.reflection.InvocationTargetException" )
344 // unwrap invocation target exception
345 uno_Any * target_exc =
346 &reinterpret_cast< reflection::InvocationTargetException * >(
347 pSource->pData )->TargetException;
348 ::uno_type_any_construct(
349 pDest, target_exc->pData, target_exc->pType, 0 );
351 else // all other exceptions are wrapped to RuntimeException
353 if (typelib_TypeClass_EXCEPTION == pSource->pType->eTypeClass)
355 constructRuntimeException(
356 pDest, ((Exception const *)pSource->pData)->Message );
358 else
360 constructRuntimeException(
361 pDest, "no exception has been thrown via invocation?!" );
365 //______________________________________________________________________________
366 void AdapterImpl::getValue(
367 const typelib_TypeDescription * pMemberType,
368 void * pReturn, uno_Any ** ppException )
370 uno_Any aInvokRet;
371 void * pInvokArgs[1];
372 pInvokArgs[0] =
373 &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
374 uno_Any aInvokExc;
375 uno_Any * pInvokExc = &aInvokExc;
377 // getValue()
378 (*m_pReceiver->pDispatcher)(
379 m_pReceiver, m_pFactory->m_pGetValueTD,
380 &aInvokRet, pInvokArgs, &pInvokExc );
382 if (pInvokExc) // getValue() call exception
384 handleInvokExc( *ppException, pInvokExc );
385 ::uno_any_destruct( pInvokExc, 0 ); // cleanup
387 else // invocation call succeeded
389 if (coerce_construct(
390 pReturn,
391 ((typelib_InterfaceAttributeTypeDescription *)
392 pMemberType)->pAttributeTypeRef,
393 &aInvokRet, *ppException ))
395 *ppException = 0; // no exceptions be thrown
397 ::uno_any_destruct( &aInvokRet, 0 );
400 //______________________________________________________________________________
401 void AdapterImpl::setValue(
402 const typelib_TypeDescription * pMemberType,
403 void * pArgs[], uno_Any ** ppException )
405 uno_Any aInvokVal;
406 ::uno_type_any_construct(
407 &aInvokVal, pArgs[0],
408 ((typelib_InterfaceAttributeTypeDescription *)
409 pMemberType)->pAttributeTypeRef, 0 );
411 void * pInvokArgs[2];
412 pInvokArgs[0] =
413 &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
414 pInvokArgs[1] = &aInvokVal;
415 uno_Any aInvokExc;
416 uno_Any * pInvokExc = &aInvokExc;
418 // setValue()
419 (*m_pReceiver->pDispatcher)(
420 m_pReceiver, m_pFactory->m_pSetValueTD, 0, pInvokArgs, &pInvokExc );
422 if (pInvokExc) // setValue() call exception
424 handleInvokExc( *ppException, pInvokExc );
425 ::uno_any_destruct( pInvokExc, 0 ); // cleanup
427 else // invocation call succeeded
429 *ppException = 0; // no exceptions be thrown
432 ::uno_any_destruct( &aInvokVal, 0 ); // cleanup
434 //______________________________________________________________________________
435 void AdapterImpl::invoke(
436 const typelib_TypeDescription * pMemberType,
437 void * pReturn, void * pArgs[], uno_Any ** ppException )
439 sal_Int32 nParams =
440 ((typelib_InterfaceMethodTypeDescription *)pMemberType)->nParams;
441 typelib_MethodParameter * pFormalParams =
442 ((typelib_InterfaceMethodTypeDescription *)pMemberType)->pParams;
444 // in params
445 uno_Sequence * pInParamsSeq = 0;
446 ::uno_sequence_construct(
447 &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0, nParams, 0 );
448 uno_Any * pInAnys = (uno_Any *)pInParamsSeq->elements;
449 sal_Int32 nOutParams = 0;
450 sal_Int32 nPos;
451 for ( nPos = nParams; nPos--; )
453 typelib_MethodParameter const & rParam = pFormalParams[nPos];
454 if (rParam.bIn) // is in/inout param
456 ::uno_type_any_assign(
457 &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef, 0, 0 );
459 // else: pure out is empty any
461 if (rParam.bOut)
462 ++nOutParams;
465 // out params, out indices
466 uno_Sequence * pOutIndices;
467 uno_Sequence * pOutParams;
468 // return value
469 uno_Any aInvokRet;
470 // perform call
471 void * pInvokArgs[4];
472 pInvokArgs[0] =
473 &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
474 pInvokArgs[1] = &pInParamsSeq;
475 pInvokArgs[2] = &pOutIndices;
476 pInvokArgs[3] = &pOutParams;
477 uno_Any aInvokExc;
478 uno_Any * pInvokExc = &aInvokExc;
480 // invoke() call
481 (*m_pReceiver->pDispatcher)(
482 m_pReceiver, m_pFactory->m_pInvokMethodTD,
483 &aInvokRet, pInvokArgs, &pInvokExc );
485 if (pInvokExc)
487 handleInvokExc( *ppException, pInvokExc );
488 ::uno_any_destruct( pInvokExc, 0 ); // cleanup
490 else // no invocation exception
492 // write changed out params
493 OSL_ENSURE(
494 pOutParams->nElements == nOutParams &&
495 pOutIndices->nElements == nOutParams,
496 "### out params lens differ!" );
497 if (pOutParams->nElements == nOutParams &&
498 pOutIndices->nElements == nOutParams)
500 sal_Int16 * pIndices = (sal_Int16 *)pOutIndices->elements;
501 uno_Any * pOut = (uno_Any *)pOutParams->elements;
502 for ( nPos = 0; nPos < nOutParams; ++nPos )
504 sal_Int32 nIndex = pIndices[nPos];
505 OSL_ENSURE( nIndex < nParams, "### illegal index!" );
506 typelib_MethodParameter const & rParam = pFormalParams[nIndex];
507 bool succ;
508 if (rParam.bIn) // is in/inout param
510 succ = coerce_assign(
511 pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
512 *ppException );
514 else // pure out
516 succ = coerce_construct(
517 pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
518 *ppException );
520 if (! succ) // cleanup of out params
522 for ( sal_Int32 n = 0; n <= nPos; ++n )
524 sal_Int32 nIndex2 = pIndices[n];
525 OSL_ENSURE( nIndex2 < nParams, "### illegal index!" );
526 typelib_MethodParameter const & rParam2 =
527 pFormalParams[nIndex2];
528 if (! rParam2.bIn) // is pure out param
530 ::uno_type_destructData(
531 pArgs[nIndex2], rParam2.pTypeRef, 0 );
536 if (nPos == pOutIndices->nElements)
538 // out param copy ok; write return value
539 if (coerce_construct(
540 pReturn,
541 ((typelib_InterfaceMethodTypeDescription *)
542 pMemberType)->pReturnTypeRef,
543 &aInvokRet, *ppException ))
545 *ppException = 0; // no exception
549 else
551 // set runtime exception
552 constructRuntimeException(
553 *ppException,
554 "out params lengths differ after invocation call!" );
556 // cleanup invok out params
557 ::uno_destructData( &pOutIndices, m_pFactory->m_pShortSeqTD, 0 );
558 ::uno_destructData( &pOutParams, m_pFactory->m_pAnySeqTD, 0 );
559 // cleanup invok return value
560 ::uno_any_destruct( &aInvokRet, 0 );
562 // cleanup constructed in params
563 ::uno_destructData( &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0 );
566 extern "C"
568 //______________________________________________________________________________
569 static void SAL_CALL adapter_acquire( uno_Interface * pUnoI )
571 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire();
573 //______________________________________________________________________________
574 static void SAL_CALL adapter_release( uno_Interface * pUnoI )
576 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release();
578 //______________________________________________________________________________
579 static void SAL_CALL adapter_dispatch(
580 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType,
581 void * pReturn, void * pArgs[], uno_Any ** ppException )
583 // query to emulated interface
584 switch (((typelib_InterfaceMemberTypeDescription *)pMemberType)->nPosition)
586 case 0: // queryInterface()
588 AdapterImpl * that =
589 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
590 *ppException = 0; // no exc
591 typelib_TypeDescriptionReference * pDemanded =
592 *(typelib_TypeDescriptionReference **)pArgs[0];
593 // pInterfaces[0] is XInterface
594 for ( sal_Int32 nPos = 0; nPos < that->m_nInterfaces; ++nPos )
596 typelib_InterfaceTypeDescription * pTD =
597 that->m_pInterfaces[nPos].m_pTypeDescr;
598 while (pTD)
600 if (type_equals(
601 ((typelib_TypeDescription *)pTD)->pWeakRef, pDemanded ))
603 uno_Interface * pUnoI2 = &that->m_pInterfaces[nPos];
604 ::uno_any_construct(
605 (uno_Any *)pReturn, &pUnoI2,
606 (typelib_TypeDescription *)pTD, 0 );
607 return;
609 pTD = pTD->pBaseTypeDescription;
612 ::uno_any_construct( (uno_Any *)pReturn, 0, 0, 0 ); // clear()
613 break;
615 case 1: // acquire()
616 *ppException = 0; // no exc
617 adapter_acquire( pUnoI );
618 break;
619 case 2: // release()
620 *ppException = 0; // no exc
621 adapter_release( pUnoI );
622 break;
624 default:
626 AdapterImpl * that =
627 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
628 if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
630 that->invoke( pMemberType, pReturn, pArgs, ppException );
632 else // attribute
634 if (pReturn)
635 that->getValue( pMemberType, pReturn, ppException );
636 else
637 that->setValue( pMemberType, pArgs, ppException );
643 //______________________________________________________________________________
644 AdapterImpl::AdapterImpl(
645 void * key, Reference< script::XInvocation > const & xReceiver,
646 const Sequence< Type > & rTypes,
647 FactoryImpl * pFactory )
648 SAL_THROW( (RuntimeException) )
649 : m_nRef( 1 ),
650 m_pFactory( pFactory ),
651 m_key( key )
653 // init adapters
654 m_nInterfaces = rTypes.getLength();
655 m_pInterfaces = new InterfaceAdapterImpl[ rTypes.getLength() ];
656 const Type * pTypes = rTypes.getConstArray();
657 for ( sal_Int32 nPos = rTypes.getLength(); nPos--; )
659 InterfaceAdapterImpl * pInterface = &m_pInterfaces[nPos];
660 pInterface->acquire = adapter_acquire;
661 pInterface->release = adapter_release;
662 pInterface->pDispatcher = adapter_dispatch;
663 pInterface->m_pAdapter = this;
664 pInterface->m_pTypeDescr = 0;
665 pTypes[nPos].getDescription(
666 (typelib_TypeDescription **)&pInterface->m_pTypeDescr );
667 OSL_ASSERT( pInterface->m_pTypeDescr );
668 if (! pInterface->m_pTypeDescr)
670 for ( sal_Int32 n = 0; n < nPos; ++n )
672 ::typelib_typedescription_release(
673 (typelib_TypeDescription *)
674 m_pInterfaces[ n ].m_pTypeDescr );
676 delete [] m_pInterfaces;
677 throw RuntimeException(
678 "cannot retrieve all interface type infos!",
679 Reference< XInterface >() );
683 // map receiver
684 m_pReceiver = (uno_Interface *)m_pFactory->m_aCpp2Uno.mapInterface(
685 xReceiver.get(), ::getCppuType( &xReceiver ) );
686 OSL_ASSERT( 0 != m_pReceiver );
687 if (! m_pReceiver)
689 throw RuntimeException(
690 "cannot map receiver!", Reference< XInterface >() );
693 m_pFactory->acquire();
696 //______________________________________________________________________________
697 FactoryImpl::FactoryImpl( Reference< XComponentContext > const & xContext )
698 SAL_THROW( (RuntimeException) )
699 : m_pInvokMethodTD( 0 ),
700 m_pSetValueTD( 0 ),
701 m_pGetValueTD( 0 ),
702 m_pAnySeqTD( 0 ),
703 m_pShortSeqTD( 0 ),
704 m_pConvertToTD( 0 )
706 // C++/UNO bridge
707 OUString aCppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
708 OUString aUnoEnvTypeName = UNO_LB_UNO;
709 m_aUno2Cpp = Mapping( aUnoEnvTypeName, aCppEnvTypeName );
710 m_aCpp2Uno = Mapping( aCppEnvTypeName, aUnoEnvTypeName );
711 OSL_ENSURE(
712 m_aUno2Cpp.is() && m_aCpp2Uno.is(), "### no uno / C++ mappings!" );
714 // type converter
715 Reference< script::XTypeConverter > xConverter(
716 xContext->getServiceManager()->createInstanceWithContext(
717 OUString("com.sun.star.script.Converter"),
718 xContext ),
719 UNO_QUERY_THROW );
720 m_pConverter = (uno_Interface *)m_aCpp2Uno.mapInterface(
721 xConverter.get(), ::getCppuType( &xConverter ) );
722 OSL_ASSERT( 0 != m_pConverter );
724 // some type info:
725 // sequence< any >
726 Type const & rAnySeqType = ::getCppuType( (const Sequence< Any > *)0 );
727 rAnySeqType.getDescription( &m_pAnySeqTD );
728 // sequence< short >
729 const Type & rShortSeqType =
730 ::getCppuType( (const Sequence< sal_Int16 > *)0 );
731 rShortSeqType.getDescription( &m_pShortSeqTD );
732 // script.XInvocation
733 typelib_TypeDescription * pTD = 0;
734 const Type & rInvType = ::getCppuType(
735 (const Reference< script::XInvocation > *)0 );
736 TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() );
737 typelib_InterfaceTypeDescription * pITD;
738 pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
739 if( ! pITD->aBase.bComplete )
740 typelib_typedescription_complete( &pTD );
741 ::typelib_typedescriptionreference_getDescription(
742 &m_pInvokMethodTD, pITD->ppMembers[ 1 ] ); // invoke()
743 ::typelib_typedescriptionreference_getDescription(
744 &m_pSetValueTD, pITD->ppMembers[ 2 ] ); // setValue()
745 ::typelib_typedescriptionreference_getDescription(
746 &m_pGetValueTD, pITD->ppMembers[ 3 ] ); // getValue()
747 // script.XTypeConverter
748 const Type & rTCType =
749 ::getCppuType( (const Reference< script::XTypeConverter > *)0 );
750 TYPELIB_DANGER_GET( &pTD, rTCType.getTypeLibType() );
751 pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
752 ::typelib_typedescriptionreference_getDescription(
753 &m_pConvertToTD, pITD->ppMembers[ 0 ] ); // convertTo()
754 TYPELIB_DANGER_RELEASE( pTD );
756 if (!m_pInvokMethodTD || !m_pSetValueTD || !m_pGetValueTD ||
757 !m_pConvertToTD ||
758 !m_pAnySeqTD || !m_pShortSeqTD)
760 throw RuntimeException(
761 "missing type descriptions!", Reference< XInterface >() );
764 //______________________________________________________________________________
765 FactoryImpl::~FactoryImpl() SAL_THROW(())
767 ::typelib_typedescription_release( m_pInvokMethodTD );
768 ::typelib_typedescription_release( m_pSetValueTD );
769 ::typelib_typedescription_release( m_pGetValueTD );
770 ::typelib_typedescription_release( m_pAnySeqTD );
771 ::typelib_typedescription_release( m_pShortSeqTD );
772 ::typelib_typedescription_release( m_pConvertToTD );
774 (*m_pConverter->release)( m_pConverter );
776 #if OSL_DEBUG_LEVEL > 1
777 OSL_ENSURE( m_receiver2adapters.empty(), "### still adapters out there!?" );
778 #endif
781 //------------------------------------------------------------------------------
782 static inline AdapterImpl * lookup_adapter(
783 t_ptr_set ** pp_adapter_set,
784 t_ptr_map & map, void * key, Sequence< Type > const & rTypes )
785 SAL_THROW(())
787 t_ptr_set & adapters_set = map[ key ];
788 *pp_adapter_set = &adapters_set;
789 if (adapters_set.empty())
790 return 0; // shortcut
791 // find matching adapter
792 Type const * pTypes = rTypes.getConstArray();
793 sal_Int32 nTypes = rTypes.getLength();
794 t_ptr_set::const_iterator iPos( adapters_set.begin() );
795 t_ptr_set::const_iterator const iEnd( adapters_set.end() );
796 while (iEnd != iPos)
798 AdapterImpl * that = reinterpret_cast< AdapterImpl * >( *iPos );
799 // iterate thru all types if that is a matching adapter
800 sal_Int32 nPosTypes;
801 for ( nPosTypes = nTypes; nPosTypes--; )
803 Type const & rType = pTypes[ nPosTypes ];
804 // find in adapter's type list
805 sal_Int32 nPos;
806 for ( nPos = that->m_nInterfaces; nPos--; )
808 if (::typelib_typedescriptionreference_isAssignableFrom(
809 rType.getTypeLibType(),
810 ((typelib_TypeDescription *)that->
811 m_pInterfaces[ nPos ].m_pTypeDescr)->pWeakRef ))
813 // found
814 break;
817 if (nPos < 0) // type not found => next adapter
818 break;
820 if (nPosTypes < 0) // all types found
821 return that;
822 ++iPos;
824 return 0;
827 // XInvocationAdapterFactory2 impl
828 //______________________________________________________________________________
829 Reference< XInterface > FactoryImpl::createAdapter(
830 const Reference< script::XInvocation > & xReceiver,
831 const Sequence< Type > & rTypes )
832 throw (RuntimeException)
834 Reference< XInterface > xRet;
835 if (xReceiver.is() && rTypes.getLength())
837 t_ptr_set * adapter_set;
838 AdapterImpl * that;
839 Reference< XInterface > xKey( xReceiver, UNO_QUERY );
841 ClearableMutexGuard guard( m_mutex );
842 that = lookup_adapter(
843 &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
844 if (0 == that) // no entry
846 guard.clear();
847 // create adapter; already acquired: m_nRef == 1
848 AdapterImpl * pNew =
849 new AdapterImpl( xKey.get(), xReceiver, rTypes, this );
850 // lookup again
851 ClearableMutexGuard guard2( m_mutex );
852 that = lookup_adapter(
853 &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
854 if (0 == that) // again no entry
856 pair< t_ptr_set::iterator, bool > i(adapter_set->insert(pNew));
857 SAL_WARN_IF(
858 !i.second, "stoc",
859 "set already contains " << *(i.first) << " != " << pNew);
860 that = pNew;
862 else
864 that->acquire();
865 guard2.clear();
866 delete pNew; // has never been inserted
869 else // found adapter
871 that->acquire();
874 // map one interface to C++
875 uno_Interface * pUnoI = &that->m_pInterfaces[ 0 ];
876 m_aUno2Cpp.mapInterface(
877 (void **)&xRet, pUnoI, ::getCppuType( &xRet ) );
878 that->release();
879 OSL_ASSERT( xRet.is() );
880 if (! xRet.is())
882 throw RuntimeException(
883 "mapping UNO to C++ failed!",
884 Reference< XInterface >() );
887 return xRet;
889 // XInvocationAdapterFactory impl
890 //______________________________________________________________________________
891 Reference< XInterface > FactoryImpl::createAdapter(
892 const Reference< script::XInvocation > & xReceiver, const Type & rType )
893 throw (RuntimeException)
895 return createAdapter( xReceiver, Sequence< Type >( &rType, 1 ) );
898 // XServiceInfo
899 //______________________________________________________________________________
900 OUString FactoryImpl::getImplementationName()
901 throw (RuntimeException)
903 return invadp_getImplementationName();
905 //______________________________________________________________________________
906 sal_Bool FactoryImpl::supportsService( const OUString & rServiceName )
907 throw (RuntimeException)
909 const Sequence< OUString > & rSNL = getSupportedServiceNames();
910 const OUString * pArray = rSNL.getConstArray();
911 for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
913 if (pArray[nPos].equals( rServiceName ))
914 return sal_True;
916 return sal_False;
918 //______________________________________________________________________________
919 Sequence< OUString > FactoryImpl::getSupportedServiceNames()
920 throw (RuntimeException)
922 return invadp_getSupportedServiceNames();
925 //==============================================================================
926 static Reference< XInterface > SAL_CALL FactoryImpl_create(
927 const Reference< XComponentContext > & xContext )
928 throw (Exception)
930 return (::cppu::OWeakObject *)new FactoryImpl( xContext );
936 //##############################################################################
937 //##############################################################################
938 //##############################################################################
940 static struct ::cppu::ImplementationEntry g_entries[] =
943 ::stoc_invadp::FactoryImpl_create,
944 ::stoc_invadp::invadp_getImplementationName,
945 ::stoc_invadp::invadp_getSupportedServiceNames,
946 ::cppu::createOneInstanceComponentFactory,
947 0, 0
949 { 0, 0, 0, 0, 0, 0 }
952 extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL invocadapt_component_getFactory(
953 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
955 return ::cppu::component_getFactoryHelper(
956 pImplName, pServiceManager, pRegistryKey , g_entries );
959 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */