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 { 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 //__________________________________________________________________________________________________ 119 void IdlReflectionServiceImpl::acquire() throw() 120 { 121 OComponentHelper::acquire(); 122 } 123 //__________________________________________________________________________________________________ 124 void IdlReflectionServiceImpl::release() throw() 125 { 126 OComponentHelper::release(); 127 } 128 129 // XTypeProvider 130 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 187 OUString IdlReflectionServiceImpl::getImplementationName() 188 { 189 return core_getImplementationName(); 190 } 191 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 204 Sequence< OUString > IdlReflectionServiceImpl::getSupportedServiceNames() 205 { 206 return core_getSupportedServiceNames(); 207 } 208 209 // XIdlReflection 210 //__________________________________________________________________________________________________ 211 Reference< XIdlClass > IdlReflectionServiceImpl::getType( const Any & rObj ) 212 { 213 return (rObj.hasValue() ? forType( rObj.getValueTypeRef() ) : Reference< XIdlClass >()); 214 } 215 216 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //__________________________________________________________________________________________________ 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 //================================================================================================== 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 { 476 sal_Bool SAL_CALL component_canUnload( TimeValue *pTime ) 477 { 478 return g_moduleCount.canUnload( &g_moduleCount , pTime ); 479 } 480 481 //================================================================================================== 482 void SAL_CALL component_getImplementationEnvironment( 483 const sal_Char ** ppEnvTypeName, uno_Environment ** ) 484 { 485 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 486 } 487 //================================================================================================== 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