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