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