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 <osl/diagnose.h> 27 #include <osl/mutex.hxx> 28 #include <uno/dispatcher.h> 29 #include <uno/mapping.hxx> 30 #include <cppuhelper/factory.hxx> 31 #include <cppuhelper/compbase4.hxx> 32 #include <cppuhelper/implbase2.hxx> 33 #include <cppuhelper/typeprovider.hxx> 34 35 #include <cppuhelper/weakref.hxx> 36 37 #include <com/sun/star/lang/XServiceInfo.hpp> 38 #include <com/sun/star/lang/XComponent.hpp> 39 #include <com/sun/star/lang/XTypeProvider.hpp> 40 #include <com/sun/star/lang/XInitialization.hpp> 41 #include <com/sun/star/registry/XSimpleRegistry.hpp> 42 #include <com/sun/star/registry/XRegistryKey.hpp> 43 #include <com/sun/star/beans/XPropertySet.hpp> 44 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> 45 #include "com/sun/star/uno/RuntimeException.hpp" 46 47 #include "registry/reader.hxx" 48 #include "registry/version.h" 49 #include "base.hxx" 50 #include "rdbtdp_tdenumeration.hxx" 51 #include "structtypedescription.hxx" 52 53 #define SERVICENAME "com.sun.star.reflection.TypeDescriptionProvider" 54 #define IMPLNAME "com.sun.star.comp.stoc.RegistryTypeDescriptionProvider" 55 56 using namespace com::sun::star; 57 using namespace com::sun::star::beans; 58 using namespace com::sun::star::registry; 59 60 extern rtl_StandardModuleCount g_moduleCount; 61 62 namespace stoc_bootstrap 63 { 64 uno::Sequence< OUString > rdbtdp_getSupportedServiceNames() 65 { 66 static Sequence < OUString > *pNames = 0; 67 if( ! pNames ) 68 { 69 MutexGuard guard( Mutex::getGlobalMutex() ); 70 if( !pNames ) 71 { 72 static Sequence< OUString > seqNames(1); 73 seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); 74 pNames = &seqNames; 75 } 76 } 77 return *pNames; 78 } 79 80 OUString rdbtdp_getImplementationName() 81 { 82 static OUString *pImplName = 0; 83 if( ! pImplName ) 84 { 85 MutexGuard guard( Mutex::getGlobalMutex() ); 86 if( ! pImplName ) 87 { 88 static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); 89 pImplName = &implName; 90 } 91 } 92 return *pImplName; 93 } 94 } 95 96 namespace stoc_rdbtdp 97 { 98 struct MutexHolder 99 { 100 Mutex _aComponentMutex; 101 }; 102 //================================================================================================== 103 class ProviderImpl 104 : public MutexHolder 105 , public WeakComponentImplHelper4< XServiceInfo, 106 XHierarchicalNameAccess, 107 XTypeDescriptionEnumerationAccess, 108 XInitialization > 109 { 110 // XHierarchicalNameAccess + XTypeDescriptionEnumerationAccess wrapper 111 // first asking the tdmgr instance, then looking up locally 112 class TypeDescriptionManagerWrapper 113 : public ::cppu::WeakImplHelper2< 114 container::XHierarchicalNameAccess, 115 reflection::XTypeDescriptionEnumerationAccess> 116 { 117 com::sun::star::uno::Reference<container::XHierarchicalNameAccess> 118 m_xTDMgr; 119 com::sun::star::uno::Reference<container::XHierarchicalNameAccess> 120 m_xThisProvider; 121 public: 122 TypeDescriptionManagerWrapper( ProviderImpl * pProvider ) 123 : m_xTDMgr( pProvider->_xContext->getValueByName( 124 OUString( RTL_CONSTASCII_USTRINGPARAM( 125 "/singletons/com.sun.star.reflection." 126 "theTypeDescriptionManager") ) ), 127 UNO_QUERY_THROW ), 128 m_xThisProvider( pProvider ) 129 {} 130 // XHierarchicalNameAccess 131 virtual Any SAL_CALL getByHierarchicalName( OUString const & name ); 132 virtual sal_Bool SAL_CALL hasByHierarchicalName( OUString const & name ); 133 134 // XTypeDescriptionEnumerationAccess 135 virtual uno::Reference< 136 reflection::XTypeDescriptionEnumeration > SAL_CALL 137 createTypeDescriptionEnumeration( 138 const ::rtl::OUString& moduleName, 139 const uno::Sequence< uno::TypeClass >& types, 140 reflection::TypeDescriptionSearchDepth depth ); 141 }; 142 friend class TypeDescriptionManagerWrapper; 143 144 com::sun::star::uno::Reference< XComponentContext > _xContext; 145 com::sun::star::uno::WeakReference<XHierarchicalNameAccess> _xTDMgr; 146 com::sun::star::uno::Reference< XHierarchicalNameAccess > getTDMgr() SAL_THROW( () ); 147 148 RegistryKeyList _aBaseKeys; 149 150 protected: 151 virtual void SAL_CALL disposing(); 152 153 public: 154 ProviderImpl( const com::sun::star::uno::Reference< XComponentContext > & xContext ); 155 virtual ~ProviderImpl(); 156 157 // XInitialization 158 virtual void SAL_CALL initialize( const Sequence< Any > & args ); 159 160 // XServiceInfo 161 virtual OUString SAL_CALL getImplementationName(); 162 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ); 163 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(); 164 165 // XHierarchicalNameAccess 166 Any getByHierarchicalNameImpl( const OUString & rName ); 167 168 virtual Any SAL_CALL getByHierarchicalName( const OUString & rName ); 169 virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ); 170 171 // XTypeDescriptionEnumerationAccess 172 virtual ::com::sun::star::uno::Reference< 173 ::com::sun::star::reflection::XTypeDescriptionEnumeration > SAL_CALL 174 createTypeDescriptionEnumeration( 175 const ::rtl::OUString& moduleName, 176 const ::com::sun::star::uno::Sequence< 177 ::com::sun::star::uno::TypeClass >& types, 178 ::com::sun::star::reflection::TypeDescriptionSearchDepth depth ); 179 }; 180 //__________________________________________________________________________________________________ 181 ProviderImpl::ProviderImpl( const com::sun::star::uno::Reference< XComponentContext > & xContext ) 182 : WeakComponentImplHelper4< 183 XServiceInfo, XHierarchicalNameAccess, 184 XTypeDescriptionEnumerationAccess, XInitialization >( _aComponentMutex ) 185 , _xContext( xContext ) 186 { 187 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 188 } 189 //__________________________________________________________________________________________________ 190 ProviderImpl::~ProviderImpl() 191 { 192 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 193 } 194 195 //______________________________________________________________________________ 196 Any ProviderImpl::TypeDescriptionManagerWrapper::getByHierarchicalName( 197 OUString const & name ) 198 { 199 try 200 { 201 // first try tdmgr: 202 return m_xTDMgr->getByHierarchicalName( name ); 203 } 204 catch (container::NoSuchElementException &) 205 { 206 // then lookup locally: 207 return m_xThisProvider->getByHierarchicalName( name ); 208 } 209 } 210 211 //______________________________________________________________________________ 212 sal_Bool ProviderImpl::TypeDescriptionManagerWrapper::hasByHierarchicalName( 213 OUString const & name ) 214 { 215 return m_xTDMgr->hasByHierarchicalName( name ) || m_xThisProvider->hasByHierarchicalName( name ); 216 } 217 218 //______________________________________________________________________________ 219 uno::Reference< reflection::XTypeDescriptionEnumeration > SAL_CALL 220 ProviderImpl::TypeDescriptionManagerWrapper::createTypeDescriptionEnumeration( 221 const ::rtl::OUString& moduleName, 222 const uno::Sequence< uno::TypeClass >& types, 223 reflection::TypeDescriptionSearchDepth depth ) 224 { 225 try 226 { 227 // first try tdmgr: 228 uno::Reference< reflection::XTypeDescriptionEnumerationAccess > xTDEA( 229 m_xTDMgr, uno::UNO_QUERY_THROW ); 230 return 231 xTDEA->createTypeDescriptionEnumeration( moduleName, types, depth ); 232 } 233 catch (reflection::NoSuchTypeNameException &) 234 { 235 // then lookup locally: 236 uno::Reference< reflection::XTypeDescriptionEnumerationAccess > xTDEA( 237 m_xThisProvider, uno::UNO_QUERY_THROW ); 238 return 239 xTDEA->createTypeDescriptionEnumeration( moduleName, types, depth ); 240 } 241 } 242 243 //__________________________________________________________________________________________________ 244 com::sun::star::uno::Reference< XHierarchicalNameAccess > ProviderImpl::getTDMgr() 245 SAL_THROW( () ) 246 { 247 // harden weak reference: 248 com::sun::star::uno::Reference<container::XHierarchicalNameAccess> xTDMgr( 249 _xTDMgr ); 250 if (! xTDMgr.is()) 251 { 252 xTDMgr.set( new TypeDescriptionManagerWrapper(this) ); 253 { 254 MutexGuard guard( _aComponentMutex ); 255 _xTDMgr = xTDMgr; 256 } 257 } 258 return xTDMgr; 259 } 260 261 //__________________________________________________________________________________________________ 262 void ProviderImpl::disposing() 263 { 264 _xContext.clear(); 265 266 for ( RegistryKeyList::const_iterator iPos( _aBaseKeys.begin() ); 267 iPos != _aBaseKeys.end(); ++iPos ) 268 { 269 (*iPos)->closeKey(); 270 } 271 _aBaseKeys.clear(); 272 } 273 274 // XInitialization 275 //__________________________________________________________________________________________________ 276 void ProviderImpl::initialize( 277 const Sequence< Any > & args ) 278 { 279 // registries to read from 280 Any const * pRegistries = args.getConstArray(); 281 for ( sal_Int32 nPos = 0; nPos < args.getLength(); ++nPos ) 282 { 283 com::sun::star::uno::Reference< XSimpleRegistry > xRegistry( pRegistries[ nPos ], UNO_QUERY ); 284 if (xRegistry.is() && xRegistry->isValid()) 285 { 286 com::sun::star::uno::Reference< XRegistryKey > xKey( xRegistry->getRootKey()->openKey( 287 OUString( RTL_CONSTASCII_USTRINGPARAM("/UCR") ) ) ); 288 if (xKey.is() && xKey->isValid()) 289 { 290 _aBaseKeys.push_back( xKey ); 291 } 292 } 293 } 294 } 295 296 // XServiceInfo 297 //__________________________________________________________________________________________________ 298 OUString ProviderImpl::getImplementationName() 299 { 300 return stoc_bootstrap::rdbtdp_getImplementationName(); 301 } 302 //__________________________________________________________________________________________________ 303 sal_Bool ProviderImpl::supportsService( const OUString & rServiceName ) 304 { 305 const Sequence< OUString > & rSNL = getSupportedServiceNames(); 306 const OUString * pArray = rSNL.getConstArray(); 307 for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) 308 { 309 if (pArray[nPos] == rServiceName) 310 return sal_True; 311 } 312 return sal_False; 313 } 314 //__________________________________________________________________________________________________ 315 Sequence< OUString > ProviderImpl::getSupportedServiceNames() 316 { 317 return stoc_bootstrap::rdbtdp_getSupportedServiceNames(); 318 } 319 320 // XHierarchicalNameAccess 321 //__________________________________________________________________________________________________ 322 Any ProviderImpl::getByHierarchicalNameImpl( const OUString & rName ) 323 { 324 Any aRet; 325 326 // read from registry 327 OUString aKey( rName.replace( '.', '/' ) ); 328 for ( RegistryKeyList::const_iterator iPos( _aBaseKeys.begin() ); 329 !aRet.hasValue() && iPos != _aBaseKeys.end(); ++iPos ) 330 { 331 try 332 { 333 com::sun::star::uno::Reference< XRegistryKey > xBaseKey( *iPos ); 334 com::sun::star::uno::Reference< XRegistryKey > xKey( xBaseKey->openKey( aKey ) ); 335 if (xKey.is()) 336 { 337 // closes key in it's dtor (which is 338 // called even in case of exceptions). 339 RegistryKeyCloser aCloser( xKey ); 340 341 if ( xKey->isValid() ) 342 { 343 if (xKey->getValueType() == RegistryValueType_BINARY) 344 { 345 Sequence< sal_Int8 > aBytes( xKey->getBinaryValue() ); 346 com::sun::star::uno::Reference< XTypeDescription > xTD( 347 createTypeDescription( aBytes, 348 getTDMgr(), 349 true ) ); 350 if ( xTD.is() ) 351 aRet <<= xTD; 352 } 353 } 354 } 355 else // might be a constant 356 { 357 sal_Int32 nIndex = aKey.lastIndexOf( '/' ); 358 if (nIndex > 0) 359 { 360 // open module 361 com::sun::star::uno::Reference< XRegistryKey > xKey2( xBaseKey->openKey( aKey.copy( 0, nIndex ) ) ); 362 if (xKey2.is()) 363 { 364 // closes key in it's dtor (which is 365 // called even in case of exceptions). 366 RegistryKeyCloser aCloser( xKey2 ); 367 368 if ( xKey2->isValid() ) 369 { 370 if (xKey2->getValueType() == RegistryValueType_BINARY) 371 { 372 Sequence< sal_Int8 > aBytes( xKey2->getBinaryValue() ); 373 typereg::Reader aReader( 374 aBytes.getConstArray(), aBytes.getLength(), 375 false, TYPEREG_VERSION_1); 376 377 if (aReader.getTypeClass() == RT_TYPE_MODULE || 378 aReader.getTypeClass() == RT_TYPE_CONSTANTS || 379 aReader.getTypeClass() == RT_TYPE_ENUM) 380 { 381 OUString aFieldName( aKey.copy( nIndex+1, aKey.getLength() - nIndex -1 ) ); 382 sal_Int16 nPos = aReader.getFieldCount(); 383 while (nPos--) 384 { 385 if (aFieldName.equals( 386 aReader.getFieldName(nPos))) 387 break; 388 } 389 if (nPos >= 0) 390 aRet = getRTValue( 391 aReader.getFieldValue(nPos)); 392 } 393 } 394 } 395 } 396 } 397 } 398 } 399 catch ( InvalidRegistryException const & ) 400 { 401 OSL_ENSURE( sal_False, 402 "ProviderImpl::getByHierarchicalName " 403 "- Caught InvalidRegistryException!" ); 404 405 // openKey, closeKey, getValueType, getBinaryValue, isValid 406 407 // Don't stop iteration in this case. 408 } 409 catch ( NoSuchElementException const & ) 410 { 411 } 412 } 413 return aRet; 414 } 415 416 Any SAL_CALL ProviderImpl::getByHierarchicalName( const OUString & rName ) 417 { 418 Any aRet( getByHierarchicalNameImpl( rName ) ); 419 420 if ( !aRet.hasValue() ) 421 throw NoSuchElementException( 422 rName, static_cast< cppu::OWeakObject * >( this ) ); 423 424 return aRet; 425 } 426 427 //__________________________________________________________________________________________________ 428 sal_Bool ProviderImpl::hasByHierarchicalName( const OUString & rName ) 429 { 430 return getByHierarchicalNameImpl( rName ).hasValue(); 431 } 432 433 // XTypeDescriptionEnumerationAccess 434 //__________________________________________________________________________________________________ 435 // virtual 436 com::sun::star::uno::Reference< XTypeDescriptionEnumeration > SAL_CALL 437 ProviderImpl::createTypeDescriptionEnumeration( 438 const OUString & moduleName, 439 const Sequence< TypeClass > & types, 440 TypeDescriptionSearchDepth depth ) 441 { 442 return com::sun::star::uno::Reference< XTypeDescriptionEnumeration >( 443 TypeDescriptionEnumerationImpl::createInstance( getTDMgr(), 444 moduleName, 445 types, 446 depth, 447 _aBaseKeys ).get() ); 448 } 449 450 //__________________________________________________________________________________________________ 451 // global helper function 452 453 com::sun::star::uno::Reference< XTypeDescription > resolveTypedefs( 454 com::sun::star::uno::Reference< XTypeDescription > const & type) 455 { 456 com::sun::star::uno::Reference< XTypeDescription > resolved(type); 457 while (resolved->getTypeClass() == TypeClass_TYPEDEF) { 458 resolved = com::sun::star::uno::Reference< XIndirectTypeDescription >( 459 resolved, UNO_QUERY_THROW)->getReferencedType(); 460 } 461 return resolved; 462 } 463 464 com::sun::star::uno::Reference< XTypeDescription > createTypeDescription( 465 const Sequence< sal_Int8 > & rData, 466 const com::sun::star::uno::Reference< XHierarchicalNameAccess > & xNameAccess, 467 bool bReturnEmptyRefForUnknownType ) 468 { 469 typereg::Reader aReader( 470 rData.getConstArray(), rData.getLength(), false, TYPEREG_VERSION_1); 471 472 OUString aName( aReader.getTypeName().replace( '/', '.' ) ); 473 474 switch (aReader.getTypeClass()) 475 { 476 case RT_TYPE_INTERFACE: 477 { 478 sal_uInt16 n = aReader.getSuperTypeCount(); 479 com::sun::star::uno::Sequence< rtl::OUString > aBaseTypeNames(n); 480 {for (sal_uInt16 i = 0; i < n; ++i) { 481 aBaseTypeNames[i] = aReader.getSuperTypeName(i).replace( 482 '/', '.'); 483 }} 484 sal_uInt16 n2 = aReader.getReferenceCount(); 485 com::sun::star::uno::Sequence< rtl::OUString > 486 aOptionalBaseTypeNames(n2); 487 {for (sal_uInt16 i = 0; i < n2; ++i) { 488 OSL_ASSERT( 489 aReader.getReferenceSort(i) == RT_REF_SUPPORTS 490 && aReader.getReferenceFlags(i) == RT_ACCESS_OPTIONAL); 491 aOptionalBaseTypeNames[i] = aReader.getReferenceTypeName(i); 492 }} 493 return com::sun::star::uno::Reference< XTypeDescription >( 494 new InterfaceTypeDescriptionImpl( xNameAccess, 495 aName, 496 aBaseTypeNames, 497 aOptionalBaseTypeNames, 498 rData, 499 aReader.isPublished() ) ); 500 } 501 502 case RT_TYPE_MODULE: 503 { 504 com::sun::star::uno::Reference< 505 XTypeDescriptionEnumerationAccess > xTDEA( 506 xNameAccess, UNO_QUERY ); 507 508 OSL_ENSURE( xTDEA.is(), 509 "No XTypeDescriptionEnumerationAccess!" ); 510 511 return com::sun::star::uno::Reference< XTypeDescription >( 512 new ModuleTypeDescriptionImpl( xTDEA, aName ) ); 513 } 514 515 case RT_TYPE_STRUCT: 516 { 517 rtl::OUString superTypeName; 518 if (aReader.getSuperTypeCount() == 1) { 519 superTypeName = aReader.getSuperTypeName(0).replace( 520 '/', '.'); 521 } 522 return com::sun::star::uno::Reference< XTypeDescription >( 523 new stoc::registry_tdprovider::StructTypeDescription( 524 xNameAccess, aName, superTypeName, rData, 525 aReader.isPublished())); 526 } 527 528 case RT_TYPE_ENUM: 529 return com::sun::star::uno::Reference< XTypeDescription >( 530 new EnumTypeDescriptionImpl( xNameAccess, 531 aName, 532 getRTValueAsInt32( 533 aReader.getFieldValue( 0 ) ), 534 rData, aReader.isPublished() ) ); 535 536 case RT_TYPE_EXCEPTION: 537 { 538 rtl::OUString superTypeName; 539 if (aReader.getSuperTypeCount() == 1) { 540 superTypeName = aReader.getSuperTypeName(0).replace( 541 '/', '.'); 542 } 543 return com::sun::star::uno::Reference< XTypeDescription >( 544 new CompoundTypeDescriptionImpl( 545 xNameAccess, TypeClass_EXCEPTION, aName, superTypeName, 546 rData, aReader.isPublished())); 547 } 548 549 case RT_TYPE_TYPEDEF: 550 return com::sun::star::uno::Reference< XTypeDescription >( 551 new TypedefTypeDescriptionImpl( xNameAccess, 552 aName, 553 aReader.getSuperTypeName(0) 554 .replace( '/', '.' ), 555 aReader.isPublished() ) ); 556 case RT_TYPE_SERVICE: 557 return com::sun::star::uno::Reference< XTypeDescription >( 558 new ServiceTypeDescriptionImpl( 559 xNameAccess, aName, rData, aReader.isPublished() ) ); 560 561 case RT_TYPE_CONSTANTS: 562 return com::sun::star::uno::Reference< XTypeDescription >( 563 new ConstantsTypeDescriptionImpl( 564 aName, rData, aReader.isPublished() ) ); 565 566 case RT_TYPE_SINGLETON: 567 return com::sun::star::uno::Reference< XTypeDescription >( 568 new SingletonTypeDescriptionImpl( xNameAccess, 569 aName, 570 aReader.getSuperTypeName(0) 571 .replace( '/', '.' ), 572 aReader.isPublished() ) ); 573 case RT_TYPE_INVALID: 574 case RT_TYPE_OBJECT: // deprecated and not used 575 case RT_TYPE_UNION: // deprecated and not used 576 OSL_ENSURE( sal_False, "createTypeDescription - Unsupported Type!" ); 577 break; 578 579 default: 580 OSL_ENSURE( sal_False, "createTypeDescription - Unknown Type!" ); 581 break; 582 } 583 584 // Unknown type. 585 586 if ( bReturnEmptyRefForUnknownType ) 587 return com::sun::star::uno::Reference< XTypeDescription >(); 588 589 return com::sun::star::uno::Reference< XTypeDescription >( 590 new TypeDescriptionImpl( TypeClass_UNKNOWN, aName ) ); 591 } 592 593 } 594 595 namespace stoc_bootstrap 596 { 597 //================================================================================================== 598 com::sun::star::uno::Reference< XInterface > SAL_CALL ProviderImpl_create( 599 com::sun::star::uno::Reference< XComponentContext > const & xContext ) 600 { 601 return com::sun::star::uno::Reference< XInterface >( *new stoc_rdbtdp::ProviderImpl( xContext ) ); 602 } 603 } 604