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