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