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 0 : static Sequence< OUString > invadp_getSupportedServiceNames()
67 : {
68 0 : Sequence< OUString > seqNames(1);
69 : seqNames.getArray()[0] =
70 0 : OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
71 0 : return seqNames;
72 : }
73 :
74 0 : static OUString invadp_getImplementationName()
75 : {
76 0 : return OUString(RTL_CONSTASCII_USTRINGPARAM(IMPLNAME));
77 : }
78 :
79 : struct hash_ptr
80 : {
81 0 : inline size_t operator() ( void * p ) const
82 0 : { 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 0 : inline AdapterImpl::~AdapterImpl()
180 : SAL_THROW(())
181 : {
182 0 : for ( sal_Int32 nPos = m_nInterfaces; nPos--; )
183 : {
184 : ::typelib_typedescription_release(
185 0 : (typelib_TypeDescription *)m_pInterfaces[ nPos ].m_pTypeDescr );
186 : }
187 0 : delete [] m_pInterfaces;
188 : //
189 0 : (*m_pReceiver->release)( m_pReceiver );
190 0 : m_pFactory->release();
191 0 : }
192 : //______________________________________________________________________________
193 0 : inline void AdapterImpl::acquire()
194 : SAL_THROW(())
195 : {
196 0 : ::osl_atomic_increment( &m_nRef );
197 0 : }
198 : //______________________________________________________________________________
199 0 : inline void AdapterImpl::release()
200 : SAL_THROW(())
201 : {
202 0 : bool delete_this = false;
203 : {
204 0 : MutexGuard guard( m_pFactory->m_mutex );
205 0 : if (! ::osl_atomic_decrement( &m_nRef ))
206 : {
207 : t_ptr_map::iterator iFind(
208 0 : m_pFactory->m_receiver2adapters.find( m_key ) );
209 : OSL_ASSERT( m_pFactory->m_receiver2adapters.end() != iFind );
210 0 : t_ptr_set & adapter_set = iFind->second;
211 0 : if (adapter_set.erase( this ) != 1) {
212 : OSL_ASSERT( false );
213 : }
214 0 : if (adapter_set.empty())
215 : {
216 0 : m_pFactory->m_receiver2adapters.erase( iFind );
217 : }
218 0 : delete_this = true;
219 0 : }
220 : }
221 0 : if (delete_this)
222 0 : delete this;
223 0 : }
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 0 : 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 0 : pType1->pTypeName->buffer, pType2->pTypeName->buffer )));
245 : }
246 :
247 : //______________________________________________________________________________
248 0 : bool AdapterImpl::coerce_assign(
249 : void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
250 : uno_Any * pOutExc )
251 : {
252 0 : 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 0 : if (::uno_type_assignData(
259 0 : 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 0 : args[ 0 ] = pSource;
268 0 : args[ 1 ] = &pType;
269 : uno_Any exc;
270 0 : uno_Any * p_exc = &exc;
271 :
272 : // converTo()
273 : (*m_pFactory->m_pConverter->pDispatcher)(
274 : m_pFactory->m_pConverter,
275 0 : m_pFactory->m_pConvertToTD, &ret, args, &p_exc );
276 :
277 0 : 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 0 : pDest, pType, ret.pData, ret.pType, 0, 0, 0 ));
306 0 : ::uno_any_destruct( &ret, 0 );
307 : OSL_ENSURE(
308 : succ, "### conversion succeeded, but assignment failed!?" );
309 0 : 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 0 : return succ;
318 : }
319 : }
320 : }
321 : //______________________________________________________________________________
322 0 : inline bool AdapterImpl::coerce_construct(
323 : void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
324 : uno_Any * pExc )
325 : {
326 0 : if (typelib_TypeClass_ANY == pType->eTypeClass)
327 : {
328 0 : ::uno_type_copyData( pDest, pSource, pType, 0 );
329 0 : return true;
330 : }
331 0 : if (type_equals( pType, pSource->pType))
332 : {
333 0 : ::uno_type_copyData( pDest, pSource->pData, pType, 0 );
334 0 : return true;
335 : }
336 0 : ::uno_type_constructData( pDest, pType );
337 0 : 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 0 : void AdapterImpl::invoke(
440 : const typelib_TypeDescription * pMemberType,
441 : void * pReturn, void * pArgs[], uno_Any ** ppException )
442 : {
443 : sal_Int32 nParams =
444 0 : ((typelib_InterfaceMethodTypeDescription *)pMemberType)->nParams;
445 : typelib_MethodParameter * pFormalParams =
446 0 : ((typelib_InterfaceMethodTypeDescription *)pMemberType)->pParams;
447 :
448 : // in params
449 0 : uno_Sequence * pInParamsSeq = 0;
450 : ::uno_sequence_construct(
451 0 : &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0, nParams, 0 );
452 0 : uno_Any * pInAnys = (uno_Any *)pInParamsSeq->elements;
453 0 : sal_Int32 nOutParams = 0;
454 : sal_Int32 nPos;
455 0 : for ( nPos = nParams; nPos--; )
456 : {
457 0 : typelib_MethodParameter const & rParam = pFormalParams[nPos];
458 0 : if (rParam.bIn) // is in/inout param
459 : {
460 : ::uno_type_any_assign(
461 0 : &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef, 0, 0 );
462 : }
463 : // else: pure out is empty any
464 :
465 0 : 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 0 : &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
478 0 : pInvokArgs[1] = &pInParamsSeq;
479 0 : pInvokArgs[2] = &pOutIndices;
480 0 : pInvokArgs[3] = &pOutParams;
481 : uno_Any aInvokExc;
482 0 : uno_Any * pInvokExc = &aInvokExc;
483 :
484 : // invoke() call
485 : (*m_pReceiver->pDispatcher)(
486 : m_pReceiver, m_pFactory->m_pInvokMethodTD,
487 0 : &aInvokRet, pInvokArgs, &pInvokExc );
488 :
489 0 : 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 0 : if (pOutParams->nElements == nOutParams &&
502 : pOutIndices->nElements == nOutParams)
503 : {
504 0 : sal_Int16 * pIndices = (sal_Int16 *)pOutIndices->elements;
505 0 : uno_Any * pOut = (uno_Any *)pOutParams->elements;
506 0 : 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 0 : if (nPos == pOutIndices->nElements)
541 : {
542 : // out param copy ok; write return value
543 0 : if (coerce_construct(
544 : pReturn,
545 : ((typelib_InterfaceMethodTypeDescription *)
546 : pMemberType)->pReturnTypeRef,
547 0 : &aInvokRet, *ppException ))
548 : {
549 0 : *ppException = 0; // no exception
550 : }
551 0 : }
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 0 : ::uno_destructData( &pOutIndices, m_pFactory->m_pShortSeqTD, 0 );
562 0 : ::uno_destructData( &pOutParams, m_pFactory->m_pAnySeqTD, 0 );
563 : // cleanup invok return value
564 0 : ::uno_any_destruct( &aInvokRet, 0 );
565 : }
566 : // cleanup constructed in params
567 0 : ::uno_destructData( &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0 );
568 0 : }
569 :
570 : extern "C"
571 : {
572 : //______________________________________________________________________________
573 0 : static void SAL_CALL adapter_acquire( uno_Interface * pUnoI )
574 : {
575 0 : static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire();
576 0 : }
577 : //______________________________________________________________________________
578 0 : static void SAL_CALL adapter_release( uno_Interface * pUnoI )
579 : {
580 0 : static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release();
581 0 : }
582 : //______________________________________________________________________________
583 0 : 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 0 : switch (((typelib_InterfaceMemberTypeDescription *)pMemberType)->nPosition)
589 : {
590 : case 0: // queryInterface()
591 : {
592 : AdapterImpl * that =
593 0 : static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
594 0 : *ppException = 0; // no exc
595 : typelib_TypeDescriptionReference * pDemanded =
596 0 : *(typelib_TypeDescriptionReference **)pArgs[0];
597 : // pInterfaces[0] is XInterface
598 0 : for ( sal_Int32 nPos = 0; nPos < that->m_nInterfaces; ++nPos )
599 : {
600 : typelib_InterfaceTypeDescription * pTD =
601 0 : that->m_pInterfaces[nPos].m_pTypeDescr;
602 0 : while (pTD)
603 : {
604 0 : if (type_equals(
605 0 : ((typelib_TypeDescription *)pTD)->pWeakRef, pDemanded ))
606 : {
607 0 : uno_Interface * pUnoI2 = &that->m_pInterfaces[nPos];
608 : ::uno_any_construct(
609 : (uno_Any *)pReturn, &pUnoI2,
610 0 : (typelib_TypeDescription *)pTD, 0 );
611 0 : return;
612 : }
613 0 : pTD = pTD->pBaseTypeDescription;
614 : }
615 : }
616 0 : ::uno_any_construct( (uno_Any *)pReturn, 0, 0, 0 ); // clear()
617 0 : 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 0 : static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
632 0 : if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
633 : {
634 0 : 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 0 : 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 0 : m_key( key )
656 : {
657 : // init adapters
658 0 : m_nInterfaces = rTypes.getLength();
659 0 : m_pInterfaces = new InterfaceAdapterImpl[ rTypes.getLength() ];
660 0 : const Type * pTypes = rTypes.getConstArray();
661 0 : for ( sal_Int32 nPos = rTypes.getLength(); nPos--; )
662 : {
663 0 : InterfaceAdapterImpl * pInterface = &m_pInterfaces[nPos];
664 0 : pInterface->acquire = adapter_acquire;
665 0 : pInterface->release = adapter_release;
666 0 : pInterface->pDispatcher = adapter_dispatch;
667 0 : pInterface->m_pAdapter = this;
668 0 : pInterface->m_pTypeDescr = 0;
669 : pTypes[nPos].getDescription(
670 0 : (typelib_TypeDescription **)&pInterface->m_pTypeDescr );
671 : OSL_ASSERT( pInterface->m_pTypeDescr );
672 0 : 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 0 : xReceiver.get(), ::getCppuType( &xReceiver ) );
690 : OSL_ASSERT( 0 != m_pReceiver );
691 0 : if (! m_pReceiver)
692 : {
693 : throw RuntimeException(
694 0 : OUSTR("cannot map receiver!"), Reference< XInterface >() );
695 : }
696 :
697 0 : m_pFactory->acquire();
698 0 : }
699 :
700 : //______________________________________________________________________________
701 0 : 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 0 : m_pConvertToTD( 0 )
709 : {
710 : // C++/UNO bridge
711 0 : OUString aCppEnvTypeName = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
712 0 : OUString aUnoEnvTypeName = OUSTR(UNO_LB_UNO);
713 0 : m_aUno2Cpp = Mapping( aUnoEnvTypeName, aCppEnvTypeName );
714 0 : 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 0 : xContext->getServiceManager()->createInstanceWithContext(
721 : OUString(
722 : RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter") ),
723 0 : xContext ),
724 0 : UNO_QUERY_THROW );
725 : m_pConverter = (uno_Interface *)m_aCpp2Uno.mapInterface(
726 0 : xConverter.get(), ::getCppuType( &xConverter ) );
727 : OSL_ASSERT( 0 != m_pConverter );
728 :
729 : // some type info:
730 : // sequence< any >
731 0 : Type const & rAnySeqType = ::getCppuType( (const Sequence< Any > *)0 );
732 0 : rAnySeqType.getDescription( &m_pAnySeqTD );
733 : // sequence< short >
734 : const Type & rShortSeqType =
735 0 : ::getCppuType( (const Sequence< sal_Int16 > *)0 );
736 0 : rShortSeqType.getDescription( &m_pShortSeqTD );
737 : // script.XInvocation
738 0 : typelib_TypeDescription * pTD = 0;
739 : const Type & rInvType = ::getCppuType(
740 0 : (const Reference< script::XInvocation > *)0 );
741 0 : TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() );
742 : typelib_InterfaceTypeDescription * pITD;
743 0 : pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
744 0 : if( ! pITD->aBase.bComplete )
745 0 : typelib_typedescription_complete( &pTD );
746 : ::typelib_typedescriptionreference_getDescription(
747 0 : &m_pInvokMethodTD, pITD->ppMembers[ 1 ] ); // invoke()
748 : ::typelib_typedescriptionreference_getDescription(
749 0 : &m_pSetValueTD, pITD->ppMembers[ 2 ] ); // setValue()
750 : ::typelib_typedescriptionreference_getDescription(
751 0 : &m_pGetValueTD, pITD->ppMembers[ 3 ] ); // getValue()
752 : // script.XTypeConverter
753 : const Type & rTCType =
754 0 : ::getCppuType( (const Reference< script::XTypeConverter > *)0 );
755 0 : TYPELIB_DANGER_GET( &pTD, rTCType.getTypeLibType() );
756 0 : pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
757 : ::typelib_typedescriptionreference_getDescription(
758 0 : &m_pConvertToTD, pITD->ppMembers[ 0 ] ); // convertTo()
759 0 : TYPELIB_DANGER_RELEASE( pTD );
760 :
761 0 : if (!m_pInvokMethodTD || !m_pSetValueTD || !m_pGetValueTD ||
762 0 : !m_pConvertToTD ||
763 0 : !m_pAnySeqTD || !m_pShortSeqTD)
764 : {
765 : throw RuntimeException(
766 0 : OUSTR("missing type descriptions!"), Reference< XInterface >() );
767 : }
768 :
769 0 : g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
770 0 : }
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 0 : 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 0 : t_ptr_set & adapters_set = map[ key ];
796 0 : *pp_adapter_set = &adapters_set;
797 0 : if (adapters_set.empty())
798 0 : return 0; // shortcut
799 : // find matching adapter
800 0 : Type const * pTypes = rTypes.getConstArray();
801 0 : sal_Int32 nTypes = rTypes.getLength();
802 0 : t_ptr_set::const_iterator iPos( adapters_set.begin() );
803 0 : t_ptr_set::const_iterator const iEnd( adapters_set.end() );
804 0 : while (iEnd != iPos)
805 : {
806 0 : AdapterImpl * that = reinterpret_cast< AdapterImpl * >( *iPos );
807 : // iterate thru all types if that is a matching adapter
808 : sal_Int32 nPosTypes;
809 0 : for ( nPosTypes = nTypes; nPosTypes--; )
810 : {
811 0 : Type const & rType = pTypes[ nPosTypes ];
812 : // find in adapter's type list
813 : sal_Int32 nPos;
814 0 : for ( nPos = that->m_nInterfaces; nPos--; )
815 : {
816 0 : if (::typelib_typedescriptionreference_isAssignableFrom(
817 : rType.getTypeLibType(),
818 : ((typelib_TypeDescription *)that->
819 0 : m_pInterfaces[ nPos ].m_pTypeDescr)->pWeakRef ))
820 : {
821 : // found
822 0 : break;
823 : }
824 : }
825 0 : if (nPos < 0) // type not found => next adapter
826 0 : break;
827 : }
828 0 : if (nPosTypes < 0) // all types found
829 0 : return that;
830 0 : ++iPos;
831 : }
832 0 : return 0;
833 : }
834 :
835 : // XInvocationAdapterFactory2 impl
836 : //______________________________________________________________________________
837 0 : Reference< XInterface > FactoryImpl::createAdapter(
838 : const Reference< script::XInvocation > & xReceiver,
839 : const Sequence< Type > & rTypes )
840 : throw (RuntimeException)
841 : {
842 0 : Reference< XInterface > xRet;
843 0 : if (xReceiver.is() && rTypes.getLength())
844 : {
845 : t_ptr_set * adapter_set;
846 : AdapterImpl * that;
847 0 : Reference< XInterface > xKey( xReceiver, UNO_QUERY );
848 : {
849 0 : ClearableMutexGuard guard( m_mutex );
850 : that = lookup_adapter(
851 0 : &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
852 0 : if (0 == that) // no entry
853 : {
854 0 : guard.clear();
855 : // create adapter; already acquired: m_nRef == 1
856 : AdapterImpl * pNew =
857 0 : new AdapterImpl( xKey.get(), xReceiver, rTypes, this );
858 : // lookup again
859 0 : ClearableMutexGuard guard2( m_mutex );
860 : that = lookup_adapter(
861 0 : &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
862 0 : if (0 == that) // again no entry
863 : {
864 0 : 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 0 : that = pNew;
869 : }
870 : else
871 : {
872 0 : that->acquire();
873 0 : guard2.clear();
874 0 : delete pNew; // has never been inserted
875 0 : }
876 : }
877 : else // found adapter
878 : {
879 0 : that->acquire();
880 0 : }
881 : }
882 : // map one interface to C++
883 0 : uno_Interface * pUnoI = &that->m_pInterfaces[ 0 ];
884 : m_aUno2Cpp.mapInterface(
885 0 : (void **)&xRet, pUnoI, ::getCppuType( &xRet ) );
886 0 : that->release();
887 : OSL_ASSERT( xRet.is() );
888 0 : if (! xRet.is())
889 : {
890 : throw RuntimeException(
891 : OUSTR("mapping UNO to C++ failed!"),
892 0 : Reference< XInterface >() );
893 0 : }
894 : }
895 0 : return xRet;
896 : }
897 : // XInvocationAdapterFactory impl
898 : //______________________________________________________________________________
899 0 : Reference< XInterface > FactoryImpl::createAdapter(
900 : const Reference< script::XInvocation > & xReceiver, const Type & rType )
901 : throw (RuntimeException)
902 : {
903 0 : 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 0 : static Reference< XInterface > SAL_CALL FactoryImpl_create(
935 : const Reference< XComponentContext > & xContext )
936 : throw (Exception)
937 : {
938 0 : 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 0 : SAL_DLLPUBLIC_EXPORT void * SAL_CALL invocadapt_component_getFactory(
971 : const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
972 : {
973 : return ::cppu::component_getFactoryHelper(
974 0 : pImplName, pServiceManager, pRegistryKey , g_entries );
975 : }
976 : }
977 :
978 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|