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