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 : #include <cppuhelper/queryinterface.hxx>
21 : #include <cppuhelper/implementationentry.hxx>
22 : #include <cppuhelper/supportsservice.hxx>
23 :
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 <uno/lbnames.h>
29 :
30 : using namespace com::sun::star;
31 : using namespace com::sun::star::lang;
32 : using namespace com::sun::star::registry;
33 : using namespace cppu;
34 : using namespace osl;
35 :
36 :
37 : #include "base.hxx"
38 :
39 :
40 : namespace stoc_corefl
41 : {
42 :
43 : static const sal_Int32 CACHE_SIZE = 256;
44 :
45 : #define SERVICENAME "com.sun.star.reflection.CoreReflection"
46 : #define IMPLNAME "com.sun.star.comp.stoc.CoreReflection"
47 :
48 82 : static Sequence< OUString > core_getSupportedServiceNames()
49 : {
50 82 : Sequence< OUString > seqNames(1);
51 82 : seqNames.getArray()[0] = OUString( SERVICENAME );
52 82 : return seqNames;
53 : }
54 :
55 82 : static OUString core_getImplementationName()
56 : {
57 82 : return OUString(IMPLNAME);
58 : }
59 :
60 82 : IdlReflectionServiceImpl::IdlReflectionServiceImpl(
61 : const Reference< XComponentContext > & xContext )
62 : : OComponentHelper( _aComponentMutex )
63 82 : , _xMgr( xContext->getServiceManager(), UNO_QUERY )
64 164 : , _aElements( CACHE_SIZE )
65 : {
66 82 : xContext->getValueByName( OUString(
67 164 : "/singletons/com.sun.star.reflection.theTypeDescriptionManager") ) >>= _xTDMgr;
68 : OSL_ENSURE( _xTDMgr.is(), "### cannot get singleton \"TypeDescriptionManager\" from context!" );
69 82 : }
70 :
71 104 : IdlReflectionServiceImpl::~IdlReflectionServiceImpl() {}
72 :
73 : // XInterface
74 :
75 14024 : Any IdlReflectionServiceImpl::queryInterface( const Type & rType )
76 : throw(::com::sun::star::uno::RuntimeException, std::exception)
77 : {
78 : Any aRet( ::cppu::queryInterface(
79 : rType,
80 : static_cast< XIdlReflection * >( this ),
81 : static_cast< XHierarchicalNameAccess * >( this ),
82 14024 : static_cast< XServiceInfo * >( this ) ) );
83 :
84 14024 : return (aRet.hasValue() ? aRet : OComponentHelper::queryInterface( rType ));
85 : }
86 :
87 140465 : void IdlReflectionServiceImpl::acquire() throw()
88 : {
89 140465 : OComponentHelper::acquire();
90 140465 : }
91 :
92 132153 : void IdlReflectionServiceImpl::release() throw()
93 : {
94 132153 : OComponentHelper::release();
95 132153 : }
96 :
97 : // XTypeProvider
98 :
99 0 : Sequence< Type > IdlReflectionServiceImpl::getTypes()
100 : throw (::com::sun::star::uno::RuntimeException, std::exception)
101 : {
102 : static OTypeCollection * s_pTypes = 0;
103 0 : if (! s_pTypes)
104 : {
105 0 : MutexGuard aGuard( _aComponentMutex );
106 0 : if (! s_pTypes)
107 : {
108 : static OTypeCollection s_aTypes(
109 0 : ::getCppuType( (const Reference< XIdlReflection > *)0 ),
110 0 : ::getCppuType( (const Reference< XHierarchicalNameAccess > *)0 ),
111 0 : ::getCppuType( (const Reference< XServiceInfo > *)0 ),
112 0 : OComponentHelper::getTypes() );
113 0 : s_pTypes = &s_aTypes;
114 0 : }
115 : }
116 0 : return s_pTypes->getTypes();
117 : }
118 :
119 0 : Sequence< sal_Int8 > IdlReflectionServiceImpl::getImplementationId()
120 : throw (::com::sun::star::uno::RuntimeException, std::exception)
121 : {
122 0 : return css::uno::Sequence<sal_Int8>();
123 : }
124 :
125 : // XComponent
126 :
127 81 : void IdlReflectionServiceImpl::dispose()
128 : throw(::com::sun::star::uno::RuntimeException, std::exception)
129 : {
130 81 : OComponentHelper::dispose();
131 :
132 81 : MutexGuard aGuard( _aComponentMutex );
133 81 : _aElements.clear();
134 : #ifdef TEST_LIST_CLASSES
135 : OSL_ENSURE( g_aClassNames.empty(), "### idl classes still alive!" );
136 : ClassNameList::const_iterator iPos( g_aClassNames.begin() );
137 : while (iPos != g_aClassNames.end())
138 : {
139 : OUString aName( *iPos );
140 : ++iPos;
141 : }
142 : #endif
143 81 : }
144 :
145 : // XServiceInfo
146 :
147 0 : OUString IdlReflectionServiceImpl::getImplementationName()
148 : throw(::com::sun::star::uno::RuntimeException, std::exception)
149 : {
150 0 : return core_getImplementationName();
151 : }
152 :
153 0 : sal_Bool IdlReflectionServiceImpl::supportsService( const OUString & rServiceName )
154 : throw(::com::sun::star::uno::RuntimeException, std::exception)
155 : {
156 0 : return cppu::supportsService(this, rServiceName);
157 : }
158 :
159 0 : Sequence< OUString > IdlReflectionServiceImpl::getSupportedServiceNames()
160 : throw(::com::sun::star::uno::RuntimeException, std::exception)
161 : {
162 0 : return core_getSupportedServiceNames();
163 : }
164 :
165 : // XIdlReflection
166 :
167 0 : Reference< XIdlClass > IdlReflectionServiceImpl::getType( const Any & rObj )
168 : throw(::com::sun::star::uno::RuntimeException, std::exception)
169 : {
170 0 : return (rObj.hasValue() ? forType( rObj.getValueTypeRef() ) : Reference< XIdlClass >());
171 : }
172 :
173 :
174 8865 : inline Reference< XIdlClass > IdlReflectionServiceImpl::constructClass(
175 : typelib_TypeDescription * pTypeDescr )
176 : {
177 : OSL_ENSURE( pTypeDescr->eTypeClass != typelib_TypeClass_TYPEDEF, "### unexpected typedef!" );
178 :
179 8865 : switch (pTypeDescr->eTypeClass)
180 : {
181 : case typelib_TypeClass_VOID:
182 : case typelib_TypeClass_CHAR:
183 : case typelib_TypeClass_BOOLEAN:
184 : case typelib_TypeClass_BYTE:
185 : case typelib_TypeClass_SHORT:
186 : case typelib_TypeClass_UNSIGNED_SHORT:
187 : case typelib_TypeClass_LONG:
188 : case typelib_TypeClass_UNSIGNED_LONG:
189 : case typelib_TypeClass_HYPER:
190 : case typelib_TypeClass_UNSIGNED_HYPER:
191 : case typelib_TypeClass_FLOAT:
192 : case typelib_TypeClass_DOUBLE:
193 : case typelib_TypeClass_STRING:
194 : case typelib_TypeClass_ANY:
195 489 : return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
196 :
197 : case TypeClass_ENUM:
198 10 : return new EnumIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
199 :
200 : case typelib_TypeClass_STRUCT:
201 : case typelib_TypeClass_EXCEPTION:
202 242 : return new CompoundIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
203 :
204 : case typelib_TypeClass_SEQUENCE:
205 564 : return new ArrayIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
206 :
207 : case typelib_TypeClass_INTERFACE:
208 7535 : return new InterfaceIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
209 :
210 : case typelib_TypeClass_TYPE:
211 25 : return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
212 :
213 : default:
214 : #if OSL_DEBUG_LEVEL > 1
215 : OSL_TRACE( "### corereflection type unsupported: " );
216 : OString aName( OUStringToOString( pTypeDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
217 : OSL_TRACE( "%s", aName.getStr() );
218 : OSL_TRACE( "\n" );
219 : #endif
220 0 : return Reference< XIdlClass >();
221 : }
222 : }
223 :
224 255336 : Reference< XIdlClass > IdlReflectionServiceImpl::forName( const OUString & rTypeName )
225 : throw(::com::sun::star::uno::RuntimeException, std::exception)
226 : {
227 255336 : Reference< XIdlClass > xRet;
228 510672 : Any aAny( _aElements.getValue( rTypeName ) );
229 :
230 255336 : if (aAny.hasValue())
231 : {
232 249994 : if (aAny.getValueTypeClass() == TypeClass_INTERFACE)
233 249994 : xRet = *(const Reference< XIdlClass > *)aAny.getValue();
234 : }
235 : else
236 : {
237 : // try to get _type_ by name
238 5342 : typelib_TypeDescription * pTD = 0;
239 5342 : typelib_typedescription_getByName( &pTD, rTypeName.pData );
240 5342 : if (pTD)
241 : {
242 5342 : if ((xRet = constructClass( pTD )).is())
243 5342 : _aElements.setValue( rTypeName, makeAny( xRet ) ); // update
244 5342 : typelib_typedescription_release( pTD );
245 : }
246 : }
247 :
248 510672 : return xRet;
249 : }
250 :
251 : // XHierarchicalNameAccess
252 :
253 66 : Any IdlReflectionServiceImpl::getByHierarchicalName( const OUString & rName )
254 : throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException, std::exception)
255 : {
256 66 : Any aRet( _aElements.getValue( rName ) );
257 66 : if (! aRet.hasValue())
258 : {
259 16 : aRet = _xTDMgr->getByHierarchicalName( rName );
260 16 : if (aRet.getValueTypeClass() == TypeClass_INTERFACE)
261 : {
262 : // type retrieved from tdmgr
263 : OSL_ASSERT( (*(Reference< XInterface > *)aRet.getValue())->queryInterface(
264 : ::getCppuType( (const Reference< XTypeDescription > *)0 ) ).hasValue() );
265 :
266 : css::uno::Reference< css::reflection::XConstantTypeDescription >
267 16 : ctd;
268 16 : if (aRet >>= ctd)
269 : {
270 1 : aRet = ctd->getConstantValue();
271 : }
272 : else
273 : {
274 : // if you are interested in a type then CALL forName()!!!
275 : // this way is NOT recommended for types, because this method looks for constants first
276 :
277 : // if td manager found some type, it will be in the cache (hopefully.. we just got it)
278 : // so the second retrieving via c typelib callback chain should succeed...
279 :
280 : // try to get _type_ by name
281 15 : typelib_TypeDescription * pTD = 0;
282 15 : typelib_typedescription_getByName( &pTD, rName.pData );
283 :
284 15 : aRet.clear(); // kick XTypeDescription interface
285 :
286 15 : if (pTD)
287 : {
288 8 : Reference< XIdlClass > xIdlClass( constructClass( pTD ) );
289 8 : aRet.setValue( &xIdlClass, ::getCppuType( (const Reference< XIdlClass > *)0 ) );
290 8 : typelib_typedescription_release( pTD );
291 : }
292 16 : }
293 : }
294 : // else is enum member(?)
295 :
296 : // update
297 16 : if (aRet.hasValue())
298 9 : _aElements.setValue( rName, aRet );
299 : else
300 : {
301 7 : throw NoSuchElementException( rName, Reference< XInterface >() );
302 : }
303 : }
304 59 : return aRet;
305 : }
306 :
307 57 : sal_Bool IdlReflectionServiceImpl::hasByHierarchicalName( const OUString & rName )
308 : throw(::com::sun::star::uno::RuntimeException, std::exception)
309 : {
310 : try
311 : {
312 57 : return getByHierarchicalName( rName ).hasValue();
313 : }
314 0 : catch (NoSuchElementException &)
315 : {
316 : }
317 0 : return sal_False;
318 : }
319 :
320 :
321 35766 : Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescription * pTypeDescr )
322 : throw(::com::sun::star::uno::RuntimeException)
323 : {
324 35766 : Reference< XIdlClass > xRet;
325 71532 : OUString aName( pTypeDescr->pTypeName );
326 71532 : Any aAny( _aElements.getValue( aName ) );
327 :
328 35766 : if (aAny.hasValue())
329 : {
330 32251 : if (aAny.getValueTypeClass() == TypeClass_INTERFACE)
331 32251 : xRet = *(const Reference< XIdlClass > *)aAny.getValue();
332 : }
333 : else
334 : {
335 3515 : if ((xRet = constructClass( pTypeDescr )).is())
336 3515 : _aElements.setValue( aName, makeAny( xRet ) ); // update
337 : }
338 :
339 71532 : return xRet;
340 : }
341 :
342 29393 : Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescriptionReference * pRef )
343 : throw(::com::sun::star::uno::RuntimeException)
344 : {
345 29393 : typelib_TypeDescription * pTD = 0;
346 29393 : TYPELIB_DANGER_GET( &pTD, pRef );
347 29393 : if (pTD)
348 : {
349 29393 : Reference< XIdlClass > xRet = forType( pTD );
350 29393 : TYPELIB_DANGER_RELEASE( pTD );
351 58786 : return xRet;
352 : }
353 : throw RuntimeException(
354 : OUString( "IdlReflectionServiceImpl::forType() failed!" ),
355 0 : (XWeak *)(OWeakObject *)this );
356 : }
357 :
358 :
359 11426 : const Mapping & IdlReflectionServiceImpl::getCpp2Uno()
360 : throw(::com::sun::star::uno::RuntimeException)
361 : {
362 11426 : if (! _aCpp2Uno.is())
363 : {
364 22 : MutexGuard aGuard( getMutexAccess() );
365 22 : if (! _aCpp2Uno.is())
366 : {
367 44 : _aCpp2Uno = Mapping(
368 : OUString( CPPU_CURRENT_LANGUAGE_BINDING_NAME ),
369 22 : OUString( UNO_LB_UNO ) );
370 : OSL_ENSURE( _aCpp2Uno.is(), "### cannot get c++ to uno mapping!" );
371 22 : if (! _aCpp2Uno.is())
372 : {
373 : throw RuntimeException(
374 : OUString("cannot get c++ to uno mapping!"),
375 0 : (XWeak *)(OWeakObject *)this );
376 : }
377 22 : }
378 : }
379 11426 : return _aCpp2Uno;
380 : }
381 :
382 4620 : const Mapping & IdlReflectionServiceImpl::getUno2Cpp()
383 : throw(::com::sun::star::uno::RuntimeException)
384 : {
385 4620 : if (! _aUno2Cpp.is())
386 : {
387 22 : MutexGuard aGuard( getMutexAccess() );
388 22 : if (! _aUno2Cpp.is())
389 : {
390 44 : _aUno2Cpp = Mapping(
391 : OUString( UNO_LB_UNO ),
392 22 : OUString( CPPU_CURRENT_LANGUAGE_BINDING_NAME ) );
393 : OSL_ENSURE( _aUno2Cpp.is(), "### cannot get uno to c++ mapping!" );
394 22 : if (! _aUno2Cpp.is())
395 : {
396 : throw RuntimeException(
397 : OUString("cannot get uno to c++ mapping!"),
398 0 : (XWeak *)(OWeakObject *)this );
399 : }
400 22 : }
401 : }
402 4620 : return _aUno2Cpp;
403 : }
404 :
405 5524 : uno_Interface * IdlReflectionServiceImpl::mapToUno(
406 : const Any & rObj, typelib_InterfaceTypeDescription * pTo )
407 : throw(::com::sun::star::uno::RuntimeException)
408 : {
409 5524 : Reference< XInterface > xObj;
410 5524 : if (extract( rObj, pTo, xObj, this ))
411 11048 : return (uno_Interface *)getCpp2Uno().mapInterface( xObj.get(), pTo );
412 :
413 : throw RuntimeException(
414 : OUString("illegal object given!"),
415 5524 : (XWeak *)(OWeakObject *)this );
416 : }
417 :
418 :
419 82 : Reference< XInterface > SAL_CALL IdlReflectionServiceImpl_create(
420 : const Reference< XComponentContext > & xContext )
421 : throw(::com::sun::star::uno::Exception)
422 : {
423 82 : return Reference< XInterface >( (XWeak *)(OWeakObject *)new IdlReflectionServiceImpl( xContext ) );
424 : }
425 :
426 : }
427 :
428 :
429 : using namespace stoc_corefl;
430 :
431 : static const struct ImplementationEntry g_entries[] =
432 : {
433 : {
434 : IdlReflectionServiceImpl_create, core_getImplementationName,
435 : core_getSupportedServiceNames, createSingleComponentFactory,
436 : 0, 0
437 : },
438 : { 0, 0, 0, 0, 0, 0 }
439 : };
440 :
441 82 : extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL reflection_component_getFactory(
442 : const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
443 : {
444 82 : return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
445 : }
446 :
447 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|