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