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 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 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 100 IdlReflectionServiceImpl::~IdlReflectionServiceImpl() 101 { 102 TRACE( "> IdlReflectionServiceImpl dtor <\n" ); 103 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 104 } 105 106 // XInterface 107 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 120 void IdlReflectionServiceImpl::acquire() throw() 121 { 122 OComponentHelper::acquire(); 123 } 124 //__________________________________________________________________________________________________ 125 void IdlReflectionServiceImpl::release() throw() 126 { 127 OComponentHelper::release(); 128 } 129 130 // XTypeProvider 131 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 191 OUString IdlReflectionServiceImpl::getImplementationName() 192 throw(::com::sun::star::uno::RuntimeException) 193 { 194 return core_getImplementationName(); 195 } 196 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 210 Sequence< OUString > IdlReflectionServiceImpl::getSupportedServiceNames() 211 throw(::com::sun::star::uno::RuntimeException) 212 { 213 return core_getSupportedServiceNames(); 214 } 215 216 // XIdlReflection 217 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //================================================================================================== 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 { 493 sal_Bool SAL_CALL component_canUnload( TimeValue *pTime ) 494 { 495 return g_moduleCount.canUnload( &g_moduleCount , pTime ); 496 } 497 498 //================================================================================================== 499 void SAL_CALL component_getImplementationEnvironment( 500 const sal_Char ** ppEnvTypeName, uno_Environment ** ) 501 { 502 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 503 } 504 //================================================================================================== 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