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 {
110 Any aRet( ::cppu::queryInterface(
111 rType,
112 static_cast< XIdlReflection * >( this ),
113 static_cast< XHierarchicalNameAccess * >( this ),
114 static_cast< XServiceInfo * >( this ) ) );
115
116 return (aRet.hasValue() ? aRet : OComponentHelper::queryInterface( rType ));
117 }
118 //__________________________________________________________________________________________________
acquire()119 void IdlReflectionServiceImpl::acquire() throw()
120 {
121 OComponentHelper::acquire();
122 }
123 //__________________________________________________________________________________________________
release()124 void IdlReflectionServiceImpl::release() throw()
125 {
126 OComponentHelper::release();
127 }
128
129 // XTypeProvider
130 //__________________________________________________________________________________________________
getTypes()131 Sequence< Type > IdlReflectionServiceImpl::getTypes()
132 {
133 static OTypeCollection * s_pTypes = 0;
134 if (! s_pTypes)
135 {
136 MutexGuard aGuard( _aComponentMutex );
137 if (! s_pTypes)
138 {
139 static OTypeCollection s_aTypes(
140 ::getCppuType( (const Reference< XIdlReflection > *)0 ),
141 ::getCppuType( (const Reference< XHierarchicalNameAccess > *)0 ),
142 ::getCppuType( (const Reference< XServiceInfo > *)0 ),
143 OComponentHelper::getTypes() );
144 s_pTypes = &s_aTypes;
145 }
146 }
147 return s_pTypes->getTypes();
148 }
149 //__________________________________________________________________________________________________
getImplementationId()150 Sequence< sal_Int8 > IdlReflectionServiceImpl::getImplementationId()
151 {
152 static OImplementationId * s_pId = 0;
153 if (! s_pId)
154 {
155 MutexGuard aGuard( _aComponentMutex );
156 if (! s_pId)
157 {
158 static OImplementationId s_aId;
159 s_pId = &s_aId;
160 }
161 }
162 return s_pId->getImplementationId();
163 }
164
165 // XComponent
166 //__________________________________________________________________________________________________
dispose()167 void IdlReflectionServiceImpl::dispose()
168 {
169 TRACE( "> disposing corereflection... <" );
170 OComponentHelper::dispose();
171
172 MutexGuard aGuard( _aComponentMutex );
173 _aElements.clear();
174 #ifdef TEST_LIST_CLASSES
175 OSL_ENSURE( g_aClassNames.size() == 0, "### idl classes still alive!" );
176 ClassNameList::const_iterator iPos( g_aClassNames.begin() );
177 while (iPos != g_aClassNames.end())
178 {
179 OUString aName( *iPos );
180 ++iPos;
181 }
182 #endif
183 }
184
185 // XServiceInfo
186 //__________________________________________________________________________________________________
getImplementationName()187 OUString IdlReflectionServiceImpl::getImplementationName()
188 {
189 return core_getImplementationName();
190 }
191 //__________________________________________________________________________________________________
supportsService(const OUString & rServiceName)192 sal_Bool IdlReflectionServiceImpl::supportsService( const OUString & rServiceName )
193 {
194 const Sequence< OUString > & rSNL = getSupportedServiceNames();
195 const OUString * pArray = rSNL.getConstArray();
196 for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
197 {
198 if (pArray[nPos] == rServiceName)
199 return sal_True;
200 }
201 return sal_False;
202 }
203 //__________________________________________________________________________________________________
getSupportedServiceNames()204 Sequence< OUString > IdlReflectionServiceImpl::getSupportedServiceNames()
205 {
206 return core_getSupportedServiceNames();
207 }
208
209 // XIdlReflection
210 //__________________________________________________________________________________________________
getType(const Any & rObj)211 Reference< XIdlClass > IdlReflectionServiceImpl::getType( const Any & rObj )
212 {
213 return (rObj.hasValue() ? forType( rObj.getValueTypeRef() ) : Reference< XIdlClass >());
214 }
215
216 //__________________________________________________________________________________________________
constructClass(typelib_TypeDescription * pTypeDescr)217 inline Reference< XIdlClass > IdlReflectionServiceImpl::constructClass(
218 typelib_TypeDescription * pTypeDescr )
219 {
220 OSL_ENSURE( pTypeDescr->eTypeClass != typelib_TypeClass_TYPEDEF, "### unexpected typedef!" );
221
222 switch (pTypeDescr->eTypeClass)
223 {
224 case typelib_TypeClass_VOID:
225 case typelib_TypeClass_CHAR:
226 case typelib_TypeClass_BOOLEAN:
227 case typelib_TypeClass_BYTE:
228 case typelib_TypeClass_SHORT:
229 case typelib_TypeClass_UNSIGNED_SHORT:
230 case typelib_TypeClass_LONG:
231 case typelib_TypeClass_UNSIGNED_LONG:
232 case typelib_TypeClass_HYPER:
233 case typelib_TypeClass_UNSIGNED_HYPER:
234 case typelib_TypeClass_FLOAT:
235 case typelib_TypeClass_DOUBLE:
236 case typelib_TypeClass_STRING:
237 case typelib_TypeClass_ANY:
238 return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
239
240 case TypeClass_ENUM:
241 return new EnumIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
242
243 case typelib_TypeClass_STRUCT:
244 case typelib_TypeClass_UNION:
245 case typelib_TypeClass_EXCEPTION:
246 return new CompoundIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
247
248 case typelib_TypeClass_ARRAY:
249 case typelib_TypeClass_SEQUENCE:
250 return new ArrayIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
251
252 case typelib_TypeClass_INTERFACE:
253 return new InterfaceIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
254
255 case typelib_TypeClass_TYPE:
256 return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr );
257
258 default:
259 #if OSL_DEBUG_LEVEL > 1
260 OSL_TRACE( "### corereflection type unsupported: " );
261 OString aName( OUStringToOString( pTypeDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
262 OSL_TRACE( aName.getStr() );
263 OSL_TRACE( "\n" );
264 #endif
265 return Reference< XIdlClass >();
266 }
267 }
268 //__________________________________________________________________________________________________
forName(const OUString & rTypeName)269 Reference< XIdlClass > IdlReflectionServiceImpl::forName( const OUString & rTypeName )
270 {
271 Reference< XIdlClass > xRet;
272 Any aAny( _aElements.getValue( rTypeName ) );
273
274 if (aAny.hasValue())
275 {
276 if (aAny.getValueTypeClass() == TypeClass_INTERFACE)
277 xRet = *(const Reference< XIdlClass > *)aAny.getValue();
278 }
279 else
280 {
281 // try to get _type_ by name
282 typelib_TypeDescription * pTD = 0;
283 typelib_typedescription_getByName( &pTD, rTypeName.pData );
284 if (pTD)
285 {
286 if ((xRet = constructClass( pTD )).is())
287 _aElements.setValue( rTypeName, makeAny( xRet ) ); // update
288 typelib_typedescription_release( pTD );
289 }
290 }
291
292 return xRet;
293 }
294
295 // XHierarchicalNameAccess
296 //__________________________________________________________________________________________________
getByHierarchicalName(const OUString & rName)297 Any IdlReflectionServiceImpl::getByHierarchicalName( const OUString & rName )
298 {
299 Any aRet( _aElements.getValue( rName ) );
300 if (! aRet.hasValue())
301 {
302 // first look for constants exclusivly!
303 aRet = _xTDMgr->getByHierarchicalName( rName );
304 if (aRet.getValueTypeClass() == TypeClass_INTERFACE) // if no constant,
305 // i.e. XTypeDescription for a type
306 {
307 // type retrieved from tdmgr
308 OSL_ASSERT( (*(Reference< XInterface > *)aRet.getValue())->queryInterface(
309 ::getCppuType( (const Reference< XTypeDescription > *)0 ) ).hasValue() );
310
311 // if you are interested in a type then CALL forName()!!!
312 // this way is NOT recommended for types, because this method looks for constants first
313
314 // if td manager found some type, it will be in the cache (hopefully.. we just got it)
315 // so the second retrieving via c typelib callback chain should succeed...
316
317 // try to get _type_ by name
318 typelib_TypeDescription * pTD = 0;
319 typelib_typedescription_getByName( &pTD, rName.pData );
320
321 aRet.clear(); // kick XTypeDescription interface
322
323 if (pTD)
324 {
325 Reference< XIdlClass > xIdlClass( constructClass( pTD ) );
326 aRet.setValue( &xIdlClass, ::getCppuType( (const Reference< XIdlClass > *)0 ) );
327 typelib_typedescription_release( pTD );
328 }
329 }
330 // else is constant
331
332 // update
333 if (aRet.hasValue())
334 _aElements.setValue( rName, aRet );
335 else
336 {
337 throw NoSuchElementException( rName, Reference< XInterface >() );
338 }
339 }
340 return aRet;
341 }
342 //__________________________________________________________________________________________________
hasByHierarchicalName(const OUString & rName)343 sal_Bool IdlReflectionServiceImpl::hasByHierarchicalName( const OUString & rName )
344 {
345 try
346 {
347 return getByHierarchicalName( rName ).hasValue();
348 }
349 catch (NoSuchElementException &)
350 {
351 }
352 return sal_False;
353 }
354
355 //__________________________________________________________________________________________________
forType(typelib_TypeDescription * pTypeDescr)356 Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescription * pTypeDescr )
357 {
358 Reference< XIdlClass > xRet;
359 OUString aName( pTypeDescr->pTypeName );
360 Any aAny( _aElements.getValue( aName ) );
361
362 if (aAny.hasValue())
363 {
364 if (aAny.getValueTypeClass() == TypeClass_INTERFACE)
365 xRet = *(const Reference< XIdlClass > *)aAny.getValue();
366 }
367 else
368 {
369 if (pTypeDescr && (xRet = constructClass( pTypeDescr )).is())
370 _aElements.setValue( aName, makeAny( xRet ) ); // update
371 }
372
373 return xRet;
374 }
375 //__________________________________________________________________________________________________
forType(typelib_TypeDescriptionReference * pRef)376 Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescriptionReference * pRef )
377 {
378 typelib_TypeDescription * pTD = 0;
379 TYPELIB_DANGER_GET( &pTD, pRef );
380 if (pTD)
381 {
382 Reference< XIdlClass > xRet = forType( pTD );
383 TYPELIB_DANGER_RELEASE( pTD );
384 return xRet;
385 }
386 throw RuntimeException(
387 OUString( RTL_CONSTASCII_USTRINGPARAM("IdlReflectionServiceImpl::forType() failed!") ),
388 (XWeak *)(OWeakObject *)this );
389 }
390
391 //__________________________________________________________________________________________________
getCpp2Uno()392 const Mapping & IdlReflectionServiceImpl::getCpp2Uno()
393 {
394 if (! _aCpp2Uno.is())
395 {
396 MutexGuard aGuard( getMutexAccess() );
397 if (! _aCpp2Uno.is())
398 {
399 _aCpp2Uno = Mapping(
400 OUString( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) ),
401 OUString( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) ) );
402 OSL_ENSURE( _aCpp2Uno.is(), "### cannot get c++ to uno mapping!" );
403 if (! _aCpp2Uno.is())
404 {
405 throw RuntimeException(
406 OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get c++ to uno mapping!") ),
407 (XWeak *)(OWeakObject *)this );
408 }
409 }
410 }
411 return _aCpp2Uno;
412 }
413 //__________________________________________________________________________________________________
getUno2Cpp()414 const Mapping & IdlReflectionServiceImpl::getUno2Cpp()
415 {
416 if (! _aUno2Cpp.is())
417 {
418 MutexGuard aGuard( getMutexAccess() );
419 if (! _aUno2Cpp.is())
420 {
421 _aUno2Cpp = Mapping(
422 OUString( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) ),
423 OUString( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) ) );
424 OSL_ENSURE( _aUno2Cpp.is(), "### cannot get uno to c++ mapping!" );
425 if (! _aUno2Cpp.is())
426 {
427 throw RuntimeException(
428 OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get uno to c++ mapping!") ),
429 (XWeak *)(OWeakObject *)this );
430 }
431 }
432 }
433 return _aUno2Cpp;
434 }
435 //__________________________________________________________________________________________________
mapToUno(const Any & rObj,typelib_InterfaceTypeDescription * pTo)436 uno_Interface * IdlReflectionServiceImpl::mapToUno(
437 const Any & rObj, typelib_InterfaceTypeDescription * pTo )
438 {
439 Reference< XInterface > xObj;
440 if (extract( rObj, pTo, xObj, this ))
441 return (uno_Interface *)getCpp2Uno().mapInterface( xObj.get(), pTo );
442
443 throw RuntimeException(
444 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ),
445 (XWeak *)(OWeakObject *)this );
446 }
447
448 //==================================================================================================
IdlReflectionServiceImpl_create(const Reference<XComponentContext> & xContext)449 Reference< XInterface > SAL_CALL IdlReflectionServiceImpl_create(
450 const Reference< XComponentContext > & xContext )
451 {
452 return Reference< XInterface >( (XWeak *)(OWeakObject *)new IdlReflectionServiceImpl( xContext ) );
453 }
454
455 }
456
457
458 //##################################################################################################
459 //##################################################################################################
460 //##################################################################################################
461
462 using namespace stoc_corefl;
463
464 static struct ImplementationEntry g_entries[] =
465 {
466 {
467 IdlReflectionServiceImpl_create, core_getImplementationName,
468 core_getSupportedServiceNames, createSingleComponentFactory,
469 &g_moduleCount.modCnt , 0
470 },
471 { 0, 0, 0, 0, 0, 0 }
472 };
473
474 extern "C"
475 {
component_canUnload(TimeValue * pTime)476 sal_Bool SAL_CALL component_canUnload( TimeValue *pTime )
477 {
478 return g_moduleCount.canUnload( &g_moduleCount , pTime );
479 }
480
481 //==================================================================================================
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment **)482 void SAL_CALL component_getImplementationEnvironment(
483 const sal_Char ** ppEnvTypeName, uno_Environment ** )
484 {
485 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
486 }
487 //==================================================================================================
component_getFactory(const sal_Char * pImplName,void * pServiceManager,void * pRegistryKey)488 void * SAL_CALL component_getFactory(
489 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
490 {
491 return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
492 }
493 }
494