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