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 #include <sal/config.h>
21
22 #include <cassert>
23 #include <cstddef>
24 #include <limits>
25
26 #ifdef SAL_UNX
27 #include <sal/alloca.h>
28 #endif
29 #include <o3tl/any.hxx>
30 #include <typelib/typedescription.hxx>
31 #include <uno/data.h>
32
33 #include "base.hxx"
34
35 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
36 #include <com/sun/star/reflection/XIdlField2.hpp>
37 #include <com/sun/star/uno/RuntimeException.hpp>
38 #include <cppuhelper/queryinterface.hxx>
39 #include <cppuhelper/exc_hlp.hxx>
40 #include <cppuhelper/typeprovider.hxx>
41
42 using namespace css::lang;
43 using namespace css::reflection;
44 using namespace css::uno;
45
46 namespace {
47
multipleOf16(std::size_t n)48 std::size_t multipleOf16(std::size_t n) {
49 assert(n <= std::numeric_limits<std::size_t>::max() - 15);
50 return (n + 15) & ~std::size_t(15);
51 }
52
53 }
54
55 namespace stoc_corefl
56 {
57
58 namespace {
59
60 class IdlAttributeFieldImpl
61 : public IdlMemberImpl
62 , public XIdlField
63 , public XIdlField2
64 {
65 public:
getAttributeTypeDescr() const66 typelib_InterfaceAttributeTypeDescription * getAttributeTypeDescr() const
67 { return reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>(getTypeDescr()); }
68
IdlAttributeFieldImpl(IdlReflectionServiceImpl * pReflection,const OUString & rName,typelib_TypeDescription * pTypeDescr,typelib_TypeDescription * pDeclTypeDescr)69 IdlAttributeFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName,
70 typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr )
71 : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr )
72 {}
73
74 // XInterface
75 virtual Any SAL_CALL queryInterface( const Type & rType ) override;
76 virtual void SAL_CALL acquire() noexcept override;
77 virtual void SAL_CALL release() noexcept override;
78
79 // XTypeProvider
80 virtual Sequence< Type > SAL_CALL getTypes() override;
81 virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
82
83 // XIdlMember
84 virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() override;
85 virtual OUString SAL_CALL getName() override;
86 // XIdlField
87 virtual Reference< XIdlClass > SAL_CALL getType() override;
88 virtual FieldAccessMode SAL_CALL getAccessMode() override;
89 virtual Any SAL_CALL get( const Any & rObj ) override;
90 virtual void SAL_CALL set( const Any & rObj, const Any & rValue ) override;
91 // XIdlField2: getType, getAccessMode and get are equal to XIdlField
92 virtual void SAL_CALL set( Any & rObj, const Any & rValue ) override;
93
94 private:
95 void checkException(
96 uno_Any * exception, Reference< XInterface > const & context) const;
97 };
98
99 }
100
101 // XInterface
102
queryInterface(const Type & rType)103 Any IdlAttributeFieldImpl::queryInterface( const Type & rType )
104 {
105 Any aRet( ::cppu::queryInterface( rType,
106 static_cast< XIdlField * >( this ),
107 static_cast< XIdlField2 * >( this ) ) );
108 return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType ));
109 }
110
acquire()111 void IdlAttributeFieldImpl::acquire() noexcept
112 {
113 IdlMemberImpl::acquire();
114 }
115
release()116 void IdlAttributeFieldImpl::release() noexcept
117 {
118 IdlMemberImpl::release();
119 }
120
121 // XTypeProvider
122
getTypes()123 Sequence< Type > IdlAttributeFieldImpl::getTypes()
124 {
125 static cppu::OTypeCollection s_aTypes(
126 cppu::UnoType<XIdlField2>::get(),
127 cppu::UnoType<XIdlField>::get(),
128 IdlMemberImpl::getTypes() );
129
130 return s_aTypes.getTypes();
131 }
132
getImplementationId()133 Sequence< sal_Int8 > IdlAttributeFieldImpl::getImplementationId()
134 {
135 return css::uno::Sequence<sal_Int8>();
136 }
137
138 // XIdlMember
139
getDeclaringClass()140 Reference< XIdlClass > IdlAttributeFieldImpl::getDeclaringClass()
141 {
142 if (! _xDeclClass.is())
143 {
144 ::osl::MutexGuard aGuard( getMutexAccess() );
145 if (! _xDeclClass.is())
146 {
147 OUString aName(getAttributeTypeDescr()->aBase.aBase.pTypeName);
148 sal_Int32 i = aName.indexOf(':');
149 OSL_ASSERT(i >= 0);
150 _xDeclClass = getReflection()->forName(aName.copy(0, i));
151 }
152 }
153 return _xDeclClass;
154 }
155
getName()156 OUString IdlAttributeFieldImpl::getName()
157 {
158 return IdlMemberImpl::getName();
159 }
160
161 // XIdlField
162
getType()163 Reference< XIdlClass > IdlAttributeFieldImpl::getType()
164 {
165 return getReflection()->forType(
166 getAttributeTypeDescr()->pAttributeTypeRef );
167 }
168
getAccessMode()169 FieldAccessMode IdlAttributeFieldImpl::getAccessMode()
170 {
171 return (getAttributeTypeDescr()->bReadOnly
172 ? FieldAccessMode_READONLY : FieldAccessMode_READWRITE);
173 }
174
get(const Any & rObj)175 Any IdlAttributeFieldImpl::get( const Any & rObj )
176 {
177 uno_Interface * pUnoI = getReflection()->mapToUno(
178 rObj, reinterpret_cast<typelib_InterfaceTypeDescription *>(getDeclTypeDescr()) );
179 OSL_ENSURE( pUnoI, "### illegal destination object given!" );
180 if (pUnoI)
181 {
182 TypeDescription aTD( getAttributeTypeDescr()->pAttributeTypeRef );
183 typelib_TypeDescription * pTD = aTD.get();
184
185 uno_Any aExc;
186 uno_Any * pExc = &aExc;
187 void * pReturn = alloca( pTD->nSize );
188
189 (*pUnoI->pDispatcher)( pUnoI, getTypeDescr(), pReturn, nullptr, &pExc );
190 (*pUnoI->release)( pUnoI );
191
192 checkException(pExc, *o3tl::doAccess<Reference<XInterface>>(rObj));
193 Any aRet;
194 uno_any_destruct(
195 &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
196 uno_any_constructAndConvert( &aRet, pReturn, pTD, getReflection()->getUno2Cpp().get() );
197 uno_destructData( pReturn, pTD, nullptr );
198 return aRet;
199 }
200 throw IllegalArgumentException(
201 "illegal object given!",
202 static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
203 }
204
set(Any & rObj,const Any & rValue)205 void IdlAttributeFieldImpl::set( Any & rObj, const Any & rValue )
206 {
207 if (getAttributeTypeDescr()->bReadOnly)
208 {
209 throw IllegalAccessException(
210 "cannot set readonly attribute!",
211 static_cast<XWeak *>(static_cast<OWeakObject *>(this)) );
212 }
213
214 uno_Interface * pUnoI = getReflection()->mapToUno(
215 rObj, reinterpret_cast<typelib_InterfaceTypeDescription *>(getDeclTypeDescr()) );
216 OSL_ENSURE( pUnoI, "### illegal destination object given!" );
217 if (pUnoI)
218 {
219 TypeDescription aTD( getAttributeTypeDescr()->pAttributeTypeRef );
220 typelib_TypeDescription * pTD = aTD.get();
221
222 // construct uno value to be set
223 void * pArgs[1];
224 void * pArg = pArgs[0] = alloca( pTD->nSize );
225
226 bool bAssign;
227 if (pTD->eTypeClass == typelib_TypeClass_ANY)
228 {
229 uno_copyAndConvertData( pArg, const_cast< Any * >(&rValue),
230 pTD, getReflection()->getCpp2Uno().get() );
231 bAssign = true;
232 }
233 else if (typelib_typedescriptionreference_equals( rValue.getValueTypeRef(), pTD->pWeakRef ))
234 {
235 uno_copyAndConvertData( pArg, const_cast< void * >(rValue.getValue()),
236 pTD, getReflection()->getCpp2Uno().get() );
237 bAssign = true;
238 }
239 else if (pTD->eTypeClass == typelib_TypeClass_INTERFACE)
240 {
241 Reference< XInterface > xObj;
242 bAssign = extract(
243 rValue, reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD), xObj,
244 getReflection() );
245 if (bAssign)
246 {
247 *static_cast<void **>(pArg) = getReflection()->getCpp2Uno().mapInterface(
248 xObj.get(), reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD) );
249 }
250 }
251 else
252 {
253 typelib_TypeDescription * pValueTD = nullptr;
254 TYPELIB_DANGER_GET( &pValueTD, rValue.getValueTypeRef() );
255 // construct temp uno val to do proper assignment: todo opt
256 void * pTemp = alloca( pValueTD->nSize );
257 uno_copyAndConvertData(
258 pTemp, const_cast<void *>(rValue.getValue()), pValueTD, getReflection()->getCpp2Uno().get() );
259 uno_constructData(
260 pArg, pTD );
261 // assignment does simple conversion
262 bAssign = uno_assignData(
263 pArg, pTD, pTemp, pValueTD, nullptr, nullptr, nullptr );
264 uno_destructData(
265 pTemp, pValueTD, nullptr );
266 TYPELIB_DANGER_RELEASE( pValueTD );
267 }
268
269 if (bAssign)
270 {
271 uno_Any aExc;
272 uno_Any * pExc = &aExc;
273 (*pUnoI->pDispatcher)( pUnoI, getTypeDescr(), nullptr, pArgs, &pExc );
274 (*pUnoI->release)( pUnoI );
275
276 uno_destructData( pArg, pTD, nullptr );
277 checkException(pExc, *o3tl::doAccess<Reference<XInterface>>(rObj));
278 return;
279 }
280 (*pUnoI->release)( pUnoI );
281
282 throw IllegalArgumentException(
283 "illegal value given!",
284 *o3tl::doAccess<Reference<XInterface>>(rObj), 1 );
285 }
286 throw IllegalArgumentException(
287 "illegal destination object given!",
288 static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
289 }
290
set(const Any & rObj,const Any & rValue)291 void IdlAttributeFieldImpl::set( const Any & rObj, const Any & rValue )
292 {
293 IdlAttributeFieldImpl::set( const_cast< Any & >( rObj ), rValue );
294 }
295
checkException(uno_Any * exception,Reference<XInterface> const & context) const296 void IdlAttributeFieldImpl::checkException(
297 uno_Any * exception, Reference< XInterface > const & context) const
298 {
299 if (exception == nullptr)
300 return;
301
302 Any e;
303 uno_any_destruct(&e, reinterpret_cast< uno_ReleaseFunc >(cpp_release));
304 uno_type_any_constructAndConvert(
305 &e, exception->pData, exception->pType,
306 getReflection()->getUno2Cpp().get());
307 uno_any_destruct(exception, nullptr);
308 if (!e.isExtractableTo(
309 cppu::UnoType<RuntimeException>::get()))
310 {
311 throw WrappedTargetRuntimeException(
312 "non-RuntimeException occurred when accessing an"
313 " interface type attribute",
314 context, e);
315 }
316 cppu::throwException(e);
317 }
318
319 namespace {
320
321 class IdlInterfaceMethodImpl
322 : public IdlMemberImpl
323 , public XIdlMethod
324 {
325 std::optional<Sequence< Reference< XIdlClass > >> m_xExceptionTypes;
326 std::optional<Sequence< Reference< XIdlClass > >> m_xParamTypes;
327 std::optional<Sequence< ParamInfo >> m_xParamInfos;
328
329 public:
getMethodTypeDescr() const330 typelib_InterfaceMethodTypeDescription * getMethodTypeDescr() const
331 { return reinterpret_cast<typelib_InterfaceMethodTypeDescription *>(getTypeDescr()); }
332
IdlInterfaceMethodImpl(IdlReflectionServiceImpl * pReflection,const OUString & rName,typelib_TypeDescription * pTypeDescr,typelib_TypeDescription * pDeclTypeDescr)333 IdlInterfaceMethodImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName,
334 typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr )
335 : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr )
336 {}
337
338 // XInterface
339 virtual Any SAL_CALL queryInterface( const Type & rType ) override;
340 virtual void SAL_CALL acquire() noexcept override;
341 virtual void SAL_CALL release() noexcept override;
342
343 // XTypeProvider
344 virtual Sequence< Type > SAL_CALL getTypes() override;
345 virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
346
347 // XIdlMember
348 virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() override;
349 virtual OUString SAL_CALL getName() override;
350 // XIdlMethod
351 virtual Reference< XIdlClass > SAL_CALL getReturnType() override;
352 virtual Sequence< Reference< XIdlClass > > SAL_CALL getParameterTypes() override;
353 virtual Sequence< ParamInfo > SAL_CALL getParameterInfos() override;
354 virtual Sequence< Reference< XIdlClass > > SAL_CALL getExceptionTypes() override;
355 virtual MethodMode SAL_CALL getMode() override;
356 virtual Any SAL_CALL invoke( const Any & rObj, Sequence< Any > & rArgs ) override;
357 };
358
359 }
360
361 // XInterface
362
queryInterface(const Type & rType)363 Any IdlInterfaceMethodImpl::queryInterface( const Type & rType )
364 {
365 Any aRet( ::cppu::queryInterface( rType, static_cast< XIdlMethod * >( this ) ) );
366 return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType ));
367 }
368
acquire()369 void IdlInterfaceMethodImpl::acquire() noexcept
370 {
371 IdlMemberImpl::acquire();
372 }
373
release()374 void IdlInterfaceMethodImpl::release() noexcept
375 {
376 IdlMemberImpl::release();
377 }
378
379 // XTypeProvider
380
getTypes()381 Sequence< Type > IdlInterfaceMethodImpl::getTypes()
382 {
383 static cppu::OTypeCollection s_aTypes(
384 cppu::UnoType<XIdlMethod>::get(),
385 IdlMemberImpl::getTypes() );
386
387 return s_aTypes.getTypes();
388 }
389
getImplementationId()390 Sequence< sal_Int8 > IdlInterfaceMethodImpl::getImplementationId()
391 {
392 return css::uno::Sequence<sal_Int8>();
393 }
394
395 // XIdlMember
396
getDeclaringClass()397 Reference< XIdlClass > IdlInterfaceMethodImpl::getDeclaringClass()
398 {
399 if (! _xDeclClass.is())
400 {
401 ::osl::MutexGuard aGuard( getMutexAccess() );
402 if (! _xDeclClass.is())
403 {
404 OUString aName(getMethodTypeDescr()->aBase.aBase.pTypeName);
405 sal_Int32 i = aName.indexOf(':');
406 OSL_ASSERT(i >= 0);
407 _xDeclClass = getReflection()->forName(aName.copy(0, i));
408 }
409 }
410 return _xDeclClass;
411 }
412
getName()413 OUString IdlInterfaceMethodImpl::getName()
414 {
415 return IdlMemberImpl::getName();
416 }
417
418 // XIdlMethod
419
getReturnType()420 Reference< XIdlClass > SAL_CALL IdlInterfaceMethodImpl::getReturnType()
421 {
422 return getReflection()->forType( getMethodTypeDescr()->pReturnTypeRef );
423 }
424
getExceptionTypes()425 Sequence< Reference< XIdlClass > > IdlInterfaceMethodImpl::getExceptionTypes()
426 {
427 if (! m_xExceptionTypes)
428 {
429 ::osl::MutexGuard aGuard( getMutexAccess() );
430 if (! m_xExceptionTypes)
431 {
432 sal_Int32 nExc = getMethodTypeDescr()->nExceptions;
433 Sequence< Reference< XIdlClass > > aTempExceptionTypes( nExc );
434 Reference< XIdlClass > * pExceptionTypes = aTempExceptionTypes.getArray();
435
436 typelib_TypeDescriptionReference ** ppExc =
437 getMethodTypeDescr()->ppExceptions;
438 IdlReflectionServiceImpl * pRefl = getReflection();
439
440 while (nExc--)
441 pExceptionTypes[nExc] = pRefl->forType( ppExc[nExc] );
442
443 m_xExceptionTypes = std::move(aTempExceptionTypes);
444 }
445 }
446 return *m_xExceptionTypes;
447 }
448
getParameterTypes()449 Sequence< Reference< XIdlClass > > IdlInterfaceMethodImpl::getParameterTypes()
450 {
451 if (! m_xParamTypes)
452 {
453 ::osl::MutexGuard aGuard( getMutexAccess() );
454 if (! m_xParamTypes)
455 {
456 sal_Int32 nParams = getMethodTypeDescr()->nParams;
457 Sequence< Reference< XIdlClass > > aTempParamTypes( nParams );
458 Reference< XIdlClass > * pParamTypes = aTempParamTypes.getArray();
459
460 typelib_MethodParameter * pTypelibParams =
461 getMethodTypeDescr()->pParams;
462 IdlReflectionServiceImpl * pRefl = getReflection();
463
464 while (nParams--)
465 pParamTypes[nParams] = pRefl->forType( pTypelibParams[nParams].pTypeRef );
466
467 m_xParamTypes = std::move(aTempParamTypes);
468 }
469 }
470 return *m_xParamTypes;
471 }
472
getParameterInfos()473 Sequence< ParamInfo > IdlInterfaceMethodImpl::getParameterInfos()
474 {
475 if (! m_xParamInfos)
476 {
477 ::osl::MutexGuard aGuard( getMutexAccess() );
478 if (! m_xParamInfos)
479 {
480 sal_Int32 nParams = getMethodTypeDescr()->nParams;
481 Sequence< ParamInfo > aTempParamInfos( nParams );
482 ParamInfo * pParamInfos = aTempParamInfos.getArray();
483
484 typelib_MethodParameter * pTypelibParams =
485 getMethodTypeDescr()->pParams;
486
487 if (m_xParamTypes) // use param types
488 {
489 const Reference< XIdlClass > * pParamTypes = m_xParamTypes->getConstArray();
490
491 while (nParams--)
492 {
493 const typelib_MethodParameter & rParam = pTypelibParams[nParams];
494 ParamInfo & rInfo = pParamInfos[nParams];
495 rInfo.aName = rParam.pName;
496 if (rParam.bIn)
497 rInfo.aMode = (rParam.bOut ? ParamMode_INOUT : ParamMode_IN);
498 else
499 rInfo.aMode = ParamMode_OUT;
500 rInfo.aType = pParamTypes[nParams];
501 }
502 }
503 else // make also param types sequence if not already initialized
504 {
505 Sequence< Reference< XIdlClass > > aTempParamTypes( nParams );
506 Reference< XIdlClass > * pParamTypes = aTempParamTypes.getArray();
507
508 IdlReflectionServiceImpl * pRefl = getReflection();
509
510 while (nParams--)
511 {
512 const typelib_MethodParameter & rParam = pTypelibParams[nParams];
513 ParamInfo & rInfo = pParamInfos[nParams];
514 rInfo.aName = rParam.pName;
515 if (rParam.bIn)
516 rInfo.aMode = (rParam.bOut ? ParamMode_INOUT : ParamMode_IN);
517 else
518 rInfo.aMode = ParamMode_OUT;
519 rInfo.aType = pParamTypes[nParams] = pRefl->forType( rParam.pTypeRef );
520 }
521
522 m_xParamTypes = std::move(aTempParamTypes);
523 }
524
525 m_xParamInfos = std::move(aTempParamInfos);
526 }
527 }
528 return *m_xParamInfos;
529 }
530
getMode()531 MethodMode SAL_CALL IdlInterfaceMethodImpl::getMode()
532 {
533 return
534 getMethodTypeDescr()->bOneWay ? MethodMode_ONEWAY : MethodMode_TWOWAY;
535 }
536
invoke(const Any & rObj,Sequence<Any> & rArgs)537 Any SAL_CALL IdlInterfaceMethodImpl::invoke( const Any & rObj, Sequence< Any > & rArgs )
538 {
539 if (auto ifc = o3tl::tryAccess<css::uno::Reference<css::uno::XInterface>>(
540 rObj))
541 {
542 // acquire()/ release()
543 if (rtl_ustr_ascii_compare( getTypeDescr()->pTypeName->buffer,
544 "com.sun.star.uno.XInterface::acquire" ) == 0)
545 {
546 (*ifc)->acquire();
547 return Any();
548 }
549 else if (rtl_ustr_ascii_compare( getTypeDescr()->pTypeName->buffer,
550 "com.sun.star.uno.XInterface::release" ) == 0)
551 {
552 (*ifc)->release();
553 return Any();
554 }
555 }
556
557 uno_Interface * pUnoI = getReflection()->mapToUno(
558 rObj, reinterpret_cast<typelib_InterfaceTypeDescription *>(getDeclTypeDescr()) );
559 OSL_ENSURE( pUnoI, "### illegal destination object given!" );
560 if (pUnoI)
561 {
562 sal_Int32 nParams = getMethodTypeDescr()->nParams;
563 if (rArgs.getLength() != nParams)
564 {
565 (*pUnoI->release)( pUnoI );
566 throw IllegalArgumentException(
567 "expected " + OUString::number(nParams) +
568 " arguments, got " + OUString::number(rArgs.getLength()),
569 *o3tl::doAccess<Reference<XInterface>>(rObj), 1 );
570 }
571
572 Any * pCppArgs = rArgs.getArray();
573 typelib_MethodParameter * pParams = getMethodTypeDescr()->pParams;
574 typelib_TypeDescription * pReturnType = nullptr;
575 TYPELIB_DANGER_GET(
576 &pReturnType, getMethodTypeDescr()->pReturnTypeRef );
577
578 // C/C++ ABIs typically assume that structs are padded at the end, and
579 // that those padding bytes may be written to (e.g., to write into the
580 // end of a "short" struct by writing the full contents of a "long"
581 // register); so create enough space here (assuming that no ABI requires
582 // padding larger than 16 byte boundaries):
583 void * pUnoReturn = (pReturnType->nSize == 0) ? nullptr : alloca( multipleOf16(pReturnType->nSize) );
584 void ** ppUnoArgs = static_cast<void **>(alloca( sizeof(void *) * nParams *2 ));
585 typelib_TypeDescription ** ppParamTypes = reinterpret_cast<typelib_TypeDescription **>(ppUnoArgs + nParams);
586
587 // convert arguments
588 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
589 {
590 ppParamTypes[nPos] = nullptr;
591 TYPELIB_DANGER_GET( ppParamTypes + nPos, pParams[nPos].pTypeRef );
592 typelib_TypeDescription * pTD = ppParamTypes[nPos];
593
594 ppUnoArgs[nPos] = alloca( pTD->nSize );
595 if (pParams[nPos].bIn)
596 {
597 bool bAssign;
598 if (typelib_typedescriptionreference_equals(
599 pCppArgs[nPos].getValueTypeRef(), pTD->pWeakRef ))
600 {
601 uno_type_copyAndConvertData(
602 ppUnoArgs[nPos], const_cast<void *>(pCppArgs[nPos].getValue()),
603 pCppArgs[nPos].getValueTypeRef(), getReflection()->getCpp2Uno().get() );
604 bAssign = true;
605 }
606 else if (pTD->eTypeClass == typelib_TypeClass_ANY)
607 {
608 uno_type_any_constructAndConvert(
609 static_cast<uno_Any *>(ppUnoArgs[nPos]), const_cast<void *>(pCppArgs[nPos].getValue()),
610 pCppArgs[nPos].getValueTypeRef(), getReflection()->getCpp2Uno().get() );
611 bAssign = true;
612 }
613 else if (pTD->eTypeClass == typelib_TypeClass_INTERFACE)
614 {
615 Reference< XInterface > xDest;
616 bAssign = extract(
617 pCppArgs[nPos], reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD),
618 xDest, getReflection() );
619 if (bAssign)
620 {
621 *static_cast<void **>(ppUnoArgs[nPos]) = getReflection()->getCpp2Uno().mapInterface(
622 xDest.get(), reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD) );
623 }
624 }
625 else
626 {
627 typelib_TypeDescription * pValueTD = nullptr;
628 TYPELIB_DANGER_GET( &pValueTD, pCppArgs[nPos].getValueTypeRef() );
629 // construct temp uno val to do proper assignment: todo opt
630 void * pTemp = alloca( pValueTD->nSize );
631 uno_copyAndConvertData(
632 pTemp, const_cast<void *>(pCppArgs[nPos].getValue()), pValueTD,
633 getReflection()->getCpp2Uno().get() );
634 uno_constructData(
635 ppUnoArgs[nPos], pTD );
636 // assignment does simple conversion
637 bAssign = uno_assignData(
638 ppUnoArgs[nPos], pTD, pTemp, pValueTD, nullptr, nullptr, nullptr );
639 uno_destructData(
640 pTemp, pValueTD, nullptr );
641 TYPELIB_DANGER_RELEASE( pValueTD );
642 }
643
644 if (! bAssign)
645 {
646 IllegalArgumentException aExc(
647 "cannot coerce argument type during corereflection call:"
648 "\narg no.: " + OUString::number(nPos)
649 + " expected: \"" + OUString::unacquired(&pTD->pTypeName)
650 + "\" actual: \"" + OUString::unacquired(&pCppArgs[nPos].getValueTypeRef()->pTypeName)
651 + "\"",
652 *o3tl::doAccess<Reference<XInterface>>(rObj), static_cast<sal_Int16>(nPos) );
653
654 // cleanup
655 while (nPos--)
656 {
657 if (pParams[nPos].bIn)
658 uno_destructData( ppUnoArgs[nPos], ppParamTypes[nPos], nullptr );
659 TYPELIB_DANGER_RELEASE( ppParamTypes[nPos] );
660 }
661 TYPELIB_DANGER_RELEASE( pReturnType );
662 (*pUnoI->release)( pUnoI );
663
664 throw aExc;
665 }
666 }
667 }
668
669 uno_Any aUnoExc;
670 uno_Any * pUnoExc = &aUnoExc;
671
672 (*pUnoI->pDispatcher)(
673 pUnoI, getTypeDescr(), pUnoReturn, ppUnoArgs, &pUnoExc );
674 (*pUnoI->release)( pUnoI );
675
676 Any aRet;
677 if (pUnoExc)
678 {
679 // cleanup
680 while (nParams--)
681 {
682 if (pParams[nParams].bIn)
683 uno_destructData( ppUnoArgs[nParams], ppParamTypes[nParams], nullptr );
684 TYPELIB_DANGER_RELEASE( ppParamTypes[nParams] );
685 }
686 TYPELIB_DANGER_RELEASE( pReturnType );
687
688 InvocationTargetException aExc;
689 aExc.Context = *o3tl::doAccess<Reference<XInterface>>(rObj);
690 aExc.Message = "exception occurred during invocation!";
691 uno_any_destruct(
692 &aExc.TargetException,
693 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
694 uno_type_copyAndConvertData(
695 &aExc.TargetException, pUnoExc, cppu::UnoType<Any>::get().getTypeLibType(),
696 getReflection()->getUno2Cpp().get() );
697 uno_any_destruct( pUnoExc, nullptr );
698 throw aExc;
699 }
700 else
701 {
702 // reconvert arguments and cleanup
703 while (nParams--)
704 {
705 if (pParams[nParams].bOut) // write back
706 {
707 uno_any_destruct(
708 &pCppArgs[nParams],
709 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
710 uno_any_constructAndConvert(
711 &pCppArgs[nParams], ppUnoArgs[nParams], ppParamTypes[nParams],
712 getReflection()->getUno2Cpp().get() );
713 }
714 uno_destructData( ppUnoArgs[nParams], ppParamTypes[nParams], nullptr );
715 TYPELIB_DANGER_RELEASE( ppParamTypes[nParams] );
716 }
717 uno_any_destruct(
718 &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
719 uno_any_constructAndConvert(
720 &aRet, pUnoReturn, pReturnType,
721 getReflection()->getUno2Cpp().get() );
722 uno_destructData( pUnoReturn, pReturnType, nullptr );
723 TYPELIB_DANGER_RELEASE( pReturnType );
724 }
725 return aRet;
726 }
727 throw IllegalArgumentException(
728 "illegal destination object given!",
729 static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
730 }
731
732
~InterfaceIdlClassImpl()733 InterfaceIdlClassImpl::~InterfaceIdlClassImpl()
734 {
735 for ( sal_Int32 nPos = _nMethods + _nAttributes; nPos--; )
736 typelib_typedescription_release( _pSortedMemberInit[nPos].second );
737 }
738
739
getSuperclasses()740 Sequence< Reference< XIdlClass > > InterfaceIdlClassImpl::getSuperclasses()
741 {
742 ::osl::MutexGuard aGuard(getMutexAccess());
743 if (!_xSuperClasses.hasElements()) {
744 typelib_InterfaceTypeDescription * pType = getTypeDescr();
745 _xSuperClasses.realloc(pType->nBaseTypes);
746 for (sal_Int32 i = 0; i < pType->nBaseTypes; ++i) {
747 _xSuperClasses[i] = getReflection()->forType(
748 &pType->ppBaseTypes[i]->aBase);
749 OSL_ASSERT(_xSuperClasses[i].is());
750 }
751 }
752 return _xSuperClasses;
753 }
754
initMembers()755 void InterfaceIdlClassImpl::initMembers()
756 {
757 sal_Int32 nAll = getTypeDescr()->nAllMembers;
758 std::unique_ptr<MemberInit[]> pSortedMemberInit(new MemberInit[nAll]);
759 typelib_TypeDescriptionReference ** ppAllMembers = getTypeDescr()->ppAllMembers;
760
761 for ( sal_Int32 nPos = 0; nPos < nAll; ++nPos )
762 {
763 sal_Int32 nIndex;
764 if (ppAllMembers[nPos]->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
765 {
766 // methods to front
767 nIndex = _nMethods;
768 ++_nMethods;
769 }
770 else
771 {
772 ++_nAttributes;
773 nIndex = (nAll - _nAttributes);
774 // attributes at the back
775 }
776
777 typelib_TypeDescription * pTD = nullptr;
778 typelib_typedescriptionreference_getDescription( &pTD, ppAllMembers[nPos] );
779 assert(pTD && "### cannot get type description!");
780 pSortedMemberInit[nIndex].first = reinterpret_cast<typelib_InterfaceMemberTypeDescription *>(pTD)->pMemberName;
781 pSortedMemberInit[nIndex].second = pTD;
782 }
783
784 _pSortedMemberInit = std::move(pSortedMemberInit);
785 }
786
isAssignableFrom(const Reference<XIdlClass> & xType)787 sal_Bool InterfaceIdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType )
788 {
789 if (xType.is() && xType->getTypeClass() == TypeClass_INTERFACE)
790 {
791 if (equals( xType ))
792 return true;
793 else
794 {
795 const Sequence< Reference< XIdlClass > > & rSeq = xType->getSuperclasses();
796 if (std::any_of(rSeq.begin(), rSeq.end(),
797 [this](const Reference<XIdlClass>& rType){ return isAssignableFrom(rType); }))
798 return true;
799 }
800 }
801 return false;
802 }
803
getUik()804 Uik InterfaceIdlClassImpl::getUik()
805 {
806 return Uik(0, 0, 0, 0, 0);
807 // Uiks are deprecated and this function must not be called
808 }
809
getMethods()810 Sequence< Reference< XIdlMethod > > InterfaceIdlClassImpl::getMethods()
811 {
812 ::osl::MutexGuard aGuard( getMutexAccess() );
813 if (! _pSortedMemberInit)
814 initMembers();
815
816 // create methods sequence
817 Sequence< Reference< XIdlMethod > > aRet( _nMethods );
818 Reference< XIdlMethod > * pRet = aRet.getArray();
819 for ( sal_Int32 nPos = _nMethods; nPos--; )
820 {
821
822 /*_aName2Method[_pSortedMemberInit[nPos].first] = */pRet[nPos] = new IdlInterfaceMethodImpl(
823 getReflection(), _pSortedMemberInit[nPos].first,
824 _pSortedMemberInit[nPos].second, IdlClassImpl::getTypeDescr() );
825 }
826 return aRet;
827 }
828
getFields()829 Sequence< Reference< XIdlField > > InterfaceIdlClassImpl::getFields()
830 {
831 ::osl::MutexGuard aGuard( getMutexAccess() );
832 if (! _pSortedMemberInit)
833 initMembers();
834
835 // create fields sequence
836 Sequence< Reference< XIdlField > > aRet( _nAttributes );
837 Reference< XIdlField > * pRet = aRet.getArray();
838 for ( sal_Int32 nPos = _nAttributes; nPos--; )
839 {
840 /*_aName2Field[_pSortedMemberInit[_nMethods+nPos].first] = */pRet[_nAttributes-nPos-1] =
841 new IdlAttributeFieldImpl(
842 getReflection(), _pSortedMemberInit[_nMethods+nPos].first,
843 _pSortedMemberInit[_nMethods+nPos].second, IdlClassImpl::getTypeDescr() );
844 }
845 return aRet;
846 }
847
getMethod(const OUString & rName)848 Reference< XIdlMethod > InterfaceIdlClassImpl::getMethod( const OUString & rName )
849 {
850 ::osl::MutexGuard aGuard( getMutexAccess() );
851 if (! _pSortedMemberInit)
852 initMembers();
853
854 Reference< XIdlMethod > xRet;
855
856 // try weak map
857 const OUString2Method::const_iterator iFind( _aName2Method.find( rName ) );
858 if (iFind != _aName2Method.end())
859 xRet = (*iFind).second; // harden ref
860
861 if (! xRet.is())
862 {
863 for ( sal_Int32 nPos = _nMethods; nPos--; )
864 {
865 if (_pSortedMemberInit[nPos].first == rName)
866 {
867 _aName2Method[rName] = xRet = new IdlInterfaceMethodImpl(
868 getReflection(), rName,
869 _pSortedMemberInit[nPos].second, IdlClassImpl::getTypeDescr() );
870 break;
871 }
872 }
873 }
874 return xRet;
875 }
876
getField(const OUString & rName)877 Reference< XIdlField > InterfaceIdlClassImpl::getField( const OUString & rName )
878 {
879 ::osl::MutexGuard aGuard( getMutexAccess() );
880 if (! _pSortedMemberInit)
881 initMembers();
882
883 Reference< XIdlField > xRet;
884
885 // try weak map
886 const OUString2Field::const_iterator iFind( _aName2Field.find( rName ) );
887 if (iFind != _aName2Field.end())
888 xRet = (*iFind).second; // harden ref
889
890 if (! xRet.is())
891 {
892 for ( sal_Int32 nPos = _nAttributes; nPos--; )
893 {
894 if (_pSortedMemberInit[_nMethods+nPos].first == rName)
895 {
896 _aName2Field[rName] = xRet = new IdlAttributeFieldImpl(
897 getReflection(), rName,
898 _pSortedMemberInit[_nMethods+nPos].second, IdlClassImpl::getTypeDescr() );
899 break;
900 }
901 }
902 }
903 return xRet;
904 }
905
createObject(Any & rObj)906 void InterfaceIdlClassImpl::createObject( Any & rObj )
907 {
908 // interfaces cannot be constructed
909 rObj.clear();
910 }
911
912 }
913
914
915 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
916