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 "rtl/ustrbuf.hxx" 29 #include <cppuhelper/factory.hxx> 30 #ifndef _CPPUHELPER_IMPLBASE5_HXX_ 31 #include <cppuhelper/compbase5.hxx> 32 #endif 33 #include <cppuhelper/implbase1.hxx> 34 #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ 35 #include <cppuhelper/implementationentry.hxx> 36 #endif 37 #include "tdmgr_common.hxx" 38 #include "tdmgr_tdenumeration.hxx" 39 #include "lrucache.hxx" 40 41 #include <com/sun/star/lang/XServiceInfo.hpp> 42 #include <com/sun/star/lang/XSingleServiceFactory.hpp> 43 #include <com/sun/star/lang/XEventListener.hpp> 44 #include <com/sun/star/lang/XTypeProvider.hpp> 45 #include <com/sun/star/lang/XComponent.hpp> 46 #include <com/sun/star/lang/XInitialization.hpp> 47 #include <com/sun/star/container/XHierarchicalNameAccess.hpp> 48 #include <com/sun/star/container/XSet.hpp> 49 #include <com/sun/star/container/XContentEnumerationAccess.hpp> 50 #include <com/sun/star/reflection/XTypeDescription.hpp> 51 #include <com/sun/star/reflection/XArrayTypeDescription.hpp> 52 #include <com/sun/star/reflection/XIndirectTypeDescription.hpp> 53 #include <com/sun/star/reflection/XInterfaceTypeDescription.hpp> 54 #include "com/sun/star/reflection/XStructTypeDescription.hpp" 55 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> 56 #include <com/sun/star/registry/XRegistryKey.hpp> 57 #include "com/sun/star/uno/RuntimeException.hpp" 58 59 #include <algorithm> 60 #include <vector> 61 62 using namespace std; 63 using namespace cppu; 64 using namespace rtl; 65 using namespace osl; 66 using namespace com::sun::star; 67 using namespace com::sun::star::uno; 68 using namespace com::sun::star::lang; 69 using namespace com::sun::star::reflection; 70 using namespace com::sun::star::container; 71 using namespace com::sun::star::registry; 72 73 74 75 static const sal_Int32 CACHE_SIZE = 512; 76 77 #define SERVICENAME "com.sun.star.reflection.TypeDescriptionManager" 78 #define IMPLNAME "com.sun.star.comp.stoc.TypeDescriptionManager" 79 80 //-------------------------------------------------------------------------------------------------- 81 // exported via tdmgr_common.hxx 82 extern rtl_StandardModuleCount g_moduleCount; 83 84 namespace stoc_bootstrap 85 { 86 Sequence< OUString > SAL_CALL tdmgr_getSupportedServiceNames() 87 { 88 static Sequence < OUString > *pNames = 0; 89 if( ! pNames ) 90 { 91 MutexGuard guard( Mutex::getGlobalMutex() ); 92 if( !pNames ) 93 { 94 static Sequence< OUString > seqNames(1); 95 seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); 96 pNames = &seqNames; 97 } 98 } 99 return *pNames; 100 } 101 102 OUString SAL_CALL tdmgr_getImplementationName() 103 { 104 static OUString *pImplName = 0; 105 if( ! pImplName ) 106 { 107 MutexGuard guard( Mutex::getGlobalMutex() ); 108 if( ! pImplName ) 109 { 110 static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); 111 pImplName = &implName; 112 } 113 } 114 return *pImplName; 115 } 116 } 117 118 namespace stoc_tdmgr 119 { 120 typedef vector< Reference< XHierarchicalNameAccess > > ProviderVector; 121 122 class EnumerationImpl; 123 class ManagerImpl; 124 125 //================================================================================================== 126 class EventListenerImpl : public ImplHelper1< XEventListener > 127 { 128 ManagerImpl * _pMgr; 129 130 public: 131 EventListenerImpl( ManagerImpl * pMgr ) 132 : _pMgr( pMgr ) 133 { 134 ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt ); 135 } 136 virtual ~EventListenerImpl(); 137 138 // lifetime delegated to manager 139 virtual void SAL_CALL acquire() throw(); 140 virtual void SAL_CALL release() throw(); 141 142 // XEventListener 143 virtual void SAL_CALL disposing( const EventObject & rEvt ) throw(::com::sun::star::uno::RuntimeException); 144 }; 145 146 EventListenerImpl::~EventListenerImpl() 147 { 148 ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt ); 149 } 150 151 //================================================================================================== 152 class ManagerImpl 153 : public WeakComponentImplHelper5< XServiceInfo, 154 XSet, 155 XHierarchicalNameAccess, 156 XTypeDescriptionEnumerationAccess, 157 XInitialization > 158 { 159 friend class EnumerationImpl; 160 friend class EventListenerImpl; 161 162 Mutex _aComponentMutex; 163 Reference< XComponentContext > _xContext; 164 EventListenerImpl _aEventListener; 165 166 // elements 167 sal_Bool _bCaching; 168 LRU_CacheAnyByOUString _aElements; 169 // provider chain 170 ProviderVector _aProviders; 171 172 inline Any getSimpleType( const OUString & rName ); 173 174 Reference< XTypeDescription > getInstantiatedStruct(OUString const & name); 175 176 protected: 177 virtual void SAL_CALL disposing(); 178 179 public: 180 ManagerImpl( Reference< XComponentContext > const & xContext, sal_Int32 nCacheSize ); 181 virtual ~ManagerImpl(); 182 183 // XInitialization 184 virtual void SAL_CALL initialize( const Sequence< Any > & args ) throw (Exception, RuntimeException); 185 186 // XServiceInfo 187 virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); 188 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException); 189 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); 190 191 // XElementAccess 192 virtual Type SAL_CALL getElementType() throw(::com::sun::star::uno::RuntimeException); 193 virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException); 194 195 // XEnumerationAccess 196 virtual Reference< XEnumeration > SAL_CALL createEnumeration() throw(::com::sun::star::uno::RuntimeException); 197 198 // XSet 199 virtual sal_Bool SAL_CALL has( const Any & rElement ) throw(::com::sun::star::uno::RuntimeException); 200 virtual void SAL_CALL insert( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); 201 virtual void SAL_CALL remove( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); 202 203 // XHierarchicalNameAccess 204 virtual Any SAL_CALL getByHierarchicalName( const OUString & rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); 205 virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); 206 207 // XTypeDescriptionEnumerationAccess 208 virtual ::com::sun::star::uno::Reference< 209 ::com::sun::star::reflection::XTypeDescriptionEnumeration > SAL_CALL 210 createTypeDescriptionEnumeration( 211 const ::rtl::OUString& moduleName, 212 const ::com::sun::star::uno::Sequence< 213 ::com::sun::star::uno::TypeClass >& types, 214 ::com::sun::star::reflection::TypeDescriptionSearchDepth depth ) 215 throw ( ::com::sun::star::reflection::NoSuchTypeNameException, 216 ::com::sun::star::reflection::InvalidTypeNameException, 217 ::com::sun::star::uno::RuntimeException ); 218 }; 219 220 //================================================================================================== 221 class EnumerationImpl 222 : public WeakImplHelper1< XEnumeration > 223 { 224 ManagerImpl * _pMgr; 225 size_t _nPos; 226 227 public: 228 EnumerationImpl( ManagerImpl * pManager ); 229 virtual ~EnumerationImpl(); 230 231 // XEnumeration 232 virtual sal_Bool SAL_CALL hasMoreElements() throw(::com::sun::star::uno::RuntimeException); 233 virtual Any SAL_CALL nextElement() throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); 234 }; 235 236 //################################################################################################## 237 238 // lifetime delegated to manager 239 //__________________________________________________________________________________________________ 240 void EventListenerImpl::acquire() throw() 241 { 242 _pMgr->acquire(); 243 } 244 //__________________________________________________________________________________________________ 245 void EventListenerImpl::release() throw() 246 { 247 _pMgr->release(); 248 } 249 250 // XEventListener 251 //__________________________________________________________________________________________________ 252 void EventListenerImpl::disposing( const EventObject & rEvt ) 253 throw(::com::sun::star::uno::RuntimeException) 254 { 255 _pMgr->remove( makeAny( rEvt.Source ) ); 256 } 257 258 //################################################################################################## 259 260 //__________________________________________________________________________________________________ 261 EnumerationImpl::EnumerationImpl( ManagerImpl * pManager ) 262 : _pMgr( pManager ) 263 , _nPos( 0 ) 264 { 265 _pMgr->acquire(); 266 } 267 //__________________________________________________________________________________________________ 268 EnumerationImpl::~EnumerationImpl() 269 { 270 _pMgr->release(); 271 } 272 273 // XEnumeration 274 //__________________________________________________________________________________________________ 275 sal_Bool EnumerationImpl::hasMoreElements() 276 throw(::com::sun::star::uno::RuntimeException) 277 { 278 MutexGuard aGuard( _pMgr->_aComponentMutex ); 279 return (_nPos < _pMgr->_aProviders.size()); 280 } 281 //__________________________________________________________________________________________________ 282 Any EnumerationImpl::nextElement() 283 throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 284 { 285 MutexGuard aGuard( _pMgr->_aComponentMutex ); 286 if (_nPos >= _pMgr->_aProviders.size()) 287 { 288 throw NoSuchElementException( 289 OUString( RTL_CONSTASCII_USTRINGPARAM("there is no further element!") ), 290 (XWeak *)(OWeakObject *)this ); 291 } 292 return makeAny( _pMgr->_aProviders[_nPos++] ); 293 } 294 295 //################################################################################################## 296 297 //__________________________________________________________________________________________________ 298 ManagerImpl::ManagerImpl( 299 Reference< XComponentContext > const & xContext, sal_Int32 nCacheSize ) 300 : WeakComponentImplHelper5< 301 XServiceInfo, XSet, XHierarchicalNameAccess, 302 XTypeDescriptionEnumerationAccess, XInitialization >( _aComponentMutex ) 303 , _xContext( xContext ) 304 , _aEventListener( this ) 305 , _bCaching( sal_True ) 306 , _aElements( nCacheSize ) 307 { 308 ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt ); 309 } 310 //__________________________________________________________________________________________________ 311 ManagerImpl::~ManagerImpl() 312 { 313 OSL_ENSURE( _aProviders.size() == 0, "### still providers left!" ); 314 OSL_TRACE( "> TypeDescriptionManager shut down. <\n" ); 315 ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt ); 316 } 317 //__________________________________________________________________________________________________ 318 void ManagerImpl::disposing() 319 { 320 // called on disposing the tdmgr instance (supposedly from context) 321 _bCaching = sal_False; 322 _aElements.clear(); 323 _xContext.clear(); 324 _aProviders.clear(); 325 } 326 327 // XInitialization 328 //__________________________________________________________________________________________________ 329 void ManagerImpl::initialize( 330 const Sequence< Any > & args ) 331 throw (Exception, RuntimeException) 332 { 333 // additional providers 334 Any const * pProviders = args.getConstArray(); 335 for ( sal_Int32 nPos = 0; nPos < args.getLength(); ++nPos ) 336 { 337 Reference< XHierarchicalNameAccess > xHA( pProviders[ nPos ], UNO_QUERY ); 338 OSL_ENSURE( xHA.is(), "### no td provider!" ); 339 340 if (xHA.is()) 341 { 342 try 343 { 344 insert( makeAny( xHA ) ); 345 } 346 catch (IllegalArgumentException &) 347 { 348 } 349 catch (ElementExistException &) 350 { 351 } 352 } 353 } 354 } 355 356 // XServiceInfo 357 //__________________________________________________________________________________________________ 358 OUString ManagerImpl::getImplementationName() 359 throw(::com::sun::star::uno::RuntimeException) 360 { 361 return stoc_bootstrap::tdmgr_getImplementationName(); 362 } 363 //__________________________________________________________________________________________________ 364 sal_Bool ManagerImpl::supportsService( const OUString & rServiceName ) 365 throw(::com::sun::star::uno::RuntimeException) 366 { 367 const Sequence< OUString > & rSNL = getSupportedServiceNames(); 368 const OUString * pArray = rSNL.getConstArray(); 369 for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) 370 { 371 if (pArray[nPos] == rServiceName) 372 return sal_True; 373 } 374 return sal_False; 375 } 376 //__________________________________________________________________________________________________ 377 Sequence< OUString > ManagerImpl::getSupportedServiceNames() 378 throw(::com::sun::star::uno::RuntimeException) 379 { 380 return stoc_bootstrap::tdmgr_getSupportedServiceNames(); 381 } 382 383 // XElementAccess 384 //__________________________________________________________________________________________________ 385 Type ManagerImpl::getElementType() 386 throw(::com::sun::star::uno::RuntimeException) 387 { 388 return ::getCppuType( (const Reference< XHierarchicalNameAccess > *)0 ); 389 } 390 //__________________________________________________________________________________________________ 391 sal_Bool ManagerImpl::hasElements() 392 throw(::com::sun::star::uno::RuntimeException) 393 { 394 MutexGuard aGuard( _aComponentMutex ); 395 return (_aProviders.size() > 0); 396 } 397 398 // XEnumerationAccess 399 //__________________________________________________________________________________________________ 400 Reference< XEnumeration > ManagerImpl::createEnumeration() 401 throw(::com::sun::star::uno::RuntimeException) 402 { 403 return new EnumerationImpl( this ); 404 } 405 406 // XSet 407 //__________________________________________________________________________________________________ 408 sal_Bool SAL_CALL ManagerImpl::has( const Any & rElement ) 409 throw(::com::sun::star::uno::RuntimeException) 410 { 411 Reference< XHierarchicalNameAccess > xElem; 412 if (rElement >>= xElem) 413 { 414 MutexGuard aGuard( _aComponentMutex ); 415 return (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end()); 416 } 417 return sal_False; 418 } 419 420 //__________________________________________________________________________________________________ 421 void SAL_CALL ManagerImpl::insert( const Any & rElement ) 422 throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException) 423 { 424 Reference< XHierarchicalNameAccess > xElem; 425 if (! (rElement >>= xElem) || !xElem.is()) 426 { 427 throw IllegalArgumentException( 428 OUString( RTL_CONSTASCII_USTRINGPARAM("no valid type description provider given!") ), 429 (XWeak *)(OWeakObject *)this, 0 ); 430 } 431 432 MutexGuard aGuard( _aComponentMutex ); 433 if (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end()) 434 { 435 throw ElementExistException( 436 OUString( RTL_CONSTASCII_USTRINGPARAM("provider already inserted!") ), 437 (XWeak *)(OWeakObject *)this ); 438 } 439 440 if (! _aProviders.empty()) 441 { 442 // check whether all types are compatible, if possible: 443 Reference<reflection::XTypeDescriptionEnumerationAccess> xTDEnumAccess( 444 xElem, UNO_QUERY ); 445 OSL_ENSURE( xTDEnumAccess.is(), 446 "### providers ought to implement " 447 "reflection::XTypeDescriptionEnumerationAccess!" ); 448 if (xTDEnumAccess.is()) 449 { 450 try 451 { 452 TypeClass ar [] = { 453 TypeClass_ENUM, TypeClass_TYPEDEF, TypeClass_SEQUENCE, 454 TypeClass_STRUCT, TypeClass_EXCEPTION, 455 /* TypeClass_UNION, TypeClass_ARRAY not supported */ 456 TypeClass_INTERFACE, 457 TypeClass_SERVICE, 458 TypeClass_INTERFACE_METHOD, TypeClass_INTERFACE_ATTRIBUTE, 459 TypeClass_PROPERTY, TypeClass_CONSTANT, TypeClass_CONSTANTS, 460 TypeClass_SINGLETON 461 }; 462 Reference<reflection::XTypeDescriptionEnumeration> xTDEnum( 463 xTDEnumAccess->createTypeDescriptionEnumeration( 464 OUString() /* all modules */, 465 Sequence<TypeClass>( ar, ARLEN(ar) ), 466 reflection::TypeDescriptionSearchDepth_INFINITE ) ); 467 468 while (xTDEnum->hasMoreElements()) 469 { 470 Reference<reflection::XTypeDescription> xNewTD; 471 try 472 { 473 xNewTD = xTDEnum->nextTypeDescription(); 474 } 475 catch (container::NoSuchElementException & exc) 476 { 477 throw lang::IllegalArgumentException( 478 OUSTR("NoSuchElementException occured: ") + 479 exc.Message, static_cast<OWeakObject *>(this), 480 -1 /* unknown */ ); 481 } 482 483 try 484 { 485 OUString newName( xNewTD->getName() ); 486 Reference<reflection::XTypeDescription> xExistingTD( 487 getByHierarchicalName( newName ), UNO_QUERY ); 488 OSL_ASSERT( xExistingTD.is() ); 489 // existing, check whether compatible: 490 if (xExistingTD.is()) 491 { 492 try 493 { 494 check( xNewTD, xExistingTD ); 495 } 496 catch (IncompatibleTypeException & exc) 497 { 498 throw lang::IllegalArgumentException( 499 OUSTR("Rejecting types due to " 500 "incompatibility! ") + exc.m_cause, 501 static_cast<OWeakObject *>(this), 0 ); 502 } 503 } 504 } 505 catch (container::NoSuchElementException &) 506 { 507 // type not in: ok 508 } 509 } 510 } 511 catch (reflection::NoSuchTypeNameException & exc) 512 { 513 throw lang::IllegalArgumentException( 514 OUSTR("NoSuchTypeNameException occured: ") + exc.Message, 515 static_cast<OWeakObject *>(this), -1 /* unknown */ ); 516 } 517 catch (reflection::InvalidTypeNameException & exc) 518 { 519 throw lang::IllegalArgumentException( 520 OUSTR("InvalidTypeNameException occured: ") + exc.Message, 521 static_cast<OWeakObject *>(this), -1 /* unknown */ ); 522 } 523 } 524 } 525 526 _aProviders.push_back( xElem ); 527 Reference< XComponent > xComp( xElem, UNO_QUERY ); 528 if (xComp.is()) 529 xComp->addEventListener( &_aEventListener ); 530 } 531 //__________________________________________________________________________________________________ 532 void SAL_CALL ManagerImpl::remove( const Any & rElement ) 533 throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) 534 { 535 if (!rBHelper.bDisposed && !rBHelper.bInDispose) 536 { 537 Reference< XHierarchicalNameAccess > xElem; 538 if (! (rElement >>= xElem)) 539 { 540 throw IllegalArgumentException( 541 OUString( RTL_CONSTASCII_USTRINGPARAM("no type description provider given!") ), 542 (XWeak *)(OWeakObject *)this, 0 ); 543 } 544 545 MutexGuard aGuard( _aComponentMutex ); 546 ProviderVector::iterator iFind( find( _aProviders.begin(), _aProviders.end(), xElem ) ); 547 if (iFind == _aProviders.end()) 548 { 549 throw NoSuchElementException( 550 OUString( RTL_CONSTASCII_USTRINGPARAM("provider not found!") ), 551 (XWeak *)(OWeakObject *)this ); 552 } 553 _aProviders.erase( iFind ); 554 } 555 556 Reference< XComponent > xComp; 557 if (rElement >>= xComp) 558 xComp->removeEventListener( &_aEventListener ); 559 } 560 561 // XTypeDescriptionEnumerationAccess 562 //__________________________________________________________________________________________________ 563 // virtual 564 Reference< XTypeDescriptionEnumeration > SAL_CALL 565 ManagerImpl::createTypeDescriptionEnumeration( 566 const OUString & moduleName, 567 const Sequence< TypeClass > & types, 568 TypeDescriptionSearchDepth depth ) 569 throw ( NoSuchTypeNameException, 570 InvalidTypeNameException, 571 RuntimeException ) 572 { 573 MutexGuard aGuard( _aComponentMutex ); 574 575 TDEnumerationAccessStack aStack; 576 ProviderVector::const_iterator it = _aProviders.begin(); 577 const ProviderVector::const_iterator end = _aProviders.end(); 578 while ( it != end ) 579 { 580 Reference< XTypeDescriptionEnumerationAccess >xEnumAccess( 581 (*it), UNO_QUERY ); 582 OSL_ENSURE( xEnumAccess.is(), 583 "### no XTypeDescriptionEnumerationAccess!" ); 584 if ( xEnumAccess.is() ) 585 aStack.push( xEnumAccess ); 586 587 it++; 588 } 589 590 return Reference< XTypeDescriptionEnumeration >( 591 new TypeDescriptionEnumerationImpl( moduleName, 592 types, 593 depth, 594 aStack ) ); 595 } 596 597 598 //################################################################################################## 599 //################################################################################################## 600 //################################################################################################## 601 602 603 //================================================================================================== 604 class SimpleTypeDescriptionImpl 605 : public WeakImplHelper1< XTypeDescription > 606 { 607 TypeClass _eTC; 608 OUString _aName; 609 610 public: 611 SimpleTypeDescriptionImpl( TypeClass eTC, const OUString & rName ) 612 : _eTC( eTC ) 613 , _aName( rName ) 614 {} 615 616 // XTypeDescription 617 virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); 618 virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); 619 }; 620 621 // XTypeDescription 622 //__________________________________________________________________________________________________ 623 TypeClass SimpleTypeDescriptionImpl::getTypeClass() 624 throw(::com::sun::star::uno::RuntimeException) 625 { 626 return _eTC; 627 } 628 //__________________________________________________________________________________________________ 629 OUString SimpleTypeDescriptionImpl::getName() 630 throw(::com::sun::star::uno::RuntimeException) 631 { 632 return _aName; 633 } 634 635 //================================================================================================== 636 class SequenceTypeDescriptionImpl 637 : public WeakImplHelper1< XIndirectTypeDescription > 638 { 639 Reference< XTypeDescription > _xElementTD; 640 641 public: 642 SequenceTypeDescriptionImpl( const Reference< XTypeDescription > & xElementTD ) 643 : _xElementTD( xElementTD ) 644 {} 645 646 // XTypeDescription 647 virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); 648 virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); 649 650 // XIndirectTypeDescription 651 virtual Reference< XTypeDescription > SAL_CALL getReferencedType() throw(::com::sun::star::uno::RuntimeException); 652 }; 653 654 // XTypeDescription 655 //__________________________________________________________________________________________________ 656 TypeClass SequenceTypeDescriptionImpl::getTypeClass() 657 throw(::com::sun::star::uno::RuntimeException) 658 { 659 return TypeClass_SEQUENCE; 660 } 661 //__________________________________________________________________________________________________ 662 OUString SequenceTypeDescriptionImpl::getName() 663 throw(::com::sun::star::uno::RuntimeException) 664 { 665 return (OUString( RTL_CONSTASCII_USTRINGPARAM("[]") ) + _xElementTD->getName()); 666 } 667 668 // XIndirectTypeDescription 669 //__________________________________________________________________________________________________ 670 Reference< XTypeDescription > SequenceTypeDescriptionImpl::getReferencedType() 671 throw(::com::sun::star::uno::RuntimeException) 672 { 673 return _xElementTD; 674 } 675 676 //================================================================================================== 677 class ArrayTypeDescriptionImpl 678 : public WeakImplHelper1< XArrayTypeDescription > 679 { 680 Reference< XTypeDescription > _xElementTD; 681 Mutex _aDimensionMutex; 682 sal_Int32 _nDimensions; 683 Sequence< sal_Int32 > _seqDimensions; 684 OUString _sDimensions; 685 686 void initDimensions(const OUString& rSDimensions); 687 public: 688 ArrayTypeDescriptionImpl( const Reference< XTypeDescription > & xElementTD, 689 sal_Int32 nDimensions, const OUString& rSDimensions ) 690 : _xElementTD( xElementTD ) 691 , _nDimensions( nDimensions ) 692 , _seqDimensions( Sequence< sal_Int32 >(nDimensions) ) 693 , _sDimensions( rSDimensions ) 694 { 695 initDimensions( rSDimensions ); 696 } 697 virtual ~ArrayTypeDescriptionImpl() {} 698 699 // XTypeDescription 700 virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); 701 virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); 702 703 // XArrayTypeDescription 704 virtual Reference< XTypeDescription > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException); 705 virtual sal_Int32 SAL_CALL getNumberOfDimensions() throw(::com::sun::star::uno::RuntimeException); 706 virtual Sequence< sal_Int32 > SAL_CALL getDimensions() throw(::com::sun::star::uno::RuntimeException); 707 }; 708 //__________________________________________________________________________________________________ 709 static sal_Int32 unicodeToInteger( sal_Int8 base, const sal_Unicode *s ) 710 { 711 sal_Int32 r = 0; 712 sal_Int32 negative = 0; 713 714 if (*s == '-') 715 { 716 negative = 1; 717 s++; 718 } 719 if (base == 8 && *s == '0') 720 s++; 721 else if (base == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) 722 s += 2; 723 724 for (; *s; s++) 725 { 726 if (*s <= '9' && *s >= '0') 727 r = (r * base) + (*s - '0'); 728 else if (base > 10 && *s <= 'f' && *s >= 'a') 729 r = (r * base) + (*s - 'a' + 10); 730 else if (base > 10 && *s <= 'F' && *s >= 'A') 731 r = (r * base) + (*s - 'A' + 10); 732 else 733 break; 734 } 735 if (negative) r *= -1; 736 return r; 737 } 738 //__________________________________________________________________________________________________ 739 void ArrayTypeDescriptionImpl::initDimensions(const OUString& rSDimensions) 740 { 741 MutexGuard aGuard( _aDimensionMutex ); 742 743 sal_Int32 * pDimensions = _seqDimensions.getArray(); 744 OUString tmp(rSDimensions); 745 sal_Unicode* p = (sal_Unicode*)tmp.getStr()+1; 746 sal_Unicode* pOffset = p; 747 sal_Int32 len = tmp.getLength() - 1 ; 748 sal_Int32 i = 0; 749 750 while ( len > 0) 751 { 752 pOffset++; 753 if (*pOffset == ']') 754 { 755 *pOffset = '\0'; 756 pOffset += 2; 757 len -= 3; 758 pDimensions[i++] = unicodeToInteger(10, p); 759 p = pOffset; 760 } else 761 len--; 762 } 763 } 764 765 // XTypeDescription 766 //__________________________________________________________________________________________________ 767 TypeClass ArrayTypeDescriptionImpl::getTypeClass() 768 throw(::com::sun::star::uno::RuntimeException) 769 { 770 return TypeClass_ARRAY; 771 } 772 //__________________________________________________________________________________________________ 773 OUString ArrayTypeDescriptionImpl::getName() 774 throw(::com::sun::star::uno::RuntimeException) 775 { 776 return (_xElementTD->getName() + _sDimensions); 777 } 778 779 // XArrayTypeDescription 780 //__________________________________________________________________________________________________ 781 Reference< XTypeDescription > ArrayTypeDescriptionImpl::getType() 782 throw(::com::sun::star::uno::RuntimeException) 783 { 784 return _xElementTD; 785 } 786 787 //__________________________________________________________________________________________________ 788 sal_Int32 ArrayTypeDescriptionImpl::getNumberOfDimensions() 789 throw(::com::sun::star::uno::RuntimeException) 790 { 791 return _nDimensions; 792 } 793 794 //__________________________________________________________________________________________________ 795 Sequence< sal_Int32 > ArrayTypeDescriptionImpl::getDimensions() 796 throw(::com::sun::star::uno::RuntimeException) 797 { 798 return _seqDimensions; 799 } 800 801 //################################################################################################## 802 //################################################################################################## 803 //################################################################################################## 804 805 806 //__________________________________________________________________________________________________ 807 inline Any ManagerImpl::getSimpleType( const OUString & rName ) 808 { 809 Any aRet; 810 811 if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("string") )) 812 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_STRING, rName ) ); 813 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("long") )) 814 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_LONG, rName ) ); 815 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned long") )) 816 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_LONG, rName ) ); 817 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("boolean") )) 818 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_BOOLEAN, rName ) ); 819 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("char") )) 820 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_CHAR, rName ) ); 821 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("byte") )) 822 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_BYTE, rName ) ); 823 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("short") )) 824 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_SHORT, rName ) ); 825 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned short") )) 826 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_SHORT, rName ) ); 827 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("hyper") )) 828 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_HYPER, rName ) ); 829 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned hyper") )) 830 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_HYPER, rName ) ); 831 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("float") )) 832 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_FLOAT, rName ) ); 833 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("double") )) 834 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_DOUBLE, rName ) ); 835 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("any") )) 836 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_ANY, rName ) ); 837 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("void") )) 838 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_VOID, rName ) ); 839 else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("type") )) 840 aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_TYPE, rName ) ); 841 842 return aRet; 843 } 844 845 namespace { 846 847 Reference< XTypeDescription > resolveTypedefs( 848 Reference< XTypeDescription > const & type) 849 { 850 Reference< XTypeDescription > resolved(type); 851 while (resolved->getTypeClass() == TypeClass_TYPEDEF) { 852 resolved = Reference< XIndirectTypeDescription >( 853 type, UNO_QUERY_THROW)->getReferencedType(); 854 } 855 return resolved; 856 } 857 858 bool isNonVoidNonExceptionType(Reference< XTypeDescription > const & type) { 859 switch (type->getTypeClass()) { 860 case TypeClass_BOOLEAN: 861 case TypeClass_BYTE: 862 case TypeClass_SHORT: 863 case TypeClass_UNSIGNED_SHORT: 864 case TypeClass_LONG: 865 case TypeClass_UNSIGNED_LONG: 866 case TypeClass_HYPER: 867 case TypeClass_UNSIGNED_HYPER: 868 case TypeClass_FLOAT: 869 case TypeClass_DOUBLE: 870 case TypeClass_CHAR: 871 case TypeClass_STRING: 872 case TypeClass_TYPE: 873 case TypeClass_ANY: 874 case TypeClass_SEQUENCE: 875 case TypeClass_ENUM: 876 case TypeClass_STRUCT: 877 case TypeClass_INTERFACE: 878 return true; 879 880 default: 881 return false; 882 } 883 } 884 885 class InstantiatedStruct: public WeakImplHelper1< XStructTypeDescription > { 886 public: 887 InstantiatedStruct( 888 Reference< XStructTypeDescription > const & structType, 889 std::vector< Reference< XTypeDescription > > const & arguments); 890 891 virtual TypeClass SAL_CALL getTypeClass() throw (RuntimeException) 892 { return TypeClass_STRUCT; } 893 894 virtual OUString SAL_CALL getName() throw (RuntimeException); 895 896 virtual Reference< XTypeDescription > SAL_CALL getBaseType() 897 throw (RuntimeException) 898 { return m_struct->getBaseType(); } 899 900 virtual Sequence< Reference< XTypeDescription > > SAL_CALL getMemberTypes() 901 throw (RuntimeException); 902 903 virtual Sequence< OUString > SAL_CALL getMemberNames() 904 throw (RuntimeException) 905 { return m_struct->getMemberNames(); } 906 907 virtual Sequence< OUString > SAL_CALL getTypeParameters() 908 throw (RuntimeException) 909 { return Sequence< OUString >(); } 910 911 virtual Sequence< Reference< XTypeDescription > > SAL_CALL 912 getTypeArguments() throw (RuntimeException) 913 { return m_arguments; } 914 915 private: 916 Reference< XStructTypeDescription > m_struct; 917 Sequence< Reference< XTypeDescription > > m_arguments; 918 }; 919 920 InstantiatedStruct::InstantiatedStruct( 921 Reference< XStructTypeDescription > const & structType, 922 std::vector< Reference< XTypeDescription > > const & arguments): 923 m_struct(structType), 924 m_arguments(static_cast< sal_Int32 >(arguments.size())) 925 { 926 for (std::vector< Reference< XTypeDescription > >::size_type i = 0; 927 i < arguments.size(); ++i) 928 { 929 m_arguments[static_cast< sal_Int32 >(i)] = arguments[i]; 930 } 931 } 932 933 OUString InstantiatedStruct::getName() throw (RuntimeException) { 934 OUStringBuffer buf(m_struct->getName()); 935 buf.append(static_cast< sal_Unicode >('<')); 936 for (sal_Int32 i = 0; i < m_arguments.getLength(); ++i) { 937 if (i != 0) { 938 buf.append(static_cast< sal_Unicode >(',')); 939 } 940 buf.append(m_arguments[i]->getName()); 941 } 942 buf.append(static_cast< sal_Unicode >('>')); 943 return buf.makeStringAndClear(); 944 } 945 946 Sequence< Reference< XTypeDescription > > InstantiatedStruct::getMemberTypes() 947 throw (RuntimeException) 948 { 949 Sequence< Reference< XTypeDescription > > types(m_struct->getMemberTypes()); 950 for (sal_Int32 i = 0; i < types.getLength(); ++i) { 951 if (types[i]->getTypeClass() == TypeClass_UNKNOWN) { 952 Sequence< OUString > parameters(m_struct->getTypeParameters()); 953 OSL_ASSERT(parameters.getLength() == m_arguments.getLength()); 954 for (sal_Int32 j = 0; j < parameters.getLength(); ++j) { 955 if (parameters[j] == types[i]->getName()) { 956 types[i] = m_arguments[j]; 957 break; 958 } 959 } 960 } 961 } 962 return types; 963 } 964 965 } 966 967 Reference< XTypeDescription > ManagerImpl::getInstantiatedStruct( 968 OUString const & name) 969 { 970 sal_Int32 i = name.indexOf('<'); 971 OSL_ASSERT(i >= 0); 972 Reference< XStructTypeDescription > structType( 973 getByHierarchicalName(name.copy(0, i)), UNO_QUERY); 974 std::vector< Reference< XTypeDescription > > args; 975 bool good = structType.is(); 976 if (good) { 977 do { 978 ++i; // skip '<' or ',' 979 sal_Int32 j = i; 980 for (sal_Int32 level = 0; j != name.getLength(); ++j) { 981 sal_Unicode c = name[j]; 982 if (c == ',') { 983 if (level == 0) { 984 break; 985 } 986 } else if (c == '<') { 987 ++level; 988 } else if (c == '>') { 989 if (level == 0) { 990 break; 991 } 992 --level; 993 } 994 } 995 if (j != name.getLength()) { 996 Reference< XTypeDescription > type( 997 getByHierarchicalName(name.copy(i, j - i)), UNO_QUERY); 998 if (isNonVoidNonExceptionType(resolveTypedefs(type))) { 999 args.push_back(type); 1000 } else { 1001 good = false; 1002 break; 1003 } 1004 } 1005 i = j; 1006 } while (i != name.getLength() && name[i] != '>'); 1007 good = good && i == name.getLength() - 1 1008 && name[i] == '>' && !args.empty(); 1009 } 1010 // args.size() cannot exceed SAL_MAX_INT32, as each argument consumes at 1011 // least one position within an rtl::OUString (which is no longer than 1012 // SAL_MAX_INT32): 1013 if (!good 1014 || (args.size() 1015 != sal::static_int_cast< sal_uInt32 >( 1016 structType->getTypeParameters().getLength()))) 1017 { 1018 throw NoSuchElementException(name, static_cast< OWeakObject * >(this)); 1019 } 1020 return new InstantiatedStruct(structType, args); 1021 } 1022 1023 // XHierarchicalNameAccess 1024 //__________________________________________________________________________________________________ 1025 Any ManagerImpl::getByHierarchicalName( const OUString & rName ) 1026 throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) 1027 { 1028 Any aRet; 1029 if (_bCaching) 1030 aRet = _aElements.getValue( rName ); 1031 if (rName.getLength() && !aRet.hasValue()) 1032 { 1033 sal_Int32 nIndex; 1034 if (rName[0] == '[') // test for sequence 1035 { 1036 Reference< XTypeDescription > xElemType( 1037 getByHierarchicalName( rName.copy( 2 ) ), 1038 UNO_QUERY_THROW ); 1039 aRet <<= Reference< XTypeDescription >( 1040 new SequenceTypeDescriptionImpl( xElemType ) ); 1041 } 1042 else if (rName[rName.getLength()-1] == ']') // test for array 1043 { 1044 sal_Int32 nIndex2 = 0, nTokens = 0; 1045 do { rName.getToken( 0, '[', nIndex2 ); nTokens++; } while( nIndex2 != -1 ); 1046 sal_Int32 nDims = nTokens - 1; 1047 sal_Int32 dimOffset = rName.indexOf('['); 1048 Reference< XTypeDescription > xElemType( 1049 getByHierarchicalName( rName.copy( 0, dimOffset ) ), 1050 UNO_QUERY_THROW ); 1051 aRet <<= Reference< XTypeDescription >( 1052 new ArrayTypeDescriptionImpl( 1053 xElemType, nDims, rName.copy(dimOffset) ) ); 1054 } 1055 // test for interface member names: 1056 else if ((nIndex = rName.indexOf( ':' )) >= 0) 1057 { 1058 Reference< XInterfaceTypeDescription > xIfaceTD( 1059 getByHierarchicalName( rName.copy( 0, nIndex ) ), 1060 UNO_QUERY_THROW ); 1061 const Sequence< Reference< XInterfaceMemberTypeDescription > > & 1062 rMembers = xIfaceTD->getMembers(); 1063 const Reference< XInterfaceMemberTypeDescription > * pMembers = 1064 rMembers.getConstArray(); 1065 1066 for ( sal_Int32 nPos = rMembers.getLength(); nPos--; ) 1067 { 1068 if (rName == pMembers[nPos]->getName()) 1069 { 1070 aRet <<= Reference< XTypeDescription >( 1071 pMembers[nPos], UNO_QUERY_THROW ); 1072 break; 1073 } 1074 } 1075 if (! aRet.hasValue()) 1076 { 1077 // member not found: 1078 throw NoSuchElementException( 1079 rName, static_cast< OWeakObject * >(this) ); 1080 } 1081 } 1082 // test for instantiated polymorphic struct types: 1083 else if (rName.indexOf('<') >= 0) 1084 { 1085 aRet <<= getInstantiatedStruct(rName); 1086 } 1087 else if (rName.indexOf( '.' ) < 0) // test for simple/ build in types 1088 { 1089 aRet = getSimpleType( rName ); 1090 } 1091 1092 if (! aRet.hasValue()) 1093 { 1094 // last, try callback chain 1095 for ( ProviderVector::const_iterator iPos( _aProviders.begin() ); 1096 iPos != _aProviders.end(); ++iPos ) 1097 { 1098 try 1099 { 1100 if ((aRet = (*iPos)->getByHierarchicalName( 1101 rName )).hasValue()) 1102 { 1103 break; 1104 } 1105 } 1106 catch (NoSuchElementException &) 1107 { 1108 } 1109 } 1110 } 1111 1112 // update cache 1113 if (_bCaching && aRet.hasValue()) 1114 _aElements.setValue( rName, aRet ); 1115 } 1116 1117 if (! aRet.hasValue()) 1118 { 1119 throw NoSuchElementException( 1120 rName, static_cast< OWeakObject * >(this) ); 1121 } 1122 return aRet; 1123 } 1124 //__________________________________________________________________________________________________ 1125 sal_Bool ManagerImpl::hasByHierarchicalName( const OUString & rName ) 1126 throw(::com::sun::star::uno::RuntimeException) 1127 { 1128 try 1129 { 1130 return getByHierarchicalName( rName ).hasValue(); 1131 } 1132 catch (NoSuchElementException &) 1133 { 1134 } 1135 return sal_False; 1136 } 1137 } 1138 1139 namespace stoc_bootstrap 1140 { 1141 //================================================================================================== 1142 Reference< XInterface > SAL_CALL ManagerImpl_create( 1143 Reference< XComponentContext > const & xContext ) 1144 SAL_THROW( (::com::sun::star::uno::Exception) ) 1145 { 1146 sal_Int32 nCacheSize = CACHE_SIZE; 1147 if (xContext.is()) { 1148 xContext->getValueByName( 1149 OUString( 1150 RTL_CONSTASCII_USTRINGPARAM( 1151 "/implementations/" IMPLNAME "/CacheSize"))) >>= 1152 nCacheSize; 1153 } 1154 1155 return Reference< XInterface >( *new stoc_tdmgr::ManagerImpl( xContext, nCacheSize ) ); 1156 } 1157 1158 } 1159 1160