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 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 //______________________________________________________________________________
~AdapterImpl()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 //______________________________________________________________________________
acquire()218 inline void AdapterImpl::acquire()
219 SAL_THROW( () )
220 {
221 ::osl_incrementInterlockedCount( &m_nRef );
222 }
223 //______________________________________________________________________________
release()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 //------------------------------------------------------------------------------
constructRuntimeException(uno_Any * pExc,const OUString & rMsg)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 //------------------------------------------------------------------------------
type_equals(typelib_TypeDescriptionReference * pType1,typelib_TypeDescriptionReference * pType2)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 //______________________________________________________________________________
coerce_assign(void * pDest,typelib_TypeDescriptionReference * pType,uno_Any * pSource,uno_Any * pOutExc)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 occurred
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 //______________________________________________________________________________
coerce_construct(void * pDest,typelib_TypeDescriptionReference * pType,uno_Any * pSource,uno_Any * pExc)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 //------------------------------------------------------------------------------
handleInvokExc(uno_Any * pDest,uno_Any * pSource)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 //______________________________________________________________________________
getValue(const typelib_TypeDescription * pMemberType,void * pReturn,void * [],uno_Any ** ppException)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 //______________________________________________________________________________
setValue(const typelib_TypeDescription * pMemberType,void *,void * pArgs[],uno_Any ** ppException)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 //______________________________________________________________________________
invoke(const typelib_TypeDescription * pMemberType,void * pReturn,void * pArgs[],uno_Any ** ppException)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 //______________________________________________________________________________
adapter_acquire(uno_Interface * pUnoI)600 static void SAL_CALL adapter_acquire( uno_Interface * pUnoI )
601 {
602 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire();
603 }
604 //______________________________________________________________________________
adapter_release(uno_Interface * pUnoI)605 static void SAL_CALL adapter_release( uno_Interface * pUnoI )
606 {
607 static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release();
608 }
609 //______________________________________________________________________________
adapter_dispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberType,void * pReturn,void * pArgs[],uno_Any ** ppException)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 //______________________________________________________________________________
AdapterImpl(void * key,Reference<script::XInvocation> const & xReceiver,const Sequence<Type> & rTypes,FactoryImpl * pFactory)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 //______________________________________________________________________________
FactoryImpl(Reference<XComponentContext> const & xContext)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 //______________________________________________________________________________
~FactoryImpl()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 //------------------------------------------------------------------------------
lookup_adapter(t_ptr_set ** pp_adapter_set,t_ptr_map & map,void * key,Sequence<Type> const & rTypes)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 //______________________________________________________________________________
createAdapter(const Reference<script::XInvocation> & xReceiver,const Sequence<Type> & rTypes)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 //______________________________________________________________________________
createAdapter(const Reference<script::XInvocation> & xReceiver,const Type & rType)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 //______________________________________________________________________________
getImplementationName()934 OUString FactoryImpl::getImplementationName()
935 throw (RuntimeException)
936 {
937 return invadp_getImplementationName();
938 }
939 //______________________________________________________________________________
supportsService(const OUString & rServiceName)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 //______________________________________________________________________________
getSupportedServiceNames()953 Sequence< OUString > FactoryImpl::getSupportedServiceNames()
954 throw (RuntimeException)
955 {
956 return invadp_getSupportedServiceNames();
957 }
958
959 //==============================================================================
FactoryImpl_create(const Reference<XComponentContext> & xContext)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 {
component_canUnload(TimeValue * pTime)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 //==============================================================================
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment **)1008 void SAL_CALL component_getImplementationEnvironment(
1009 const sal_Char ** ppEnvTypeName, uno_Environment ** )
1010 {
1011 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
1012 }
1013
1014 //==============================================================================
component_getFactory(const sal_Char * pImplName,void * pServiceManager,void * pRegistryKey)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