Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / cppuhelper / source / tdmgr.cxx
blob8666fadc6554156316f76ef9fa8d7695cd91ac87
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
24 #include <vector>
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>
49 #include <memory>
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::reflection;
55 namespace cppu
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;
67 if (xType.is())
69 typelib_TypeDescription * pBaseType = createCTD(
70 Reference< XCompoundTypeDescription >::query( xType->getBaseType() ) );
71 if (pBaseType)
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 ));
89 sal_Int32 nPos;
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 rtl_uString_acquire( rInit.pTypeName = aMemberTypeName.pData );
98 // string is held by rMemberNames
99 rInit.pMemberName = pMemberNames[nPos].pData;
102 typelib_typedescription_new(
103 &pRet,
104 static_cast<typelib_TypeClass>(xType->getTypeClass()),
105 aTypeName.pData,
106 (pBaseType ? pBaseType->pWeakRef : nullptr),
107 nMembers, pMemberInits );
109 // cleanup
110 for ( nPos = nMembers; nPos--; )
112 rtl_uString_release( pMemberInits[nPos].pTypeName );
114 if (pBaseType)
115 typelib_typedescription_release( pBaseType );
117 return pRet;
120 static typelib_TypeDescription * createCTD(
121 Reference< container::XHierarchicalNameAccess > const & access,
122 const Reference< XStructTypeDescription > & xType )
124 typelib_TypeDescription * pRet = nullptr;
125 if (xType.is() && !xType->getTypeParameters().hasElements())
127 typelib_TypeDescription * pBaseType = createCTD(
128 access, xType->getBaseType() );
129 if (pBaseType)
130 typelib_typedescription_register( &pBaseType );
132 // construct member init array
133 const Sequence<Reference< XTypeDescription > > & rMemberTypes = xType->getMemberTypes();
134 const Sequence< OUString > & rMemberNames = xType->getMemberNames();
136 const Reference< XTypeDescription > * pMemberTypes = rMemberTypes.getConstArray();
137 const OUString * pMemberNames = rMemberNames.getConstArray();
139 sal_Int32 nMembers = rMemberTypes.getLength();
140 OSL_ENSURE( nMembers == rMemberNames.getLength(), "### lens differ!" );
142 OUString aTypeName( xType->getName() );
144 typelib_StructMember_Init * pMemberInits = static_cast<typelib_StructMember_Init *>(alloca(
145 sizeof(typelib_StructMember_Init) * nMembers ));
147 Sequence< Reference< XTypeDescription > > templateMemberTypes;
148 sal_Int32 i = aTypeName.indexOf('<');
149 if (i >= 0) {
150 Reference< XStructTypeDescription > templateDesc(
151 access->getByHierarchicalName(aTypeName.copy(0, i)),
152 UNO_QUERY_THROW);
153 OSL_ASSERT(
154 templateDesc->getTypeParameters().getLength()
155 == xType->getTypeArguments().getLength());
156 templateMemberTypes = templateDesc->getMemberTypes();
157 OSL_ASSERT(templateMemberTypes.getLength() == nMembers);
160 sal_Int32 nPos;
161 for ( nPos = nMembers; nPos--; )
163 typelib_StructMember_Init & rInit = pMemberInits[nPos];
164 rInit.aBase.eTypeClass
165 = static_cast<typelib_TypeClass>(pMemberTypes[nPos]->getTypeClass());
167 OUString aMemberTypeName( pMemberTypes[nPos]->getName() );
168 rtl_uString_acquire(
169 rInit.aBase.pTypeName = aMemberTypeName.pData );
171 // string is held by rMemberNames
172 rInit.aBase.pMemberName = pMemberNames[nPos].pData;
174 rInit.bParameterizedType = templateMemberTypes.hasElements()
175 && (templateMemberTypes[nPos]->getTypeClass()
176 == TypeClass_UNKNOWN);
179 typelib_typedescription_newStruct(
180 &pRet,
181 aTypeName.pData,
182 (pBaseType ? pBaseType->pWeakRef : nullptr),
183 nMembers, pMemberInits );
185 // cleanup
186 for ( nPos = nMembers; nPos--; )
188 rtl_uString_release( pMemberInits[nPos].aBase.pTypeName );
190 if (pBaseType)
191 typelib_typedescription_release( pBaseType );
193 return pRet;
196 static typelib_TypeDescription * createCTD(
197 const Reference< XInterfaceAttributeTypeDescription2 > & xAttribute )
199 typelib_TypeDescription * pRet = nullptr;
200 if (xAttribute.is())
202 OUString aMemberName( xAttribute->getName() );
203 Reference< XTypeDescription > xType( xAttribute->getType() );
204 OUString aMemberTypeName( xType->getName() );
205 std::vector< rtl_uString * > getExc;
206 Sequence< Reference< XCompoundTypeDescription > > getExcs(
207 xAttribute->getGetExceptions() );
208 for (sal_Int32 i = 0; i != getExcs.getLength(); ++i)
210 OSL_ASSERT( getExcs[i].is() );
211 getExc.push_back( getExcs[i]->getName().pData );
213 std::vector< rtl_uString * > setExc;
214 Sequence< Reference< XCompoundTypeDescription > > setExcs(
215 xAttribute->getSetExceptions() );
216 for (sal_Int32 i = 0; i != setExcs.getLength(); ++i)
218 OSL_ASSERT( setExcs[i].is() );
219 setExc.push_back( setExcs[i]->getName().pData );
221 typelib_typedescription_newExtendedInterfaceAttribute(
222 reinterpret_cast<typelib_InterfaceAttributeTypeDescription **>(&pRet),
223 xAttribute->getPosition(),
224 aMemberName.pData, // name
225 static_cast<typelib_TypeClass>(xType->getTypeClass()),
226 aMemberTypeName.pData, // type name
227 xAttribute->isReadOnly(),
228 getExc.size(), getExc.data(),
229 setExc.size(), setExc.data() );
231 return pRet;
234 static typelib_TypeDescription * createCTD(
235 const Reference< XInterfaceMethodTypeDescription > & xMethod )
237 typelib_TypeDescription * pRet = nullptr;
238 if (xMethod.is())
240 Reference< XTypeDescription > xReturnType( xMethod->getReturnType() );
242 // init all params
243 const Sequence<Reference< XMethodParameter > > & rParams = xMethod->getParameters();
244 const Reference< XMethodParameter > * pParams = rParams.getConstArray();
245 sal_Int32 nParams = rParams.getLength();
247 typelib_Parameter_Init * pParamInit = static_cast<typelib_Parameter_Init *>(alloca(
248 sizeof(typelib_Parameter_Init) * nParams ));
250 sal_Int32 nPos;
251 for ( nPos = nParams; nPos--; )
253 const Reference< XMethodParameter > & xParam = pParams[nPos];
254 const Reference< XTypeDescription > & xType = xParam->getType();
255 typelib_Parameter_Init & rInit = pParamInit[xParam->getPosition()];
257 rInit.eTypeClass = static_cast<typelib_TypeClass>(xType->getTypeClass());
258 OUString aParamTypeName( xType->getName() );
259 rtl_uString_acquire( rInit.pTypeName = aParamTypeName.pData );
260 OUString aParamName( xParam->getName() );
261 rtl_uString_acquire( rInit.pParamName = aParamName.pData );
262 rInit.bIn = xParam->isIn();
263 rInit.bOut = xParam->isOut();
266 // init all exception strings
267 const Sequence<Reference< XTypeDescription > > & rExceptions = xMethod->getExceptions();
268 const Reference< XTypeDescription > * pExceptions = rExceptions.getConstArray();
269 sal_Int32 nExceptions = rExceptions.getLength();
270 rtl_uString ** ppExceptionNames = static_cast<rtl_uString **>(alloca(
271 sizeof(rtl_uString *) * nExceptions ));
273 for ( nPos = nExceptions; nPos--; )
275 OUString aExceptionTypeName( pExceptions[nPos]->getName() );
276 rtl_uString_acquire( ppExceptionNames[nPos] = aExceptionTypeName.pData );
279 OUString aTypeName( xMethod->getName() );
280 OUString aReturnTypeName( xReturnType->getName() );
282 typelib_typedescription_newInterfaceMethod(
283 reinterpret_cast<typelib_InterfaceMethodTypeDescription **>(&pRet),
284 xMethod->getPosition(),
285 xMethod->isOneway(),
286 aTypeName.pData,
287 static_cast<typelib_TypeClass>(xReturnType->getTypeClass()),
288 aReturnTypeName.pData,
289 nParams, pParamInit,
290 nExceptions, ppExceptionNames );
292 for ( nPos = nParams; nPos--; )
294 rtl_uString_release( pParamInit[nPos].pTypeName );
295 rtl_uString_release( pParamInit[nPos].pParamName );
297 for ( nPos = nExceptions; nPos--; )
299 rtl_uString_release( ppExceptionNames[nPos] );
302 return pRet;
305 static typelib_TypeDescription * createCTD(
306 Reference< container::XHierarchicalNameAccess > const & access,
307 const Reference< XInterfaceTypeDescription2 > & xType )
309 typelib_TypeDescription * pRet = nullptr;
310 if (xType.is())
312 Sequence< Reference< XTypeDescription > > aBases(xType->getBaseTypes());
313 sal_Int32 nBases = aBases.getLength();
314 // Exploit the fact that a typelib_TypeDescription for an interface type
315 // is also the typelib_TypeDescriptionReference for that type:
316 std::unique_ptr< typelib_TypeDescription * []> aBaseTypes(
317 new typelib_TypeDescription *[nBases]);
318 for (sal_Int32 i = 0; i < nBases; ++i) {
319 typelib_TypeDescription * p = createCTD(access, aBases[i]);
320 OSL_ASSERT(
321 !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(p->eTypeClass));
322 typelib_typedescription_register(&p);
323 aBaseTypes[i] = p;
325 typelib_TypeDescriptionReference ** pBaseTypeRefs
326 = reinterpret_cast< typelib_TypeDescriptionReference ** >(
327 aBaseTypes.get());
329 // construct all member refs
330 const Sequence<Reference< XInterfaceMemberTypeDescription > > & rMembers = xType->getMembers();
331 sal_Int32 nMembers = rMembers.getLength();
333 typelib_TypeDescriptionReference ** ppMemberRefs = static_cast<typelib_TypeDescriptionReference **>(alloca(
334 sizeof(typelib_TypeDescriptionReference *) * nMembers ));
336 const Reference< XInterfaceMemberTypeDescription > * pMembers = rMembers.getConstArray();
338 OUString aTypeName( xType->getName() );
340 sal_Int32 nPos;
341 for ( nPos = nMembers; nPos--; )
343 OUString aMemberTypeName( pMembers[nPos]->getName() );
344 ppMemberRefs[nPos] = nullptr;
345 typelib_typedescriptionreference_new(
346 ppMemberRefs + nPos,
347 static_cast<typelib_TypeClass>(pMembers[nPos]->getTypeClass()),
348 aMemberTypeName.pData );
351 typelib_typedescription_newMIInterface(
352 reinterpret_cast<typelib_InterfaceTypeDescription **>(&pRet),
353 aTypeName.pData,
354 0, 0, 0, 0, 0,
355 nBases, pBaseTypeRefs,
356 nMembers, ppMemberRefs );
358 // cleanup refs and base type
359 for (int i = 0; i < nBases; ++i) {
360 typelib_typedescription_release(aBaseTypes[i]);
363 for ( nPos = nMembers; nPos--; )
365 typelib_typedescriptionreference_release( ppMemberRefs[nPos] );
368 return pRet;
371 static typelib_TypeDescription * createCTD( const Reference< XEnumTypeDescription > & xType )
373 typelib_TypeDescription * pRet = nullptr;
374 if (xType.is())
376 OUString aTypeName( xType->getName() );
377 Sequence< OUString > aNames( xType->getEnumNames() );
378 OSL_ASSERT( sizeof(OUString) == sizeof(rtl_uString *) ); // !!!
379 Sequence< sal_Int32 > aValues( xType->getEnumValues() );
381 typelib_typedescription_newEnum(
382 &pRet, aTypeName.pData, xType->getDefaultEnumValue(),
383 aNames.getLength(),
384 const_cast<rtl_uString **>(reinterpret_cast<rtl_uString * const *>(aNames.getConstArray())),
385 const_cast< sal_Int32 * >( aValues.getConstArray() ) );
387 return pRet;
390 static typelib_TypeDescription * createCTD(
391 Reference< container::XHierarchicalNameAccess > const & access,
392 const Reference< XIndirectTypeDescription > & xType )
394 typelib_TypeDescription * pRet = nullptr;
395 if (xType.is())
397 typelib_TypeDescription * pRefType = createCTD(
398 access, xType->getReferencedType() );
399 typelib_typedescription_register( &pRefType );
401 OUString aTypeName( xType->getName() );
403 typelib_typedescription_new(
404 &pRet,
405 static_cast<typelib_TypeClass>(xType->getTypeClass()),
406 aTypeName.pData,
407 pRefType->pWeakRef,
408 0, nullptr );
410 // cleanup
411 typelib_typedescription_release( pRefType );
413 return pRet;
417 static typelib_TypeDescription * createCTD(
418 Reference< container::XHierarchicalNameAccess > const & access,
419 const Reference< XTypeDescription > & xType )
421 typelib_TypeDescription * pRet = nullptr;
423 if (xType.is())
425 switch (xType->getTypeClass())
427 // built in types
428 case TypeClass_VOID:
430 OUString aTypeName("void");
431 typelib_typedescription_new( &pRet, typelib_TypeClass_VOID, aTypeName.pData, nullptr, 0, nullptr );
432 break;
434 case TypeClass_CHAR:
436 OUString aTypeName("char");
437 typelib_typedescription_new( &pRet, typelib_TypeClass_CHAR, aTypeName.pData, nullptr, 0, nullptr );
438 break;
440 case TypeClass_BOOLEAN:
442 OUString aTypeName("boolean");
443 typelib_typedescription_new( &pRet, typelib_TypeClass_BOOLEAN, aTypeName.pData, nullptr, 0, nullptr );
444 break;
446 case TypeClass_BYTE:
448 OUString aTypeName("byte");
449 typelib_typedescription_new( &pRet, typelib_TypeClass_BYTE, aTypeName.pData, nullptr, 0, nullptr );
450 break;
452 case TypeClass_SHORT:
454 OUString aTypeName("short");
455 typelib_typedescription_new( &pRet, typelib_TypeClass_SHORT, aTypeName.pData, nullptr, 0, nullptr );
456 break;
458 case TypeClass_UNSIGNED_SHORT:
460 OUString aTypeName("unsigned short");
461 typelib_typedescription_new( &pRet, typelib_TypeClass_UNSIGNED_SHORT, aTypeName.pData, nullptr, 0, nullptr );
462 break;
464 case TypeClass_LONG:
466 OUString aTypeName("long");
467 typelib_typedescription_new( &pRet, typelib_TypeClass_LONG, aTypeName.pData, nullptr, 0, nullptr );
468 break;
470 case TypeClass_UNSIGNED_LONG:
472 OUString aTypeName("unsigned long");
473 typelib_typedescription_new( &pRet, typelib_TypeClass_UNSIGNED_LONG, aTypeName.pData, nullptr, 0, nullptr );
474 break;
476 case TypeClass_HYPER:
478 OUString aTypeName("hyper");
479 typelib_typedescription_new( &pRet, typelib_TypeClass_HYPER, aTypeName.pData, nullptr, 0, nullptr );
480 break;
482 case TypeClass_UNSIGNED_HYPER:
484 OUString aTypeName("unsigned hyper");
485 typelib_typedescription_new( &pRet, typelib_TypeClass_UNSIGNED_HYPER, aTypeName.pData, nullptr, 0, nullptr );
486 break;
488 case TypeClass_FLOAT:
490 OUString aTypeName("float");
491 typelib_typedescription_new( &pRet, typelib_TypeClass_FLOAT, aTypeName.pData, nullptr, 0, nullptr );
492 break;
494 case TypeClass_DOUBLE:
496 OUString aTypeName("double");
497 typelib_typedescription_new( &pRet, typelib_TypeClass_DOUBLE, aTypeName.pData, nullptr, 0, nullptr );
498 break;
500 case TypeClass_STRING:
502 OUString aTypeName("string");
503 typelib_typedescription_new( &pRet, typelib_TypeClass_STRING, aTypeName.pData, nullptr, 0, nullptr );
504 break;
506 case TypeClass_TYPE:
508 OUString aTypeName("type");
509 typelib_typedescription_new( &pRet, typelib_TypeClass_TYPE, aTypeName.pData, nullptr, 0, nullptr );
510 break;
512 case TypeClass_ANY:
514 OUString aTypeName("any");
515 typelib_typedescription_new( &pRet, typelib_TypeClass_ANY, aTypeName.pData, nullptr, 0, nullptr );
516 break;
519 case TypeClass_EXCEPTION:
520 pRet = createCTD( Reference< XCompoundTypeDescription >::query( xType ) );
521 break;
522 case TypeClass_STRUCT:
523 pRet = createCTD(
524 access, Reference< XStructTypeDescription >::query( xType ) );
525 break;
526 case TypeClass_ENUM:
527 pRet = createCTD( Reference< XEnumTypeDescription >::query( xType ) );
528 break;
529 case TypeClass_TYPEDEF:
531 Reference< XIndirectTypeDescription > xTypedef( xType, UNO_QUERY );
532 if (xTypedef.is())
533 pRet = createCTD( access, xTypedef->getReferencedType() );
534 break;
536 case TypeClass_SEQUENCE:
537 pRet = createCTD(
538 access, Reference< XIndirectTypeDescription >::query( xType ) );
539 break;
540 case TypeClass_INTERFACE:
541 pRet = createCTD(
542 access,
543 Reference< XInterfaceTypeDescription2 >::query( xType ) );
544 break;
545 case TypeClass_INTERFACE_METHOD:
546 pRet = createCTD( Reference< XInterfaceMethodTypeDescription >::query( xType ) );
547 break;
548 case TypeClass_INTERFACE_ATTRIBUTE:
549 pRet = createCTD( Reference< XInterfaceAttributeTypeDescription2 >::query( xType ) );
550 break;
551 default:
552 break;
556 return pRet;
560 extern "C"
562 static void typelib_callback(
563 void * pContext, typelib_TypeDescription ** ppRet, rtl_uString * pTypeName )
565 OSL_ENSURE( pContext && ppRet && pTypeName, "### null ptr!" );
566 if (ppRet)
568 if (*ppRet)
570 ::typelib_typedescription_release( *ppRet );
571 *ppRet = nullptr;
573 if (pContext && pTypeName)
575 Reference< container::XHierarchicalNameAccess > access(
576 static_cast< container::XHierarchicalNameAccess * >(
577 pContext));
580 OUString const & rTypeName = OUString::unacquired( &pTypeName );
581 Reference< XTypeDescription > xTD;
582 if (access->getByHierarchicalName(rTypeName ) >>= xTD)
584 *ppRet = createCTD( access, xTD );
587 catch (const container::NoSuchElementException & exc)
589 SAL_INFO("cppuhelper", "typelibrary type not available: " << exc );
591 catch (const Exception & exc)
593 SAL_INFO("cppuhelper", exc );
601 class EventListenerImpl
602 : public WeakImplHelper< lang::XEventListener >
604 Reference< container::XHierarchicalNameAccess > m_xTDMgr;
606 public:
607 explicit EventListenerImpl(
608 Reference< container::XHierarchicalNameAccess > const & xTDMgr )
609 : m_xTDMgr( xTDMgr )
612 // XEventListener
613 virtual void SAL_CALL disposing( lang::EventObject const & rEvt ) override;
616 void EventListenerImpl::disposing( lang::EventObject const & rEvt )
618 if (rEvt.Source != m_xTDMgr) {
619 OSL_ASSERT(false);
621 // deregister of c typelib callback
622 ::typelib_typedescription_revokeCallback( m_xTDMgr.get(), typelib_callback );
626 sal_Bool SAL_CALL installTypeDescriptionManager(
627 Reference< container::XHierarchicalNameAccess > const & xTDMgr_c )
629 uno::Environment curr_env(Environment::getCurrent());
630 uno::Environment target_env(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
632 uno::Mapping curr2target(curr_env, target_env);
635 Reference<container::XHierarchicalNameAccess> xTDMgr(
636 static_cast<container::XHierarchicalNameAccess *>(
637 curr2target.mapInterface(xTDMgr_c.get(), cppu::UnoType<decltype(xTDMgr_c)>::get())),
638 SAL_NO_ACQUIRE);
640 Reference< lang::XComponent > xComp( xTDMgr, UNO_QUERY );
641 if (xComp.is())
643 xComp->addEventListener( new EventListenerImpl( xTDMgr ) );
644 // register c typelib callback
645 ::typelib_typedescription_registerCallback( xTDMgr.get(), typelib_callback );
646 return true;
648 return false;
651 } // end namespace cppu
653 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */