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