1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <sal/config.h>
22 #include <sal/log.hxx>
26 #include <osl/diagnose.h>
27 #include <rtl/ustring.hxx>
29 #include <uno/lbnames.h>
30 #include <uno/mapping.hxx>
32 #include <cppuhelper/bootstrap.hxx>
33 #include <cppuhelper/implbase.hxx>
34 #include <typelib/typedescription.h>
36 #include <com/sun/star/lang/XComponent.hpp>
37 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
38 #include <com/sun/star/reflection/XTypeDescription.hpp>
39 #include <com/sun/star/reflection/XEnumTypeDescription.hpp>
40 #include <com/sun/star/reflection/XIndirectTypeDescription.hpp>
41 #include <com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp>
42 #include <com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp>
43 #include <com/sun/star/reflection/XMethodParameter.hpp>
44 #include <com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp>
45 #include <com/sun/star/reflection/XInterfaceTypeDescription2.hpp>
46 #include <com/sun/star/reflection/XCompoundTypeDescription.hpp>
47 #include <com/sun/star/reflection/XStructTypeDescription.hpp>
51 using namespace ::com::sun::star
;
52 using namespace ::com::sun::star::uno
;
53 using namespace ::com::sun::star::reflection
;
58 static typelib_TypeDescription
* createCTD(
59 Reference
< container::XHierarchicalNameAccess
> const & access
,
60 const Reference
< XTypeDescription
> & xType
);
63 static typelib_TypeDescription
* createCTD(
64 const Reference
< XCompoundTypeDescription
> & xType
)
66 typelib_TypeDescription
* pRet
= nullptr;
69 typelib_TypeDescription
* pBaseType
= createCTD(
70 Reference
< XCompoundTypeDescription
>::query( xType
->getBaseType() ) );
72 typelib_typedescription_register( &pBaseType
);
74 // construct member init array
75 const Sequence
<Reference
< XTypeDescription
> > & rMemberTypes
= xType
->getMemberTypes();
76 const Sequence
< OUString
> & rMemberNames
= xType
->getMemberNames();
78 const Reference
< XTypeDescription
> * pMemberTypes
= rMemberTypes
.getConstArray();
79 const OUString
* pMemberNames
= rMemberNames
.getConstArray();
81 sal_Int32 nMembers
= rMemberTypes
.getLength();
82 OSL_ENSURE( nMembers
== rMemberNames
.getLength(), "### lens differ!" );
84 OUString
aTypeName( xType
->getName() );
86 typelib_CompoundMember_Init
* pMemberInits
= static_cast<typelib_CompoundMember_Init
*>(alloca(
87 sizeof(typelib_CompoundMember_Init
) * nMembers
));
90 for ( nPos
= nMembers
; nPos
--; )
92 typelib_CompoundMember_Init
& rInit
= pMemberInits
[nPos
];
93 rInit
.eTypeClass
= static_cast<typelib_TypeClass
>(pMemberTypes
[nPos
]->getTypeClass());
95 OUString
aMemberTypeName( pMemberTypes
[nPos
]->getName() );
96 rInit
.pTypeName
= aMemberTypeName
.pData
;
97 rtl_uString_acquire( rInit
.pTypeName
);
99 // string is held by rMemberNames
100 rInit
.pMemberName
= pMemberNames
[nPos
].pData
;
103 typelib_typedescription_new(
105 static_cast<typelib_TypeClass
>(xType
->getTypeClass()),
107 (pBaseType
? pBaseType
->pWeakRef
: nullptr),
108 nMembers
, pMemberInits
);
111 for ( nPos
= nMembers
; nPos
--; )
113 rtl_uString_release( pMemberInits
[nPos
].pTypeName
);
116 typelib_typedescription_release( pBaseType
);
121 static typelib_TypeDescription
* createCTD(
122 Reference
< container::XHierarchicalNameAccess
> const & access
,
123 const Reference
< XStructTypeDescription
> & xType
)
125 typelib_TypeDescription
* pRet
= nullptr;
126 if (xType
.is() && !xType
->getTypeParameters().hasElements())
128 typelib_TypeDescription
* pBaseType
= createCTD(
129 access
, xType
->getBaseType() );
131 typelib_typedescription_register( &pBaseType
);
133 // construct member init array
134 const Sequence
<Reference
< XTypeDescription
> > & rMemberTypes
= xType
->getMemberTypes();
135 const Sequence
< OUString
> & rMemberNames
= xType
->getMemberNames();
137 const Reference
< XTypeDescription
> * pMemberTypes
= rMemberTypes
.getConstArray();
138 const OUString
* pMemberNames
= rMemberNames
.getConstArray();
140 sal_Int32 nMembers
= rMemberTypes
.getLength();
141 OSL_ENSURE( nMembers
== rMemberNames
.getLength(), "### lens differ!" );
143 OUString
aTypeName( xType
->getName() );
145 typelib_StructMember_Init
* pMemberInits
= static_cast<typelib_StructMember_Init
*>(alloca(
146 sizeof(typelib_StructMember_Init
) * nMembers
));
148 Sequence
< Reference
< XTypeDescription
> > templateMemberTypes
;
149 sal_Int32 i
= aTypeName
.indexOf('<');
151 Reference
< XStructTypeDescription
> templateDesc(
152 access
->getByHierarchicalName(aTypeName
.copy(0, i
)),
155 templateDesc
->getTypeParameters().getLength()
156 == xType
->getTypeArguments().getLength());
157 templateMemberTypes
= templateDesc
->getMemberTypes();
158 OSL_ASSERT(templateMemberTypes
.getLength() == nMembers
);
162 for ( nPos
= nMembers
; nPos
--; )
164 typelib_StructMember_Init
& rInit
= pMemberInits
[nPos
];
165 rInit
.aBase
.eTypeClass
166 = static_cast<typelib_TypeClass
>(pMemberTypes
[nPos
]->getTypeClass());
168 OUString
aMemberTypeName( pMemberTypes
[nPos
]->getName() );
169 rInit
.aBase
.pTypeName
= aMemberTypeName
.pData
;
170 rtl_uString_acquire( rInit
.aBase
.pTypeName
);
172 // string is held by rMemberNames
173 rInit
.aBase
.pMemberName
= pMemberNames
[nPos
].pData
;
175 rInit
.bParameterizedType
= templateMemberTypes
.hasElements()
176 && (templateMemberTypes
[nPos
]->getTypeClass()
177 == TypeClass_UNKNOWN
);
180 typelib_typedescription_newStruct(
183 (pBaseType
? pBaseType
->pWeakRef
: nullptr),
184 nMembers
, pMemberInits
);
187 for ( nPos
= nMembers
; nPos
--; )
189 rtl_uString_release( pMemberInits
[nPos
].aBase
.pTypeName
);
192 typelib_typedescription_release( pBaseType
);
197 static typelib_TypeDescription
* createCTD(
198 const Reference
< XInterfaceAttributeTypeDescription2
> & xAttribute
)
200 typelib_TypeDescription
* pRet
= nullptr;
203 OUString
aMemberName( xAttribute
->getName() );
204 Reference
< XTypeDescription
> xType( xAttribute
->getType() );
205 OUString
aMemberTypeName( xType
->getName() );
206 std::vector
< rtl_uString
* > getExc
;
207 const Sequence
< Reference
< XCompoundTypeDescription
> > getExcs(
208 xAttribute
->getGetExceptions() );
209 for (const auto & ctd
: getExcs
)
211 OSL_ASSERT( ctd
.is() );
212 getExc
.push_back( ctd
->getName().pData
);
214 std::vector
< rtl_uString
* > setExc
;
215 const Sequence
< Reference
< XCompoundTypeDescription
> > setExcs(
216 xAttribute
->getSetExceptions() );
217 for (const auto & ctd
: setExcs
)
219 OSL_ASSERT( ctd
.is() );
220 setExc
.push_back( ctd
->getName().pData
);
222 typelib_typedescription_newExtendedInterfaceAttribute(
223 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
**>(&pRet
),
224 xAttribute
->getPosition(),
225 aMemberName
.pData
, // name
226 static_cast<typelib_TypeClass
>(xType
->getTypeClass()),
227 aMemberTypeName
.pData
, // type name
228 xAttribute
->isReadOnly(),
229 getExc
.size(), getExc
.data(),
230 setExc
.size(), setExc
.data() );
235 static typelib_TypeDescription
* createCTD(
236 const Reference
< XInterfaceMethodTypeDescription
> & xMethod
)
238 typelib_TypeDescription
* pRet
= nullptr;
241 Reference
< XTypeDescription
> xReturnType( xMethod
->getReturnType() );
244 const Sequence
<Reference
< XMethodParameter
> > & rParams
= xMethod
->getParameters();
245 const Reference
< XMethodParameter
> * pParams
= rParams
.getConstArray();
246 sal_Int32 nParams
= rParams
.getLength();
248 typelib_Parameter_Init
* pParamInit
= static_cast<typelib_Parameter_Init
*>(alloca(
249 sizeof(typelib_Parameter_Init
) * nParams
));
252 for ( nPos
= nParams
; nPos
--; )
254 const Reference
< XMethodParameter
> & xParam
= pParams
[nPos
];
255 const Reference
< XTypeDescription
> & xType
= xParam
->getType();
256 typelib_Parameter_Init
& rInit
= pParamInit
[xParam
->getPosition()];
258 rInit
.eTypeClass
= static_cast<typelib_TypeClass
>(xType
->getTypeClass());
259 OUString
aParamTypeName( xType
->getName() );
260 rInit
.pTypeName
= aParamTypeName
.pData
;
261 rtl_uString_acquire( rInit
.pTypeName
);
262 OUString
aParamName( xParam
->getName() );
263 rInit
.pParamName
= aParamName
.pData
;
264 rtl_uString_acquire( rInit
.pParamName
);
265 rInit
.bIn
= xParam
->isIn();
266 rInit
.bOut
= xParam
->isOut();
269 // init all exception strings
270 const Sequence
<Reference
< XTypeDescription
> > & rExceptions
= xMethod
->getExceptions();
271 const Reference
< XTypeDescription
> * pExceptions
= rExceptions
.getConstArray();
272 sal_Int32 nExceptions
= rExceptions
.getLength();
273 rtl_uString
** ppExceptionNames
= static_cast<rtl_uString
**>(alloca(
274 sizeof(rtl_uString
*) * nExceptions
));
276 for ( nPos
= nExceptions
; nPos
--; )
278 OUString
aExceptionTypeName( pExceptions
[nPos
]->getName() );
279 ppExceptionNames
[nPos
] = aExceptionTypeName
.pData
;
280 rtl_uString_acquire( ppExceptionNames
[nPos
] );
283 OUString
aTypeName( xMethod
->getName() );
284 OUString
aReturnTypeName( xReturnType
->getName() );
286 typelib_typedescription_newInterfaceMethod(
287 reinterpret_cast<typelib_InterfaceMethodTypeDescription
**>(&pRet
),
288 xMethod
->getPosition(),
291 static_cast<typelib_TypeClass
>(xReturnType
->getTypeClass()),
292 aReturnTypeName
.pData
,
294 nExceptions
, ppExceptionNames
);
296 for ( nPos
= nParams
; nPos
--; )
298 rtl_uString_release( pParamInit
[nPos
].pTypeName
);
299 rtl_uString_release( pParamInit
[nPos
].pParamName
);
301 for ( nPos
= nExceptions
; nPos
--; )
303 rtl_uString_release( ppExceptionNames
[nPos
] );
309 static typelib_TypeDescription
* createCTD(
310 Reference
< container::XHierarchicalNameAccess
> const & access
,
311 const Reference
< XInterfaceTypeDescription2
> & xType
)
313 typelib_TypeDescription
* pRet
= nullptr;
316 Sequence
< Reference
< XTypeDescription
> > aBases(xType
->getBaseTypes());
317 sal_Int32 nBases
= aBases
.getLength();
318 // Exploit the fact that a typelib_TypeDescription for an interface type
319 // is also the typelib_TypeDescriptionReference for that type:
320 std::unique_ptr
< typelib_TypeDescription
* []> aBaseTypes(
321 new typelib_TypeDescription
*[nBases
]);
322 for (sal_Int32 i
= 0; i
< nBases
; ++i
) {
323 typelib_TypeDescription
* p
= createCTD(access
, aBases
[i
]);
325 !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(p
->eTypeClass
));
326 typelib_typedescription_register(&p
);
329 typelib_TypeDescriptionReference
** pBaseTypeRefs
330 = reinterpret_cast< typelib_TypeDescriptionReference
** >(
333 // construct all member refs
334 const Sequence
<Reference
< XInterfaceMemberTypeDescription
> > & rMembers
= xType
->getMembers();
335 sal_Int32 nMembers
= rMembers
.getLength();
337 typelib_TypeDescriptionReference
** ppMemberRefs
= static_cast<typelib_TypeDescriptionReference
**>(alloca(
338 sizeof(typelib_TypeDescriptionReference
*) * nMembers
));
340 const Reference
< XInterfaceMemberTypeDescription
> * pMembers
= rMembers
.getConstArray();
342 OUString
aTypeName( xType
->getName() );
345 for ( nPos
= nMembers
; nPos
--; )
347 OUString
aMemberTypeName( pMembers
[nPos
]->getName() );
348 ppMemberRefs
[nPos
] = nullptr;
349 typelib_typedescriptionreference_new(
351 static_cast<typelib_TypeClass
>(pMembers
[nPos
]->getTypeClass()),
352 aMemberTypeName
.pData
);
355 typelib_typedescription_newMIInterface(
356 reinterpret_cast<typelib_InterfaceTypeDescription
**>(&pRet
),
359 nBases
, pBaseTypeRefs
,
360 nMembers
, ppMemberRefs
);
362 // cleanup refs and base type
363 for (int i
= 0; i
< nBases
; ++i
) {
364 typelib_typedescription_release(aBaseTypes
[i
]);
367 for ( nPos
= nMembers
; nPos
--; )
369 typelib_typedescriptionreference_release( ppMemberRefs
[nPos
] );
375 static typelib_TypeDescription
* createCTD( const Reference
< XEnumTypeDescription
> & xType
)
377 typelib_TypeDescription
* pRet
= nullptr;
380 OUString
aTypeName( xType
->getName() );
381 Sequence
< OUString
> aNames( xType
->getEnumNames() );
382 OSL_ASSERT( sizeof(OUString
) == sizeof(rtl_uString
*) ); // !!!
383 Sequence
< sal_Int32
> aValues( xType
->getEnumValues() );
385 typelib_typedescription_newEnum(
386 &pRet
, aTypeName
.pData
, xType
->getDefaultEnumValue(),
388 const_cast<rtl_uString
**>(reinterpret_cast<rtl_uString
* const *>(aNames
.getConstArray())),
389 const_cast< sal_Int32
* >( aValues
.getConstArray() ) );
394 static typelib_TypeDescription
* createCTD(
395 Reference
< container::XHierarchicalNameAccess
> const & access
,
396 const Reference
< XIndirectTypeDescription
> & xType
)
398 typelib_TypeDescription
* pRet
= nullptr;
401 typelib_TypeDescription
* pRefType
= createCTD(
402 access
, xType
->getReferencedType() );
403 typelib_typedescription_register( &pRefType
);
405 OUString
aTypeName( xType
->getName() );
407 typelib_typedescription_new(
409 static_cast<typelib_TypeClass
>(xType
->getTypeClass()),
415 typelib_typedescription_release( pRefType
);
421 static typelib_TypeDescription
* createCTD(
422 Reference
< container::XHierarchicalNameAccess
> const & access
,
423 const Reference
< XTypeDescription
> & xType
)
425 typelib_TypeDescription
* pRet
= nullptr;
429 switch (xType
->getTypeClass())
434 OUString
aTypeName("void");
435 typelib_typedescription_new( &pRet
, typelib_TypeClass_VOID
, aTypeName
.pData
, nullptr, 0, nullptr );
440 OUString
aTypeName("char");
441 typelib_typedescription_new( &pRet
, typelib_TypeClass_CHAR
, aTypeName
.pData
, nullptr, 0, nullptr );
444 case TypeClass_BOOLEAN
:
446 OUString
aTypeName("boolean");
447 typelib_typedescription_new( &pRet
, typelib_TypeClass_BOOLEAN
, aTypeName
.pData
, nullptr, 0, nullptr );
452 OUString
aTypeName("byte");
453 typelib_typedescription_new( &pRet
, typelib_TypeClass_BYTE
, aTypeName
.pData
, nullptr, 0, nullptr );
456 case TypeClass_SHORT
:
458 OUString
aTypeName("short");
459 typelib_typedescription_new( &pRet
, typelib_TypeClass_SHORT
, aTypeName
.pData
, nullptr, 0, nullptr );
462 case TypeClass_UNSIGNED_SHORT
:
464 OUString
aTypeName("unsigned short");
465 typelib_typedescription_new( &pRet
, typelib_TypeClass_UNSIGNED_SHORT
, aTypeName
.pData
, nullptr, 0, nullptr );
470 OUString
aTypeName("long");
471 typelib_typedescription_new( &pRet
, typelib_TypeClass_LONG
, aTypeName
.pData
, nullptr, 0, nullptr );
474 case TypeClass_UNSIGNED_LONG
:
476 OUString
aTypeName("unsigned long");
477 typelib_typedescription_new( &pRet
, typelib_TypeClass_UNSIGNED_LONG
, aTypeName
.pData
, nullptr, 0, nullptr );
480 case TypeClass_HYPER
:
482 OUString
aTypeName("hyper");
483 typelib_typedescription_new( &pRet
, typelib_TypeClass_HYPER
, aTypeName
.pData
, nullptr, 0, nullptr );
486 case TypeClass_UNSIGNED_HYPER
:
488 OUString
aTypeName("unsigned hyper");
489 typelib_typedescription_new( &pRet
, typelib_TypeClass_UNSIGNED_HYPER
, aTypeName
.pData
, nullptr, 0, nullptr );
492 case TypeClass_FLOAT
:
494 OUString
aTypeName("float");
495 typelib_typedescription_new( &pRet
, typelib_TypeClass_FLOAT
, aTypeName
.pData
, nullptr, 0, nullptr );
498 case TypeClass_DOUBLE
:
500 OUString
aTypeName("double");
501 typelib_typedescription_new( &pRet
, typelib_TypeClass_DOUBLE
, aTypeName
.pData
, nullptr, 0, nullptr );
504 case TypeClass_STRING
:
506 OUString
aTypeName("string");
507 typelib_typedescription_new( &pRet
, typelib_TypeClass_STRING
, aTypeName
.pData
, nullptr, 0, nullptr );
512 OUString
aTypeName("type");
513 typelib_typedescription_new( &pRet
, typelib_TypeClass_TYPE
, aTypeName
.pData
, nullptr, 0, nullptr );
518 OUString
aTypeName("any");
519 typelib_typedescription_new( &pRet
, typelib_TypeClass_ANY
, aTypeName
.pData
, nullptr, 0, nullptr );
523 case TypeClass_EXCEPTION
:
524 pRet
= createCTD( Reference
< XCompoundTypeDescription
>::query( xType
) );
526 case TypeClass_STRUCT
:
528 access
, Reference
< XStructTypeDescription
>::query( xType
) );
531 pRet
= createCTD( Reference
< XEnumTypeDescription
>::query( xType
) );
533 case TypeClass_TYPEDEF
:
535 Reference
< XIndirectTypeDescription
> xTypedef( xType
, UNO_QUERY
);
537 pRet
= createCTD( access
, xTypedef
->getReferencedType() );
540 case TypeClass_SEQUENCE
:
542 access
, Reference
< XIndirectTypeDescription
>::query( xType
) );
544 case TypeClass_INTERFACE
:
547 Reference
< XInterfaceTypeDescription2
>::query( xType
) );
549 case TypeClass_INTERFACE_METHOD
:
550 pRet
= createCTD( Reference
< XInterfaceMethodTypeDescription
>::query( xType
) );
552 case TypeClass_INTERFACE_ATTRIBUTE
:
553 pRet
= createCTD( Reference
< XInterfaceAttributeTypeDescription2
>::query( xType
) );
566 static void typelib_callback(
567 void * pContext
, typelib_TypeDescription
** ppRet
, rtl_uString
* pTypeName
)
569 OSL_ENSURE( pContext
&& ppRet
&& pTypeName
, "### null ptr!" );
575 ::typelib_typedescription_release( *ppRet
);
578 if (!(pContext
&& pTypeName
))
581 Reference
< container::XHierarchicalNameAccess
> access(
582 static_cast< container::XHierarchicalNameAccess
* >(
586 OUString
const & rTypeName
= OUString::unacquired( &pTypeName
);
587 Reference
< XTypeDescription
> xTD
;
588 if (access
->getByHierarchicalName(rTypeName
) >>= xTD
)
590 *ppRet
= createCTD( access
, xTD
);
593 catch (const container::NoSuchElementException
& exc
)
595 SAL_INFO("cppuhelper", "typelibrary type not available: " << exc
);
597 catch (const Exception
& exc
)
599 SAL_INFO("cppuhelper", exc
);
606 class EventListenerImpl
607 : public WeakImplHelper
< lang::XEventListener
>
609 Reference
< container::XHierarchicalNameAccess
> m_xTDMgr
;
612 explicit EventListenerImpl(
613 Reference
< container::XHierarchicalNameAccess
> const & xTDMgr
)
618 virtual void SAL_CALL
disposing( lang::EventObject
const & rEvt
) override
;
623 void EventListenerImpl::disposing( lang::EventObject
const & rEvt
)
625 if (rEvt
.Source
!= m_xTDMgr
) {
628 // deregister of c typelib callback
629 ::typelib_typedescription_revokeCallback( m_xTDMgr
.get(), typelib_callback
);
633 sal_Bool SAL_CALL
installTypeDescriptionManager(
634 Reference
< container::XHierarchicalNameAccess
> const & xTDMgr_c
)
636 uno::Environment
curr_env(Environment::getCurrent());
637 uno::Environment
target_env(CPPU_CURRENT_LANGUAGE_BINDING_NAME
);
639 uno::Mapping
curr2target(curr_env
, target_env
);
642 Reference
<container::XHierarchicalNameAccess
> xTDMgr(
643 static_cast<container::XHierarchicalNameAccess
*>(
644 curr2target
.mapInterface(xTDMgr_c
.get(), cppu::UnoType
<decltype(xTDMgr_c
)>::get())),
647 Reference
< lang::XComponent
> xComp( xTDMgr
, UNO_QUERY
);
650 xComp
->addEventListener( new EventListenerImpl( xTDMgr
) );
651 // register c typelib callback
652 ::typelib_typedescription_registerCallback( xTDMgr
.get(), typelib_callback
);
658 } // end namespace cppu
660 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */