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