xref: /trunk/main/stoc/source/corereflection/crefl.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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