1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_stoc.hxx"
26 
27 #include <hash_map>
28 #include <hash_set>
29 
30 #include <osl/diagnose.h>
31 #include <osl/interlck.h>
32 #include <osl/mutex.hxx>
33 
34 #include <uno/dispatcher.h>
35 #include <uno/data.h>
36 #include <uno/any2.h>
37 #include <uno/mapping.hxx>
38 
39 #include <cppuhelper/factory.hxx>
40 #include <cppuhelper/implbase3.hxx>
41 #include <cppuhelper/implementationentry.hxx>
42 
43 #include <com/sun/star/uno/XAggregation.hpp>
44 #include <com/sun/star/script/XTypeConverter.hpp>
45 #include <com/sun/star/script/XInvocationAdapterFactory.hpp>
46 #include <com/sun/star/script/XInvocationAdapterFactory2.hpp>
47 #include <com/sun/star/script/XInvocation.hpp>
48 #include <com/sun/star/lang/XServiceInfo.hpp>
49 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
50 #include <com/sun/star/registry/XSimpleRegistry.hpp>
51 #include <com/sun/star/registry/XRegistryKey.hpp>
52 #include <com/sun/star/reflection/InvocationTargetException.hpp>
53 #include "com/sun/star/uno/RuntimeException.hpp"
54 
55 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
56 
57 #define SERVICENAME "com.sun.star.script.InvocationAdapterFactory"
58 #define IMPLNAME    "com.sun.star.comp.stoc.InvocationAdapterFactory"
59 
60 
61 using namespace ::std;
62 using namespace ::rtl;
63 using namespace ::osl;
64 using namespace ::com::sun::star;
65 using namespace ::com::sun::star::uno;
66 
67 namespace stoc_invadp
68 {
69 
70 static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
71 
72 static Sequence< OUString > invadp_getSupportedServiceNames()
73 {
74     static Sequence < OUString > *pNames = 0;
75     if( ! pNames )
76     {
77         MutexGuard guard( Mutex::getGlobalMutex() );
78         if( !pNames )
79         {
80             static Sequence< OUString > seqNames(1);
81             seqNames.getArray()[0] =
82                 OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
83             pNames = &seqNames;
84         }
85     }
86     return *pNames;
87 }
88 
89 static OUString invadp_getImplementationName()
90 {
91     static OUString *pImplName = 0;
92     if( ! pImplName )
93     {
94         MutexGuard guard( Mutex::getGlobalMutex() );
95         if( ! pImplName )
96         {
97             static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
98             pImplName = &implName;
99         }
100     }
101     return *pImplName;
102 }
103 
104 struct hash_ptr
105 {
106     inline size_t operator() ( void * p ) const
107         { return (size_t)p; }
108 };
109 typedef hash_set< void *, hash_ptr, equal_to< void * > > t_ptr_set;
110 typedef hash_map< void *, t_ptr_set, hash_ptr, equal_to< void * > > t_ptr_map;
111 
112 //==============================================================================
113 class FactoryImpl
114     : public ::cppu::WeakImplHelper3< lang::XServiceInfo,
115                                       script::XInvocationAdapterFactory,
116                                       script::XInvocationAdapterFactory2 >
117 {
118 public:
119     Mapping m_aUno2Cpp;
120     Mapping m_aCpp2Uno;
121     uno_Interface * m_pConverter;
122 
123     typelib_TypeDescription * m_pInvokMethodTD;
124     typelib_TypeDescription * m_pSetValueTD;
125     typelib_TypeDescription * m_pGetValueTD;
126     typelib_TypeDescription * m_pAnySeqTD;
127     typelib_TypeDescription * m_pShortSeqTD;
128     typelib_TypeDescription * m_pConvertToTD;
129 
130     Mutex m_mutex;
131     t_ptr_map m_receiver2adapters;
132 
133     FactoryImpl( Reference< XComponentContext > const & xContext )
134         SAL_THROW( (RuntimeException) );
135     virtual ~FactoryImpl() SAL_THROW( () );
136 
137     // XServiceInfo
138     virtual OUString SAL_CALL getImplementationName()
139         throw (RuntimeException);
140     virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName )
141         throw (RuntimeException);
142     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
143         throw (RuntimeException);
144 
145     // XInvocationAdapterFactory
146     virtual Reference< XInterface > SAL_CALL createAdapter(
147         const Reference< script::XInvocation > & xReceiver, const Type & rType )
148         throw (RuntimeException);
149     // XInvocationAdapterFactory2
150     virtual Reference< XInterface > SAL_CALL createAdapter(
151         const Reference< script::XInvocation > & xReceiver,
152         const Sequence< Type > & rTypes )
153         throw (RuntimeException);
154 };
155 struct AdapterImpl;
156 //==============================================================================
157 struct InterfaceAdapterImpl : public uno_Interface
158 {
159     AdapterImpl *                           m_pAdapter;
160     typelib_InterfaceTypeDescription *      m_pTypeDescr;
161 };
162 //==============================================================================
163 struct AdapterImpl
164 {
165     oslInterlockedCount         m_nRef;
166     FactoryImpl *               m_pFactory;
167     void *                      m_key; // map key
168     uno_Interface *             m_pReceiver; // XInvocation receiver
169 
170     sal_Int32                   m_nInterfaces;
171     InterfaceAdapterImpl *      m_pInterfaces;
172 
173     // XInvocation calls
174     void getValue(
175         const typelib_TypeDescription * pMemberType,
176         void * pReturn, void * pArgs[], uno_Any ** ppException );
177     void setValue(
178         const typelib_TypeDescription * pMemberType,
179         void * pReturn, void * pArgs[], uno_Any ** ppException );
180     void invoke(
181         const typelib_TypeDescription * pMemberType,
182         void * pReturn, void * pArgs[], uno_Any ** ppException );
183 
184     bool coerce_assign(
185         void * pDest, typelib_TypeDescriptionReference * pType,
186         uno_Any * pSource, uno_Any * pExc );
187     inline bool coerce_construct(
188         void * pDest, typelib_TypeDescriptionReference * pType,
189         uno_Any * pSource, uno_Any * pExc );
190 
191     inline void acquire()
192         SAL_THROW( () );
193     inline void release()
194         SAL_THROW( () );
195     inline ~AdapterImpl()
196         SAL_THROW( () );
197     inline AdapterImpl(
198         void * key, Reference< script::XInvocation > const & xReceiver,
199         const Sequence< Type > & rTypes,
200         FactoryImpl * pFactory )
201         SAL_THROW( (RuntimeException) );
202 };
203 //______________________________________________________________________________
204 inline AdapterImpl::~AdapterImpl()
205     SAL_THROW( () )
206 {
207     for ( sal_Int32 nPos = m_nInterfaces; nPos--; )
208     {
209         ::typelib_typedescription_release(
210             (typelib_TypeDescription *)m_pInterfaces[ nPos ].m_pTypeDescr );
211     }
212     delete [] m_pInterfaces;
213     //
214     (*m_pReceiver->release)( m_pReceiver );
215     m_pFactory->release();
216 }
217 //______________________________________________________________________________
218 inline void AdapterImpl::acquire()
219     SAL_THROW( () )
220 {
221     ::osl_incrementInterlockedCount( &m_nRef );
222 }
223 //______________________________________________________________________________
224 inline void AdapterImpl::release()
225     SAL_THROW( () )
226 {
227 	bool delete_this = false;
228 	{
229     MutexGuard guard( m_pFactory->m_mutex );
230     if (! ::osl_decrementInterlockedCount( &m_nRef ))
231     {
232         t_ptr_map::iterator iFind(
233             m_pFactory->m_receiver2adapters.find( m_key ) );
234         OSL_ASSERT( m_pFactory->m_receiver2adapters.end() != iFind );
235         t_ptr_set & adapter_set = iFind->second;
236         if (adapter_set.erase( this ) != 1) {
237             OSL_ASSERT( false );
238         }
239         if (adapter_set.empty())
240         {
241             m_pFactory->m_receiver2adapters.erase( iFind );
242         }
243 		delete_this = true;
244     }
245 	}
246 	if (delete_this)
247         delete this;
248 }
249 
250 //------------------------------------------------------------------------------
251 static inline void constructRuntimeException(
252     uno_Any * pExc, const OUString & rMsg )
253 {
254     RuntimeException exc( rMsg, Reference< XInterface >() );
255     // no conversion neeeded due to binary compatibility + no convertable type
256     ::uno_type_any_construct(
257         pExc, &exc, ::getCppuType( &exc ).getTypeLibType(), 0 );
258 }
259 
260 //------------------------------------------------------------------------------
261 static inline sal_Bool type_equals(
262     typelib_TypeDescriptionReference * pType1,
263     typelib_TypeDescriptionReference * pType2 )
264     SAL_THROW( () )
265 {
266     return (pType1 == pType2 ||
267             (pType1->pTypeName->length == pType2->pTypeName->length &&
268              0 == ::rtl_ustr_compare(
269                  pType1->pTypeName->buffer, pType2->pTypeName->buffer )));
270 }
271 
272 //______________________________________________________________________________
273 bool AdapterImpl::coerce_assign(
274     void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
275     uno_Any * pOutExc )
276 {
277     if (typelib_TypeClass_ANY == pType->eTypeClass)
278     {
279         ::uno_type_any_assign(
280             (uno_Any *)pDest, pSource->pData, pSource->pType, 0, 0 );
281         return true;
282     }
283     if (::uno_type_assignData(
284             pDest, pType, pSource->pData, pSource->pType, 0, 0, 0 ))
285     {
286         return true;
287     }
288     else // try type converter
289     {
290         uno_Any ret;
291         void * args[ 2 ];
292         args[ 0 ] = pSource;
293         args[ 1 ] = &pType;
294         uno_Any exc;
295         uno_Any * p_exc = &exc;
296 
297         // converTo()
298         (*m_pFactory->m_pConverter->pDispatcher)(
299             m_pFactory->m_pConverter,
300             m_pFactory->m_pConvertToTD, &ret, args, &p_exc );
301 
302         if (p_exc) // exception occured
303         {
304             OSL_ASSERT(
305                 p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
306             if (typelib_typedescriptionreference_isAssignableFrom(
307                     ::getCppuType(
308                         (RuntimeException const *) 0 ).getTypeLibType(),
309                     p_exc->pType ))
310             {
311                 // is RuntimeException or derived: rethrow
312                 uno_type_any_construct(
313                     pOutExc, p_exc->pData, p_exc->pType, 0 );
314             }
315             else
316             {
317                 // set runtime exception
318                 constructRuntimeException(
319                     pOutExc, OUSTR("type coercion failed: ") +
320                     reinterpret_cast< Exception const * >(
321                         p_exc->pData )->Message );
322             }
323             ::uno_any_destruct( p_exc, 0 );
324             // pOutExc constructed
325             return false;
326         }
327         else
328         {
329             bool succ = (sal_False != ::uno_type_assignData(
330                              pDest, pType, ret.pData, ret.pType, 0, 0, 0 ));
331             ::uno_any_destruct( &ret, 0 );
332             OSL_ENSURE(
333                 succ, "### conversion succeeded, but assignment failed!?" );
334             if (! succ)
335             {
336                 // set runtime exception
337                 constructRuntimeException(
338                     pOutExc,
339                     OUSTR("type coercion failed: "
340                           "conversion succeeded, but assignment failed?!") );
341             }
342             return succ;
343         }
344     }
345 }
346 //______________________________________________________________________________
347 inline bool AdapterImpl::coerce_construct(
348     void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
349     uno_Any * pExc )
350 {
351     if (typelib_TypeClass_ANY == pType->eTypeClass)
352     {
353         ::uno_type_copyData( pDest, pSource, pType, 0 );
354         return true;
355     }
356     if (type_equals( pType, pSource->pType))
357     {
358         ::uno_type_copyData( pDest, pSource->pData, pType, 0 );
359         return true;
360     }
361     ::uno_type_constructData( pDest, pType );
362     return coerce_assign( pDest, pType, pSource, pExc );
363 }
364 
365 //------------------------------------------------------------------------------
366 static void handleInvokExc( uno_Any * pDest, uno_Any * pSource )
367 {
368     OUString const & name =
369         *reinterpret_cast< OUString const * >( &pSource->pType->pTypeName );
370 
371     if (name.equalsAsciiL(
372             RTL_CONSTASCII_STRINGPARAM(
373                 "com.sun.star.reflection.InvocationTargetException") ))
374     {
375         // unwrap invocation target exception
376         uno_Any * target_exc =
377             &reinterpret_cast< reflection::InvocationTargetException * >(
378                 pSource->pData )->TargetException;
379         ::uno_type_any_construct(
380             pDest, target_exc->pData, target_exc->pType, 0 );
381     }
382     else // all other exceptions are wrapped to RuntimeException
383     {
384         if (typelib_TypeClass_EXCEPTION == pSource->pType->eTypeClass)
385         {
386             constructRuntimeException(
387                 pDest, ((Exception const *)pSource->pData)->Message );
388         }
389         else
390         {
391             constructRuntimeException(
392                 pDest, OUSTR("no exception has been thrown via invocation?!") );
393         }
394     }
395 }
396 //______________________________________________________________________________
397 void AdapterImpl::getValue(
398     const typelib_TypeDescription * pMemberType,
399     void * pReturn, void * [], uno_Any ** ppException )
400 {
401     uno_Any aInvokRet;
402     void * pInvokArgs[1];
403     pInvokArgs[0] =
404         &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
405     uno_Any aInvokExc;
406     uno_Any * pInvokExc = &aInvokExc;
407 
408     // getValue()
409     (*m_pReceiver->pDispatcher)(
410         m_pReceiver, m_pFactory->m_pGetValueTD,
411         &aInvokRet, pInvokArgs, &pInvokExc );
412 
413     if (pInvokExc) // getValue() call exception
414     {
415         handleInvokExc( *ppException, pInvokExc );
416         ::uno_any_destruct( pInvokExc, 0 ); // cleanup
417     }
418     else // invocation call succeeded
419     {
420         if (coerce_construct(
421                 pReturn,
422                 ((typelib_InterfaceAttributeTypeDescription *)
423                  pMemberType)->pAttributeTypeRef,
424                 &aInvokRet, *ppException ))
425         {
426             *ppException = 0; // no exceptions be thrown
427         }
428         ::uno_any_destruct( &aInvokRet, 0 );
429     }
430 }
431 //______________________________________________________________________________
432 void AdapterImpl::setValue(
433     const typelib_TypeDescription * pMemberType,
434     void *, void * pArgs[], uno_Any ** ppException )
435 {
436     uno_Any aInvokVal;
437     ::uno_type_any_construct(
438         &aInvokVal, pArgs[0],
439         ((typelib_InterfaceAttributeTypeDescription *)
440          pMemberType)->pAttributeTypeRef, 0 );
441 
442     void * pInvokArgs[2];
443     pInvokArgs[0] =
444         &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
445     pInvokArgs[1] = &aInvokVal;
446     uno_Any aInvokExc;
447     uno_Any * pInvokExc = &aInvokExc;
448 
449     // setValue()
450     (*m_pReceiver->pDispatcher)(
451         m_pReceiver, m_pFactory->m_pSetValueTD, 0, pInvokArgs, &pInvokExc );
452 
453     if (pInvokExc) // setValue() call exception
454     {
455         handleInvokExc( *ppException, pInvokExc );
456         ::uno_any_destruct( pInvokExc, 0 ); // cleanup
457     }
458     else // invocation call succeeded
459     {
460         *ppException = 0; // no exceptions be thrown
461     }
462 
463     ::uno_any_destruct( &aInvokVal, 0 ); // cleanup
464 }
465 //______________________________________________________________________________
466 void AdapterImpl::invoke(
467     const typelib_TypeDescription * pMemberType,
468     void * pReturn, void * pArgs[], uno_Any ** ppException )
469 {
470     sal_Int32 nParams =
471         ((typelib_InterfaceMethodTypeDescription *)pMemberType)->nParams;
472     typelib_MethodParameter * pFormalParams =
473         ((typelib_InterfaceMethodTypeDescription *)pMemberType)->pParams;
474 
475     // in params
476     uno_Sequence * pInParamsSeq = 0;
477     ::uno_sequence_construct(
478         &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0, nParams, 0 );
479     uno_Any * pInAnys = (uno_Any *)pInParamsSeq->elements;
480     sal_Int32 nOutParams = 0;
481     sal_Int32 nPos;
482     for ( nPos = nParams; nPos--; )
483     {
484         typelib_MethodParameter const & rParam = pFormalParams[nPos];
485         if (rParam.bIn) // is in/inout param
486         {
487             ::uno_type_any_assign(
488                 &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef, 0, 0 );
489         }
490         // else: pure out is empty any
491 
492         if (rParam.bOut)
493             ++nOutParams;
494     }
495 
496     // out params, out indices
497     uno_Sequence * pOutIndices;
498     uno_Sequence * pOutParams;
499     // return value
500     uno_Any aInvokRet;
501     // perform call
502     void * pInvokArgs[4];
503     pInvokArgs[0] =
504         &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
505     pInvokArgs[1] = &pInParamsSeq;
506     pInvokArgs[2] = &pOutIndices;
507     pInvokArgs[3] = &pOutParams;
508     uno_Any aInvokExc;
509     uno_Any * pInvokExc = &aInvokExc;
510 
511     // invoke() call
512     (*m_pReceiver->pDispatcher)(
513         m_pReceiver, m_pFactory->m_pInvokMethodTD,
514         &aInvokRet, pInvokArgs, &pInvokExc );
515 
516     if (pInvokExc)
517     {
518         handleInvokExc( *ppException, pInvokExc );
519         ::uno_any_destruct( pInvokExc, 0 ); // cleanup
520     }
521     else // no invocation exception
522     {
523         // write changed out params
524         OSL_ENSURE(
525             pOutParams->nElements == nOutParams &&
526             pOutIndices->nElements == nOutParams,
527             "### out params lens differ!" );
528         if (pOutParams->nElements == nOutParams &&
529             pOutIndices->nElements == nOutParams)
530         {
531             sal_Int16 * pIndices = (sal_Int16 *)pOutIndices->elements;
532             uno_Any * pOut       = (uno_Any *)pOutParams->elements;
533             for ( nPos = 0; nPos < nOutParams; ++nPos )
534             {
535                 sal_Int32 nIndex = pIndices[nPos];
536                 OSL_ENSURE( nIndex < nParams, "### illegal index!" );
537                 typelib_MethodParameter const & rParam = pFormalParams[nIndex];
538                 bool succ;
539                 if (rParam.bIn) // is in/inout param
540                 {
541                     succ = coerce_assign(
542                         pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
543                         *ppException );
544                 }
545                 else // pure out
546                 {
547                     succ = coerce_construct(
548                         pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
549                         *ppException );
550                 }
551                 if (! succ) // cleanup of out params
552                 {
553                     for ( sal_Int32 n = 0; n <= nPos; ++n )
554                     {
555                         sal_Int32 nIndex2 = pIndices[n];
556                         OSL_ENSURE( nIndex2 < nParams, "### illegal index!" );
557                         typelib_MethodParameter const & rParam2 =
558                             pFormalParams[nIndex2];
559                         if (! rParam2.bIn) // is pure out param
560                         {
561                             ::uno_type_destructData(
562                                 pArgs[nIndex2], rParam2.pTypeRef, 0 );
563                         }
564                     }
565                 }
566             }
567             if (nPos == pOutIndices->nElements)
568             {
569                 // out param copy ok; write return value
570                 if (coerce_construct(
571                         pReturn,
572                         ((typelib_InterfaceMethodTypeDescription *)
573                          pMemberType)->pReturnTypeRef,
574                         &aInvokRet, *ppException ))
575                 {
576                     *ppException = 0; // no exception
577                 }
578             }
579         }
580         else
581         {
582             // set runtime exception
583             constructRuntimeException(
584                 *ppException,
585                 OUSTR("out params lengths differ after invocation call!") );
586         }
587         // cleanup invok out params
588         ::uno_destructData( &pOutIndices, m_pFactory->m_pShortSeqTD, 0 );
589         ::uno_destructData( &pOutParams, m_pFactory->m_pAnySeqTD, 0 );
590         // cleanup invok return value
591         ::uno_any_destruct( &aInvokRet, 0 );
592     }
593     // cleanup constructed in params
594     ::uno_destructData( &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0 );
595 }
596 
597 extern "C"
598 {
599 //______________________________________________________________________________
600 static void SAL_CALL adapter_acquire( uno_Interface * pUnoI )
601 {
602     static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire();
603 }
604 //______________________________________________________________________________
605 static void SAL_CALL adapter_release( uno_Interface * pUnoI )
606 {
607     static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release();
608 }
609 //______________________________________________________________________________
610 static void SAL_CALL adapter_dispatch(
611     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType,
612     void * pReturn, void * pArgs[], uno_Any ** ppException )
613 {
614     // query to emulated interface
615     switch (((typelib_InterfaceMemberTypeDescription *)pMemberType)->nPosition)
616     {
617     case 0: // queryInterface()
618     {
619         AdapterImpl * that =
620             static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
621         *ppException = 0; // no exc
622         typelib_TypeDescriptionReference * pDemanded =
623             *(typelib_TypeDescriptionReference **)pArgs[0];
624         // pInterfaces[0] is XInterface
625         for ( sal_Int32 nPos = 0; nPos < that->m_nInterfaces; ++nPos )
626         {
627             typelib_InterfaceTypeDescription * pTD =
628                 that->m_pInterfaces[nPos].m_pTypeDescr;
629             while (pTD)
630             {
631                 if (type_equals(
632                         ((typelib_TypeDescription *)pTD)->pWeakRef, pDemanded ))
633                 {
634                     uno_Interface * pUnoI2 = &that->m_pInterfaces[nPos];
635                     ::uno_any_construct(
636                         (uno_Any *)pReturn, &pUnoI2,
637                         (typelib_TypeDescription *)pTD, 0 );
638                     return;
639                 }
640                 pTD = pTD->pBaseTypeDescription;
641             }
642         }
643         ::uno_any_construct( (uno_Any *)pReturn, 0, 0, 0 ); // clear()
644         break;
645     }
646     case 1: // acquire()
647         *ppException = 0; // no exc
648         adapter_acquire( pUnoI );
649         break;
650     case 2: // release()
651         *ppException = 0; // no exc
652         adapter_release( pUnoI );
653         break;
654 
655     default:
656     {
657         AdapterImpl * that =
658             static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
659         if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
660         {
661             that->invoke( pMemberType, pReturn, pArgs, ppException );
662         }
663         else // attribute
664         {
665             if (pReturn)
666                 that->getValue( pMemberType, pReturn, pArgs, ppException );
667             else
668                 that->setValue( pMemberType, pReturn, pArgs, ppException );
669         }
670     }
671     }
672 }
673 }
674 //______________________________________________________________________________
675 AdapterImpl::AdapterImpl(
676     void * key, Reference< script::XInvocation > const & xReceiver,
677     const Sequence< Type > & rTypes,
678     FactoryImpl * pFactory )
679     SAL_THROW( (RuntimeException) )
680         : m_nRef( 1 ),
681           m_pFactory( pFactory ),
682           m_key( key )
683 {
684     // init adapters
685     m_nInterfaces = rTypes.getLength();
686     m_pInterfaces = new InterfaceAdapterImpl[ rTypes.getLength() ];
687     const Type * pTypes = rTypes.getConstArray();
688     for ( sal_Int32 nPos = rTypes.getLength(); nPos--; )
689     {
690         InterfaceAdapterImpl * pInterface = &m_pInterfaces[nPos];
691         pInterface->acquire = adapter_acquire;
692         pInterface->release = adapter_release;
693         pInterface->pDispatcher = adapter_dispatch;
694         pInterface->m_pAdapter = this;
695         pInterface->m_pTypeDescr = 0;
696         pTypes[nPos].getDescription(
697             (typelib_TypeDescription **)&pInterface->m_pTypeDescr );
698         OSL_ASSERT( pInterface->m_pTypeDescr );
699         if (! pInterface->m_pTypeDescr)
700         {
701             for ( sal_Int32 n = 0; n < nPos; ++n )
702             {
703                 ::typelib_typedescription_release(
704                     (typelib_TypeDescription *)
705                     m_pInterfaces[ n ].m_pTypeDescr );
706             }
707             delete [] m_pInterfaces;
708             throw RuntimeException(
709                 OUSTR("cannot retrieve all interface type infos!"),
710                 Reference< XInterface >() );
711         }
712     }
713 
714     // map receiver
715     m_pReceiver = (uno_Interface *)m_pFactory->m_aCpp2Uno.mapInterface(
716         xReceiver.get(), ::getCppuType( &xReceiver ) );
717     OSL_ASSERT( 0 != m_pReceiver );
718     if (! m_pReceiver)
719     {
720         throw RuntimeException(
721             OUSTR("cannot map receiver!"), Reference< XInterface >() );
722     }
723 
724     m_pFactory->acquire();
725 }
726 
727 //______________________________________________________________________________
728 FactoryImpl::FactoryImpl( Reference< XComponentContext > const & xContext )
729     SAL_THROW( (RuntimeException) )
730     : m_pInvokMethodTD( 0 ),
731       m_pSetValueTD( 0 ),
732       m_pGetValueTD( 0 ),
733       m_pAnySeqTD( 0 ),
734       m_pShortSeqTD( 0 ),
735       m_pConvertToTD( 0 )
736 {
737     // C++/UNO bridge
738     OUString aCppEnvTypeName = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
739     OUString aUnoEnvTypeName = OUSTR(UNO_LB_UNO);
740     m_aUno2Cpp = Mapping( aUnoEnvTypeName, aCppEnvTypeName );
741     m_aCpp2Uno = Mapping( aCppEnvTypeName, aUnoEnvTypeName );
742     OSL_ENSURE(
743         m_aUno2Cpp.is() && m_aCpp2Uno.is(), "### no uno / C++ mappings!" );
744 
745     // type converter
746     Reference< script::XTypeConverter > xConverter(
747         xContext->getServiceManager()->createInstanceWithContext(
748             OUString(
749                 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter") ),
750             xContext ),
751         UNO_QUERY_THROW );
752     m_pConverter = (uno_Interface *)m_aCpp2Uno.mapInterface(
753         xConverter.get(), ::getCppuType( &xConverter ) );
754     OSL_ASSERT( 0 != m_pConverter );
755 
756     // some type info:
757     // sequence< any >
758     Type const & rAnySeqType = ::getCppuType( (const Sequence< Any > *)0 );
759     rAnySeqType.getDescription( &m_pAnySeqTD );
760     // sequence< short >
761     const Type & rShortSeqType =
762         ::getCppuType( (const Sequence< sal_Int16 > *)0 );
763     rShortSeqType.getDescription( &m_pShortSeqTD );
764     // script.XInvocation
765     typelib_TypeDescription * pTD = 0;
766     const Type & rInvType = ::getCppuType(
767         (const Reference< script::XInvocation > *)0 );
768     TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() );
769     typelib_InterfaceTypeDescription * pITD;
770     pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
771     if( ! pITD->aBase.bComplete )
772         typelib_typedescription_complete( &pTD );
773     ::typelib_typedescriptionreference_getDescription(
774         &m_pInvokMethodTD, pITD->ppMembers[ 1 ] ); // invoke()
775     ::typelib_typedescriptionreference_getDescription(
776         &m_pSetValueTD, pITD->ppMembers[ 2 ] ); // setValue()
777     ::typelib_typedescriptionreference_getDescription(
778         &m_pGetValueTD, pITD->ppMembers[ 3 ] ); // getValue()
779     // script.XTypeConverter
780     const Type & rTCType =
781         ::getCppuType( (const Reference< script::XTypeConverter > *)0 );
782     TYPELIB_DANGER_GET( &pTD, rTCType.getTypeLibType() );
783     pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
784     ::typelib_typedescriptionreference_getDescription(
785         &m_pConvertToTD, pITD->ppMembers[ 0 ] ); // convertTo()
786     TYPELIB_DANGER_RELEASE( pTD );
787 
788     if (!m_pInvokMethodTD || !m_pSetValueTD || !m_pGetValueTD ||
789         !m_pConvertToTD ||
790         !m_pAnySeqTD || !m_pShortSeqTD)
791     {
792         throw RuntimeException(
793             OUSTR("missing type descriptions!"), Reference< XInterface >() );
794     }
795 
796     g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
797 }
798 //______________________________________________________________________________
799 FactoryImpl::~FactoryImpl() SAL_THROW( () )
800 {
801     ::typelib_typedescription_release( m_pInvokMethodTD );
802     ::typelib_typedescription_release( m_pSetValueTD );
803     ::typelib_typedescription_release( m_pGetValueTD );
804     ::typelib_typedescription_release( m_pAnySeqTD );
805     ::typelib_typedescription_release( m_pShortSeqTD );
806     ::typelib_typedescription_release( m_pConvertToTD );
807 
808     (*m_pConverter->release)( m_pConverter );
809 
810 #if OSL_DEBUG_LEVEL > 1
811     OSL_ENSURE( m_receiver2adapters.empty(), "### still adapters out there!?" );
812 #endif
813     g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
814 }
815 
816 //------------------------------------------------------------------------------
817 static inline AdapterImpl * lookup_adapter(
818     t_ptr_set ** pp_adapter_set,
819     t_ptr_map & map, void * key, Sequence< Type > const & rTypes )
820     SAL_THROW( () )
821 {
822     t_ptr_set & adapters_set = map[ key ];
823     *pp_adapter_set = &adapters_set;
824     if (adapters_set.empty())
825         return 0; // shortcut
826     // find matching adapter
827     Type const * pTypes = rTypes.getConstArray();
828     sal_Int32 nTypes = rTypes.getLength();
829     t_ptr_set::const_iterator iPos( adapters_set.begin() );
830     t_ptr_set::const_iterator const iEnd( adapters_set.end() );
831     while (iEnd != iPos)
832     {
833         AdapterImpl * that = reinterpret_cast< AdapterImpl * >( *iPos );
834         // iterate thru all types if that is a matching adapter
835         sal_Int32 nPosTypes;
836         for ( nPosTypes = nTypes; nPosTypes--; )
837         {
838             Type const & rType = pTypes[ nPosTypes ];
839             // find in adapter's type list
840             sal_Int32 nPos;
841             for ( nPos = that->m_nInterfaces; nPos--; )
842             {
843                 if (::typelib_typedescriptionreference_isAssignableFrom(
844                         rType.getTypeLibType(),
845                         ((typelib_TypeDescription *)that->
846                          m_pInterfaces[ nPos ].m_pTypeDescr)->pWeakRef ))
847                 {
848                     // found
849                     break;
850                 }
851             }
852             if (nPos < 0) // type not found => next adapter
853                 break;
854         }
855         if (nPosTypes < 0) // all types found
856             return that;
857         ++iPos;
858     }
859     return 0;
860 }
861 
862 // XInvocationAdapterFactory2 impl
863 //______________________________________________________________________________
864 Reference< XInterface > FactoryImpl::createAdapter(
865     const Reference< script::XInvocation > & xReceiver,
866     const Sequence< Type > & rTypes )
867     throw (RuntimeException)
868 {
869     Reference< XInterface > xRet;
870     if (xReceiver.is() && rTypes.getLength())
871     {
872         t_ptr_set * adapter_set;
873         AdapterImpl * that;
874         Reference< XInterface > xKey( xReceiver, UNO_QUERY );
875         {
876         ClearableMutexGuard guard( m_mutex );
877         that = lookup_adapter(
878             &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
879         if (0 == that) // no entry
880         {
881             guard.clear();
882             // create adapter; already acquired: m_nRef == 1
883             AdapterImpl * pNew =
884                 new AdapterImpl( xKey.get(), xReceiver, rTypes, this );
885             // lookup again
886             ClearableMutexGuard guard2( m_mutex );
887             that = lookup_adapter(
888                 &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
889             if (0 == that) // again no entry
890             {
891                 pair< t_ptr_set::iterator, bool > insertion(
892                     adapter_set->insert( pNew ) );
893                 OSL_ASSERT( insertion.second );
894                 that = pNew;
895             }
896             else
897             {
898                 that->acquire();
899                 guard2.clear();
900                 delete pNew; // has never been inserted
901             }
902         }
903         else // found adapter
904         {
905             that->acquire();
906         }
907         }
908         // map one interface to C++
909         uno_Interface * pUnoI = &that->m_pInterfaces[ 0 ];
910         m_aUno2Cpp.mapInterface(
911             (void **)&xRet, pUnoI, ::getCppuType( &xRet ) );
912         that->release();
913         OSL_ASSERT( xRet.is() );
914         if (! xRet.is())
915         {
916             throw RuntimeException(
917                 OUSTR("mapping UNO to C++ failed!"),
918                 Reference< XInterface >() );
919         }
920     }
921     return xRet;
922 }
923 // XInvocationAdapterFactory impl
924 //______________________________________________________________________________
925 Reference< XInterface > FactoryImpl::createAdapter(
926     const Reference< script::XInvocation > & xReceiver, const Type & rType )
927     throw (RuntimeException)
928 {
929     return createAdapter( xReceiver, Sequence< Type >( &rType, 1 ) );
930 }
931 
932 // XServiceInfo
933 //______________________________________________________________________________
934 OUString FactoryImpl::getImplementationName()
935     throw (RuntimeException)
936 {
937     return invadp_getImplementationName();
938 }
939 //______________________________________________________________________________
940 sal_Bool FactoryImpl::supportsService( const OUString & rServiceName )
941     throw (RuntimeException)
942 {
943     const Sequence< OUString > & rSNL = getSupportedServiceNames();
944     const OUString * pArray = rSNL.getConstArray();
945     for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
946     {
947         if (pArray[nPos].equals( rServiceName ))
948             return sal_True;
949     }
950     return sal_False;
951 }
952 //______________________________________________________________________________
953 Sequence< OUString > FactoryImpl::getSupportedServiceNames()
954     throw (RuntimeException)
955 {
956     return invadp_getSupportedServiceNames();
957 }
958 
959 //==============================================================================
960 static Reference< XInterface > SAL_CALL FactoryImpl_create(
961     const Reference< XComponentContext > & xContext )
962     throw (Exception)
963 {
964     Reference< XInterface > rRet;
965     {
966         MutexGuard guard( Mutex::getGlobalMutex() );
967         static WeakReference < XInterface > rwInstance;
968         rRet = rwInstance;
969 
970         if( ! rRet.is() )
971         {
972             rRet = (::cppu::OWeakObject *)new FactoryImpl( xContext );
973             rwInstance = rRet;
974         }
975     }
976     return rRet;
977 }
978 
979 }
980 
981 
982 //##############################################################################
983 //##############################################################################
984 //##############################################################################
985 
986 static struct ::cppu::ImplementationEntry g_entries[] =
987 {
988     {
989         ::stoc_invadp::FactoryImpl_create,
990         ::stoc_invadp::invadp_getImplementationName,
991         ::stoc_invadp::invadp_getSupportedServiceNames,
992         ::cppu::createSingleComponentFactory,
993         &::stoc_invadp::g_moduleCount.modCnt , 0
994     },
995     { 0, 0, 0, 0, 0, 0 }
996 };
997 
998 extern "C"
999 {
1000 sal_Bool SAL_CALL component_canUnload(
1001     TimeValue *pTime )
1002 {
1003     return ::stoc_invadp::g_moduleCount.canUnload(
1004         &::stoc_invadp::g_moduleCount, pTime );
1005 }
1006 
1007 //==============================================================================
1008 void SAL_CALL component_getImplementationEnvironment(
1009     const sal_Char ** ppEnvTypeName, uno_Environment ** )
1010 {
1011     *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
1012 }
1013 
1014 //==============================================================================
1015 void * SAL_CALL component_getFactory(
1016     const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
1017 {
1018     return ::cppu::component_getFactoryHelper(
1019         pImplName, pServiceManager, pRegistryKey , g_entries );
1020 }
1021 }
1022