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