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 .
20 #include <cppuhelper/queryinterface.hxx>
21 #include <cppuhelper/implementationentry.hxx>
22 #include <cppuhelper/supportsservice.hxx>
24 #include <com/sun/star/lang/XComponent.hpp>
25 #include <com/sun/star/reflection/XConstantTypeDescription.hpp>
26 #include <com/sun/star/reflection/XTypeDescription.hpp>
27 #include <com/sun/star/uno/RuntimeException.hpp>
28 #include <o3tl/any.hxx>
29 #include <uno/lbnames.h>
32 using namespace css::uno
;
33 using namespace css::lang
;
34 using namespace css::reflection
;
35 using namespace css::registry
;
46 IdlReflectionServiceImpl::IdlReflectionServiceImpl(
47 const Reference
< XComponentContext
> & xContext
)
48 : OComponentHelper( _aComponentMutex
)
51 xContext
->getValueByName(
52 "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) >>= _xTDMgr
;
53 OSL_ENSURE( _xTDMgr
.is(), "### cannot get singleton \"TypeDescriptionManager\" from context!" );
56 IdlReflectionServiceImpl::~IdlReflectionServiceImpl() {}
60 Any
IdlReflectionServiceImpl::queryInterface( const Type
& rType
)
62 Any
aRet( ::cppu::queryInterface(
64 static_cast< XIdlReflection
* >( this ),
65 static_cast< XHierarchicalNameAccess
* >( this ),
66 static_cast< XServiceInfo
* >( this ) ) );
68 return (aRet
.hasValue() ? aRet
: OComponentHelper::queryInterface( rType
));
71 void IdlReflectionServiceImpl::acquire() throw()
73 OComponentHelper::acquire();
76 void IdlReflectionServiceImpl::release() throw()
78 OComponentHelper::release();
83 Sequence
< Type
> IdlReflectionServiceImpl::getTypes()
85 static OTypeCollection
* s_pTypes
= nullptr;
88 MutexGuard
aGuard( _aComponentMutex
);
91 static OTypeCollection
s_aTypes(
92 cppu::UnoType
<XIdlReflection
>::get(),
93 cppu::UnoType
<XHierarchicalNameAccess
>::get(),
94 cppu::UnoType
<XServiceInfo
>::get(),
95 OComponentHelper::getTypes() );
99 return s_pTypes
->getTypes();
102 Sequence
< sal_Int8
> IdlReflectionServiceImpl::getImplementationId()
104 return css::uno::Sequence
<sal_Int8
>();
109 void IdlReflectionServiceImpl::dispose()
111 OComponentHelper::dispose();
113 MutexGuard
aGuard( _aComponentMutex
);
115 #ifdef TEST_LIST_CLASSES
116 OSL_ENSURE( g_aClassNames
.empty(), "### idl classes still alive!" );
117 for (auto const& className
: g_aClassNames
)
119 OUString
aName(className
);
126 OUString
IdlReflectionServiceImpl::getImplementationName()
128 return OUString("com.sun.star.comp.stoc.CoreReflection");
131 sal_Bool
IdlReflectionServiceImpl::supportsService( const OUString
& rServiceName
)
133 return cppu::supportsService(this, rServiceName
);
136 Sequence
< OUString
> IdlReflectionServiceImpl::getSupportedServiceNames()
138 Sequence
< OUString
> seqNames
{ "com.sun.star.reflection.CoreReflection" };
144 Reference
< XIdlClass
> IdlReflectionServiceImpl::getType( const Any
& rObj
)
146 return (rObj
.hasValue() ? forType( rObj
.getValueTypeRef() ) : Reference
< XIdlClass
>());
150 inline Reference
< XIdlClass
> IdlReflectionServiceImpl::constructClass(
151 typelib_TypeDescription
* pTypeDescr
)
153 OSL_ENSURE( pTypeDescr
->eTypeClass
!= typelib_TypeClass_TYPEDEF
, "### unexpected typedef!" );
155 switch (pTypeDescr
->eTypeClass
)
157 case typelib_TypeClass_VOID
:
158 case typelib_TypeClass_CHAR
:
159 case typelib_TypeClass_BOOLEAN
:
160 case typelib_TypeClass_BYTE
:
161 case typelib_TypeClass_SHORT
:
162 case typelib_TypeClass_UNSIGNED_SHORT
:
163 case typelib_TypeClass_LONG
:
164 case typelib_TypeClass_UNSIGNED_LONG
:
165 case typelib_TypeClass_HYPER
:
166 case typelib_TypeClass_UNSIGNED_HYPER
:
167 case typelib_TypeClass_FLOAT
:
168 case typelib_TypeClass_DOUBLE
:
169 case typelib_TypeClass_STRING
:
170 case typelib_TypeClass_ANY
:
171 return new IdlClassImpl( this, pTypeDescr
->pTypeName
, pTypeDescr
->eTypeClass
, pTypeDescr
);
173 case typelib_TypeClass_ENUM
:
174 return new EnumIdlClassImpl( this, pTypeDescr
->pTypeName
, pTypeDescr
->eTypeClass
, pTypeDescr
);
176 case typelib_TypeClass_STRUCT
:
177 case typelib_TypeClass_EXCEPTION
:
178 return new CompoundIdlClassImpl( this, pTypeDescr
->pTypeName
, pTypeDescr
->eTypeClass
, pTypeDescr
);
180 case typelib_TypeClass_SEQUENCE
:
181 return new ArrayIdlClassImpl( this, pTypeDescr
->pTypeName
, pTypeDescr
->eTypeClass
, pTypeDescr
);
183 case typelib_TypeClass_INTERFACE
:
184 return new InterfaceIdlClassImpl( this, pTypeDescr
->pTypeName
, pTypeDescr
->eTypeClass
, pTypeDescr
);
186 case typelib_TypeClass_TYPE
:
187 return new IdlClassImpl( this, pTypeDescr
->pTypeName
, pTypeDescr
->eTypeClass
, pTypeDescr
);
190 SAL_INFO("stoc", "corereflection type unsupported: " << pTypeDescr
->pTypeName
);
191 return Reference
< XIdlClass
>();
195 Reference
< XIdlClass
> IdlReflectionServiceImpl::forName( const OUString
& rTypeName
)
197 Reference
< XIdlClass
> xRet
;
198 Any
aAny( _aElements
.getValue( rTypeName
) );
206 // try to get _type_ by name
207 typelib_TypeDescription
* pTD
= nullptr;
208 typelib_typedescription_getByName( &pTD
, rTypeName
.pData
);
211 if ((xRet
= constructClass( pTD
)).is())
212 _aElements
.setValue( rTypeName
, makeAny( xRet
) ); // update
213 typelib_typedescription_release( pTD
);
220 // XHierarchicalNameAccess
222 Any
IdlReflectionServiceImpl::getByHierarchicalName( const OUString
& rName
)
224 Any
aRet( _aElements
.getValue( rName
) );
225 if (! aRet
.hasValue())
227 aRet
= _xTDMgr
->getByHierarchicalName( rName
);
228 if (aRet
.getValueTypeClass() == TypeClass_INTERFACE
)
230 // type retrieved from tdmgr
231 OSL_ASSERT( (*o3tl::forceAccess
<Reference
<XInterface
>>(aRet
))->queryInterface(
232 cppu::UnoType
<XTypeDescription
>::get()).hasValue() );
234 css::uno::Reference
< css::reflection::XConstantTypeDescription
>
238 aRet
= ctd
->getConstantValue();
242 // if you are interested in a type then CALL forName()!!!
243 // this way is NOT recommended for types, because this method looks for constants first
245 // if td manager found some type, it will be in the cache (hopefully.. we just got it)
246 // so the second retrieving via c typelib callback chain should succeed...
248 // try to get _type_ by name
249 typelib_TypeDescription
* pTD
= nullptr;
250 typelib_typedescription_getByName( &pTD
, rName
.pData
);
252 aRet
.clear(); // kick XTypeDescription interface
256 Reference
< XIdlClass
> xIdlClass( constructClass( pTD
) );
257 aRet
.setValue( &xIdlClass
, cppu::UnoType
<XIdlClass
>::get());
258 typelib_typedescription_release( pTD
);
262 // else is enum member(?)
265 if (!aRet
.hasValue())
266 throw container::NoSuchElementException( rName
);
268 _aElements
.setValue( rName
, aRet
);
273 sal_Bool
IdlReflectionServiceImpl::hasByHierarchicalName( const OUString
& rName
)
277 return getByHierarchicalName( rName
).hasValue();
279 catch (container::NoSuchElementException
&)
286 Reference
< XIdlClass
> IdlReflectionServiceImpl::forType( typelib_TypeDescription
* pTypeDescr
)
288 Reference
< XIdlClass
> xRet
;
289 OUString
aName( pTypeDescr
->pTypeName
);
290 Any
aAny( _aElements
.getValue( aName
) );
298 if ((xRet
= constructClass( pTypeDescr
)).is())
299 _aElements
.setValue( aName
, makeAny( xRet
) ); // update
305 Reference
< XIdlClass
> IdlReflectionServiceImpl::forType( typelib_TypeDescriptionReference
* pRef
)
307 typelib_TypeDescription
* pTD
= nullptr;
308 TYPELIB_DANGER_GET( &pTD
, pRef
);
311 Reference
< XIdlClass
> xRet
= forType( pTD
);
312 TYPELIB_DANGER_RELEASE( pTD
);
315 throw RuntimeException(
316 "IdlReflectionServiceImpl::forType() failed!",
317 static_cast<XWeak
*>(static_cast<OWeakObject
*>(this)) );
321 const Mapping
& IdlReflectionServiceImpl::getCpp2Uno()
323 if (! _aCpp2Uno
.is())
325 MutexGuard
aGuard( getMutexAccess() );
326 if (! _aCpp2Uno
.is())
329 OUString( CPPU_CURRENT_LANGUAGE_BINDING_NAME
),
330 OUString( UNO_LB_UNO
) );
331 OSL_ENSURE( _aCpp2Uno
.is(), "### cannot get c++ to uno mapping!" );
332 if (! _aCpp2Uno
.is())
334 throw RuntimeException(
335 "cannot get c++ to uno mapping!",
336 static_cast<XWeak
*>(static_cast<OWeakObject
*>(this)) );
343 const Mapping
& IdlReflectionServiceImpl::getUno2Cpp()
345 if (! _aUno2Cpp
.is())
347 MutexGuard
aGuard( getMutexAccess() );
348 if (! _aUno2Cpp
.is())
351 OUString( UNO_LB_UNO
),
352 OUString( CPPU_CURRENT_LANGUAGE_BINDING_NAME
) );
353 OSL_ENSURE( _aUno2Cpp
.is(), "### cannot get uno to c++ mapping!" );
354 if (! _aUno2Cpp
.is())
356 throw RuntimeException(
357 "cannot get uno to c++ mapping!",
358 static_cast<XWeak
*>(static_cast<OWeakObject
*>(this)) );
365 uno_Interface
* IdlReflectionServiceImpl::mapToUno(
366 const Any
& rObj
, typelib_InterfaceTypeDescription
* pTo
)
368 Reference
< XInterface
> xObj
;
369 if (extract( rObj
, pTo
, xObj
, this ))
370 return static_cast<uno_Interface
*>(getCpp2Uno().mapInterface( xObj
.get(), pTo
));
372 throw RuntimeException(
373 "illegal object given!",
374 static_cast<XWeak
*>(static_cast<OWeakObject
*>(this)) );
384 css::uno::Reference
<css::uno::XComponentContext
> const & context
):
385 instance(new stoc_corefl::IdlReflectionServiceImpl(context
))
388 rtl::Reference
<cppu::OWeakObject
> instance
;
392 public rtl::StaticWithArg
<
393 Instance
, css::uno::Reference
<css::uno::XComponentContext
>, Singleton
>
398 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
399 com_sun_star_comp_stoc_CoreReflection_get_implementation(
400 css::uno::XComponentContext
* context
,
401 css::uno::Sequence
<css::uno::Any
> const & arguments
)
404 arguments
.hasElements(), "stoc", "unexpected singleton arguments");
405 return cppu::acquire(Singleton::get(context
).instance
.get());
408 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */