xref: /AOO41X/main/stoc/source/corereflection/crefl.cxx (revision 647a425c57429e1e89af1c7acf2de6af6f1bb730)
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