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