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