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