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 0 : static Sequence< OUString > core_getSupportedServiceNames()
49 : {
50 0 : Sequence< OUString > seqNames(1);
51 0 : seqNames.getArray()[0] = OUString( SERVICENAME );
52 0 : return seqNames;
53 : }
54 :
55 0 : static OUString core_getImplementationName()
56 : {
57 0 : return OUString(IMPLNAME);
58 : }
59 :
60 0 : IdlReflectionServiceImpl::IdlReflectionServiceImpl(
61 : const Reference< XComponentContext > & xContext )
62 : : OComponentHelper( _aComponentMutex )
63 0 : , _xMgr( xContext->getServiceManager(), UNO_QUERY )
64 0 : , _aElements( CACHE_SIZE )
65 : {
66 0 : xContext->getValueByName( OUString(
67 0 : "/singletons/com.sun.star.reflection.theTypeDescriptionManager") ) >>= _xTDMgr;
68 : OSL_ENSURE( _xTDMgr.is(), "### cannot get singleton \"TypeDescriptionManager\" from context!" );
69 0 : }
70 :
71 0 : IdlReflectionServiceImpl::~IdlReflectionServiceImpl() {}
72 :
73 : // XInterface
74 :
75 0 : 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 0 : static_cast< XServiceInfo * >( this ) ) );
83 :
84 0 : return (aRet.hasValue() ? aRet : OComponentHelper::queryInterface( rType ));
85 : }
86 :
87 0 : void IdlReflectionServiceImpl::acquire() throw()
88 : {
89 0 : OComponentHelper::acquire();
90 0 : }
91 :
92 0 : void IdlReflectionServiceImpl::release() throw()
93 : {
94 0 : OComponentHelper::release();
95 0 : }
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 0 : void IdlReflectionServiceImpl::dispose()
128 : throw(::com::sun::star::uno::RuntimeException, std::exception)
129 : {
130 0 : OComponentHelper::dispose();
131 :
132 0 : MutexGuard aGuard( _aComponentMutex );
133 0 : _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 0 : }
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 0 : inline Reference< XIdlClass > IdlReflectionServiceImpl::constructClass(
175 : typelib_TypeDescription * pTypeDescr )
176 : {
177 : OSL_ENSURE( pTypeDescr->eTypeClass != typelib_TypeClass_TYPEDEF, "### unexpected typedef!" );
178 :
179 0 : 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 0 : return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
196 :
197 : case TypeClass_ENUM:
198 0 : return new EnumIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
199 :
200 : case typelib_TypeClass_STRUCT:
201 : case typelib_TypeClass_EXCEPTION:
202 0 : return new CompoundIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
203 :
204 : case typelib_TypeClass_SEQUENCE:
205 0 : return new ArrayIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
206 :
207 : case typelib_TypeClass_INTERFACE:
208 0 : return new InterfaceIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
209 :
210 : case typelib_TypeClass_TYPE:
211 0 : 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 0 : Reference< XIdlClass > IdlReflectionServiceImpl::forName( const OUString & rTypeName )
225 : throw(::com::sun::star::uno::RuntimeException, std::exception)
226 : {
227 0 : Reference< XIdlClass > xRet;
228 0 : Any aAny( _aElements.getValue( rTypeName ) );
229 :
230 0 : if (aAny.hasValue())
231 : {
232 0 : if (aAny.getValueTypeClass() == TypeClass_INTERFACE)
233 0 : xRet = *(const Reference< XIdlClass > *)aAny.getValue();
234 : }
235 : else
236 : {
237 : // try to get _type_ by name
238 0 : typelib_TypeDescription * pTD = 0;
239 0 : typelib_typedescription_getByName( &pTD, rTypeName.pData );
240 0 : if (pTD)
241 : {
242 0 : if ((xRet = constructClass( pTD )).is())
243 0 : _aElements.setValue( rTypeName, makeAny( xRet ) ); // update
244 0 : typelib_typedescription_release( pTD );
245 : }
246 : }
247 :
248 0 : return xRet;
249 : }
250 :
251 : // XHierarchicalNameAccess
252 :
253 0 : Any IdlReflectionServiceImpl::getByHierarchicalName( const OUString & rName )
254 : throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException, std::exception)
255 : {
256 0 : Any aRet( _aElements.getValue( rName ) );
257 0 : if (! aRet.hasValue())
258 : {
259 0 : aRet = _xTDMgr->getByHierarchicalName( rName );
260 0 : 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 0 : ctd;
268 0 : if (aRet >>= ctd)
269 : {
270 0 : 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 0 : typelib_TypeDescription * pTD = 0;
282 0 : typelib_typedescription_getByName( &pTD, rName.pData );
283 :
284 0 : aRet.clear(); // kick XTypeDescription interface
285 :
286 0 : if (pTD)
287 : {
288 0 : Reference< XIdlClass > xIdlClass( constructClass( pTD ) );
289 0 : aRet.setValue( &xIdlClass, ::getCppuType( (const Reference< XIdlClass > *)0 ) );
290 0 : typelib_typedescription_release( pTD );
291 : }
292 0 : }
293 : }
294 : // else is enum member(?)
295 :
296 : // update
297 0 : if (aRet.hasValue())
298 0 : _aElements.setValue( rName, aRet );
299 : else
300 : {
301 0 : throw NoSuchElementException( rName, Reference< XInterface >() );
302 : }
303 : }
304 0 : return aRet;
305 : }
306 :
307 0 : sal_Bool IdlReflectionServiceImpl::hasByHierarchicalName( const OUString & rName )
308 : throw(::com::sun::star::uno::RuntimeException, std::exception)
309 : {
310 : try
311 : {
312 0 : return getByHierarchicalName( rName ).hasValue();
313 : }
314 0 : catch (NoSuchElementException &)
315 : {
316 : }
317 0 : return sal_False;
318 : }
319 :
320 :
321 0 : Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescription * pTypeDescr )
322 : throw(::com::sun::star::uno::RuntimeException)
323 : {
324 0 : Reference< XIdlClass > xRet;
325 0 : OUString aName( pTypeDescr->pTypeName );
326 0 : Any aAny( _aElements.getValue( aName ) );
327 :
328 0 : if (aAny.hasValue())
329 : {
330 0 : if (aAny.getValueTypeClass() == TypeClass_INTERFACE)
331 0 : xRet = *(const Reference< XIdlClass > *)aAny.getValue();
332 : }
333 : else
334 : {
335 0 : if ((xRet = constructClass( pTypeDescr )).is())
336 0 : _aElements.setValue( aName, makeAny( xRet ) ); // update
337 : }
338 :
339 0 : return xRet;
340 : }
341 :
342 0 : Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescriptionReference * pRef )
343 : throw(::com::sun::star::uno::RuntimeException)
344 : {
345 0 : typelib_TypeDescription * pTD = 0;
346 0 : TYPELIB_DANGER_GET( &pTD, pRef );
347 0 : if (pTD)
348 : {
349 0 : Reference< XIdlClass > xRet = forType( pTD );
350 0 : TYPELIB_DANGER_RELEASE( pTD );
351 0 : return xRet;
352 : }
353 : throw RuntimeException(
354 : OUString( "IdlReflectionServiceImpl::forType() failed!" ),
355 0 : (XWeak *)(OWeakObject *)this );
356 : }
357 :
358 :
359 0 : const Mapping & IdlReflectionServiceImpl::getCpp2Uno()
360 : throw(::com::sun::star::uno::RuntimeException)
361 : {
362 0 : if (! _aCpp2Uno.is())
363 : {
364 0 : MutexGuard aGuard( getMutexAccess() );
365 0 : if (! _aCpp2Uno.is())
366 : {
367 0 : _aCpp2Uno = Mapping(
368 : OUString( CPPU_CURRENT_LANGUAGE_BINDING_NAME ),
369 0 : OUString( UNO_LB_UNO ) );
370 : OSL_ENSURE( _aCpp2Uno.is(), "### cannot get c++ to uno mapping!" );
371 0 : if (! _aCpp2Uno.is())
372 : {
373 : throw RuntimeException(
374 : OUString("cannot get c++ to uno mapping!"),
375 0 : (XWeak *)(OWeakObject *)this );
376 : }
377 0 : }
378 : }
379 0 : return _aCpp2Uno;
380 : }
381 :
382 0 : const Mapping & IdlReflectionServiceImpl::getUno2Cpp()
383 : throw(::com::sun::star::uno::RuntimeException)
384 : {
385 0 : if (! _aUno2Cpp.is())
386 : {
387 0 : MutexGuard aGuard( getMutexAccess() );
388 0 : if (! _aUno2Cpp.is())
389 : {
390 0 : _aUno2Cpp = Mapping(
391 : OUString( UNO_LB_UNO ),
392 0 : OUString( CPPU_CURRENT_LANGUAGE_BINDING_NAME ) );
393 : OSL_ENSURE( _aUno2Cpp.is(), "### cannot get uno to c++ mapping!" );
394 0 : if (! _aUno2Cpp.is())
395 : {
396 : throw RuntimeException(
397 : OUString("cannot get uno to c++ mapping!"),
398 0 : (XWeak *)(OWeakObject *)this );
399 : }
400 0 : }
401 : }
402 0 : return _aUno2Cpp;
403 : }
404 :
405 0 : uno_Interface * IdlReflectionServiceImpl::mapToUno(
406 : const Any & rObj, typelib_InterfaceTypeDescription * pTo )
407 : throw(::com::sun::star::uno::RuntimeException)
408 : {
409 0 : Reference< XInterface > xObj;
410 0 : if (extract( rObj, pTo, xObj, this ))
411 0 : return (uno_Interface *)getCpp2Uno().mapInterface( xObj.get(), pTo );
412 :
413 : throw RuntimeException(
414 : OUString("illegal object given!"),
415 0 : (XWeak *)(OWeakObject *)this );
416 : }
417 :
418 :
419 0 : Reference< XInterface > SAL_CALL IdlReflectionServiceImpl_create(
420 : const Reference< XComponentContext > & xContext )
421 : throw(::com::sun::star::uno::Exception)
422 : {
423 0 : 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 0 : extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL reflection_component_getFactory(
442 : const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
443 : {
444 0 : return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
445 : }
446 :
447 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|