/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_stoc.hxx" #include #include #include "rtl/ustrbuf.hxx" #include #ifndef _CPPUHELPER_IMPLBASE5_HXX_ #include #endif #include #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ #include #endif #include "tdmgr_common.hxx" #include "tdmgr_tdenumeration.hxx" #include "lrucache.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "com/sun/star/reflection/XStructTypeDescription.hpp" #include #include #include "com/sun/star/uno/RuntimeException.hpp" #include #include using namespace std; using namespace cppu; using namespace rtl; using namespace osl; using namespace com::sun::star; using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::reflection; using namespace com::sun::star::container; using namespace com::sun::star::registry; static const sal_Int32 CACHE_SIZE = 512; #define SERVICENAME "com.sun.star.reflection.TypeDescriptionManager" #define IMPLNAME "com.sun.star.comp.stoc.TypeDescriptionManager" //-------------------------------------------------------------------------------------------------- // exported via tdmgr_common.hxx extern rtl_StandardModuleCount g_moduleCount; namespace stoc_bootstrap { Sequence< OUString > SAL_CALL tdmgr_getSupportedServiceNames() { static Sequence < OUString > *pNames = 0; if( ! pNames ) { MutexGuard guard( Mutex::getGlobalMutex() ); if( !pNames ) { static Sequence< OUString > seqNames(1); seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); pNames = &seqNames; } } return *pNames; } OUString SAL_CALL tdmgr_getImplementationName() { static OUString *pImplName = 0; if( ! pImplName ) { MutexGuard guard( Mutex::getGlobalMutex() ); if( ! pImplName ) { static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); pImplName = &implName; } } return *pImplName; } } namespace stoc_tdmgr { typedef vector< Reference< XHierarchicalNameAccess > > ProviderVector; class EnumerationImpl; class ManagerImpl; //================================================================================================== class EventListenerImpl : public ImplHelper1< XEventListener > { ManagerImpl * _pMgr; public: EventListenerImpl( ManagerImpl * pMgr ) : _pMgr( pMgr ) { ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt ); } virtual ~EventListenerImpl(); // lifetime delegated to manager virtual void SAL_CALL acquire() throw(); virtual void SAL_CALL release() throw(); // XEventListener virtual void SAL_CALL disposing( const EventObject & rEvt ) throw(::com::sun::star::uno::RuntimeException); }; EventListenerImpl::~EventListenerImpl() { ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt ); } //================================================================================================== class ManagerImpl : public WeakComponentImplHelper5< XServiceInfo, XSet, XHierarchicalNameAccess, XTypeDescriptionEnumerationAccess, XInitialization > { friend class EnumerationImpl; friend class EventListenerImpl; Mutex _aComponentMutex; Reference< XComponentContext > _xContext; EventListenerImpl _aEventListener; // elements sal_Bool _bCaching; LRU_CacheAnyByOUString _aElements; // provider chain ProviderVector _aProviders; inline Any getSimpleType( const OUString & rName ); Reference< XTypeDescription > getInstantiatedStruct(OUString const & name); protected: virtual void SAL_CALL disposing(); public: ManagerImpl( Reference< XComponentContext > const & xContext, sal_Int32 nCacheSize ); virtual ~ManagerImpl(); // XInitialization virtual void SAL_CALL initialize( const Sequence< Any > & args ) throw (Exception, RuntimeException); // XServiceInfo virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException); virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); // XElementAccess virtual Type SAL_CALL getElementType() throw(::com::sun::star::uno::RuntimeException); virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException); // XEnumerationAccess virtual Reference< XEnumeration > SAL_CALL createEnumeration() throw(::com::sun::star::uno::RuntimeException); // XSet virtual sal_Bool SAL_CALL has( const Any & rElement ) throw(::com::sun::star::uno::RuntimeException); virtual void SAL_CALL insert( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); virtual void SAL_CALL remove( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); // XHierarchicalNameAccess virtual Any SAL_CALL getByHierarchicalName( const OUString & rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); // XTypeDescriptionEnumerationAccess virtual ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XTypeDescriptionEnumeration > SAL_CALL createTypeDescriptionEnumeration( const ::rtl::OUString& moduleName, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::TypeClass >& types, ::com::sun::star::reflection::TypeDescriptionSearchDepth depth ) throw ( ::com::sun::star::reflection::NoSuchTypeNameException, ::com::sun::star::reflection::InvalidTypeNameException, ::com::sun::star::uno::RuntimeException ); }; //================================================================================================== class EnumerationImpl : public WeakImplHelper1< XEnumeration > { ManagerImpl * _pMgr; size_t _nPos; public: EnumerationImpl( ManagerImpl * pManager ); virtual ~EnumerationImpl(); // XEnumeration virtual sal_Bool SAL_CALL hasMoreElements() throw(::com::sun::star::uno::RuntimeException); virtual Any SAL_CALL nextElement() throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); }; //################################################################################################## // lifetime delegated to manager //__________________________________________________________________________________________________ void EventListenerImpl::acquire() throw() { _pMgr->acquire(); } //__________________________________________________________________________________________________ void EventListenerImpl::release() throw() { _pMgr->release(); } // XEventListener //__________________________________________________________________________________________________ void EventListenerImpl::disposing( const EventObject & rEvt ) throw(::com::sun::star::uno::RuntimeException) { _pMgr->remove( makeAny( rEvt.Source ) ); } //################################################################################################## //__________________________________________________________________________________________________ EnumerationImpl::EnumerationImpl( ManagerImpl * pManager ) : _pMgr( pManager ) , _nPos( 0 ) { _pMgr->acquire(); } //__________________________________________________________________________________________________ EnumerationImpl::~EnumerationImpl() { _pMgr->release(); } // XEnumeration //__________________________________________________________________________________________________ sal_Bool EnumerationImpl::hasMoreElements() throw(::com::sun::star::uno::RuntimeException) { MutexGuard aGuard( _pMgr->_aComponentMutex ); return (_nPos < _pMgr->_aProviders.size()); } //__________________________________________________________________________________________________ Any EnumerationImpl::nextElement() throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) { MutexGuard aGuard( _pMgr->_aComponentMutex ); if (_nPos >= _pMgr->_aProviders.size()) { throw NoSuchElementException( OUString( RTL_CONSTASCII_USTRINGPARAM("there is no further element!") ), (XWeak *)(OWeakObject *)this ); } return makeAny( _pMgr->_aProviders[_nPos++] ); } //################################################################################################## //__________________________________________________________________________________________________ ManagerImpl::ManagerImpl( Reference< XComponentContext > const & xContext, sal_Int32 nCacheSize ) : WeakComponentImplHelper5< XServiceInfo, XSet, XHierarchicalNameAccess, XTypeDescriptionEnumerationAccess, XInitialization >( _aComponentMutex ) , _xContext( xContext ) , _aEventListener( this ) , _bCaching( sal_True ) , _aElements( nCacheSize ) { ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt ); } //__________________________________________________________________________________________________ ManagerImpl::~ManagerImpl() { OSL_ENSURE( _aProviders.size() == 0, "### still providers left!" ); OSL_TRACE( "> TypeDescriptionManager shut down. <\n" ); ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt ); } //__________________________________________________________________________________________________ void ManagerImpl::disposing() { // called on disposing the tdmgr instance (supposedly from context) _bCaching = sal_False; _aElements.clear(); _xContext.clear(); _aProviders.clear(); } // XInitialization //__________________________________________________________________________________________________ void ManagerImpl::initialize( const Sequence< Any > & args ) throw (Exception, RuntimeException) { // additional providers Any const * pProviders = args.getConstArray(); for ( sal_Int32 nPos = 0; nPos < args.getLength(); ++nPos ) { Reference< XHierarchicalNameAccess > xHA( pProviders[ nPos ], UNO_QUERY ); OSL_ENSURE( xHA.is(), "### no td provider!" ); if (xHA.is()) { try { insert( makeAny( xHA ) ); } catch (IllegalArgumentException &) { } catch (ElementExistException &) { } } } } // XServiceInfo //__________________________________________________________________________________________________ OUString ManagerImpl::getImplementationName() throw(::com::sun::star::uno::RuntimeException) { return stoc_bootstrap::tdmgr_getImplementationName(); } //__________________________________________________________________________________________________ sal_Bool ManagerImpl::supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException) { const Sequence< OUString > & rSNL = getSupportedServiceNames(); const OUString * pArray = rSNL.getConstArray(); for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) { if (pArray[nPos] == rServiceName) return sal_True; } return sal_False; } //__________________________________________________________________________________________________ Sequence< OUString > ManagerImpl::getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException) { return stoc_bootstrap::tdmgr_getSupportedServiceNames(); } // XElementAccess //__________________________________________________________________________________________________ Type ManagerImpl::getElementType() throw(::com::sun::star::uno::RuntimeException) { return ::getCppuType( (const Reference< XHierarchicalNameAccess > *)0 ); } //__________________________________________________________________________________________________ sal_Bool ManagerImpl::hasElements() throw(::com::sun::star::uno::RuntimeException) { MutexGuard aGuard( _aComponentMutex ); return (_aProviders.size() > 0); } // XEnumerationAccess //__________________________________________________________________________________________________ Reference< XEnumeration > ManagerImpl::createEnumeration() throw(::com::sun::star::uno::RuntimeException) { return new EnumerationImpl( this ); } // XSet //__________________________________________________________________________________________________ sal_Bool SAL_CALL ManagerImpl::has( const Any & rElement ) throw(::com::sun::star::uno::RuntimeException) { Reference< XHierarchicalNameAccess > xElem; if (rElement >>= xElem) { MutexGuard aGuard( _aComponentMutex ); return (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end()); } return sal_False; } //__________________________________________________________________________________________________ void SAL_CALL ManagerImpl::insert( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException) { Reference< XHierarchicalNameAccess > xElem; if (! (rElement >>= xElem) || !xElem.is()) { throw IllegalArgumentException( OUString( RTL_CONSTASCII_USTRINGPARAM("no valid type description provider given!") ), (XWeak *)(OWeakObject *)this, 0 ); } MutexGuard aGuard( _aComponentMutex ); if (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end()) { throw ElementExistException( OUString( RTL_CONSTASCII_USTRINGPARAM("provider already inserted!") ), (XWeak *)(OWeakObject *)this ); } if (! _aProviders.empty()) { // check whether all types are compatible, if possible: Reference xTDEnumAccess( xElem, UNO_QUERY ); OSL_ENSURE( xTDEnumAccess.is(), "### providers ought to implement " "reflection::XTypeDescriptionEnumerationAccess!" ); if (xTDEnumAccess.is()) { try { TypeClass ar [] = { TypeClass_ENUM, TypeClass_TYPEDEF, TypeClass_SEQUENCE, TypeClass_STRUCT, TypeClass_EXCEPTION, /* TypeClass_UNION, TypeClass_ARRAY not supported */ TypeClass_INTERFACE, TypeClass_SERVICE, TypeClass_INTERFACE_METHOD, TypeClass_INTERFACE_ATTRIBUTE, TypeClass_PROPERTY, TypeClass_CONSTANT, TypeClass_CONSTANTS, TypeClass_SINGLETON }; Reference xTDEnum( xTDEnumAccess->createTypeDescriptionEnumeration( OUString() /* all modules */, Sequence( ar, ARLEN(ar) ), reflection::TypeDescriptionSearchDepth_INFINITE ) ); while (xTDEnum->hasMoreElements()) { Reference xNewTD; try { xNewTD = xTDEnum->nextTypeDescription(); } catch (container::NoSuchElementException & exc) { throw lang::IllegalArgumentException( OUSTR("NoSuchElementException occured: ") + exc.Message, static_cast(this), -1 /* unknown */ ); } try { OUString newName( xNewTD->getName() ); Reference xExistingTD( getByHierarchicalName( newName ), UNO_QUERY ); OSL_ASSERT( xExistingTD.is() ); // existing, check whether compatible: if (xExistingTD.is()) { try { check( xNewTD, xExistingTD ); } catch (IncompatibleTypeException & exc) { throw lang::IllegalArgumentException( OUSTR("Rejecting types due to " "incompatibility! ") + exc.m_cause, static_cast(this), 0 ); } } } catch (container::NoSuchElementException &) { // type not in: ok } } } catch (reflection::NoSuchTypeNameException & exc) { throw lang::IllegalArgumentException( OUSTR("NoSuchTypeNameException occured: ") + exc.Message, static_cast(this), -1 /* unknown */ ); } catch (reflection::InvalidTypeNameException & exc) { throw lang::IllegalArgumentException( OUSTR("InvalidTypeNameException occured: ") + exc.Message, static_cast(this), -1 /* unknown */ ); } } } _aProviders.push_back( xElem ); Reference< XComponent > xComp( xElem, UNO_QUERY ); if (xComp.is()) xComp->addEventListener( &_aEventListener ); } //__________________________________________________________________________________________________ void SAL_CALL ManagerImpl::remove( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) { if (!rBHelper.bDisposed && !rBHelper.bInDispose) { Reference< XHierarchicalNameAccess > xElem; if (! (rElement >>= xElem)) { throw IllegalArgumentException( OUString( RTL_CONSTASCII_USTRINGPARAM("no type description provider given!") ), (XWeak *)(OWeakObject *)this, 0 ); } MutexGuard aGuard( _aComponentMutex ); ProviderVector::iterator iFind( find( _aProviders.begin(), _aProviders.end(), xElem ) ); if (iFind == _aProviders.end()) { throw NoSuchElementException( OUString( RTL_CONSTASCII_USTRINGPARAM("provider not found!") ), (XWeak *)(OWeakObject *)this ); } _aProviders.erase( iFind ); } Reference< XComponent > xComp; if (rElement >>= xComp) xComp->removeEventListener( &_aEventListener ); } // XTypeDescriptionEnumerationAccess //__________________________________________________________________________________________________ // virtual Reference< XTypeDescriptionEnumeration > SAL_CALL ManagerImpl::createTypeDescriptionEnumeration( const OUString & moduleName, const Sequence< TypeClass > & types, TypeDescriptionSearchDepth depth ) throw ( NoSuchTypeNameException, InvalidTypeNameException, RuntimeException ) { MutexGuard aGuard( _aComponentMutex ); TDEnumerationAccessStack aStack; ProviderVector::const_iterator it = _aProviders.begin(); const ProviderVector::const_iterator end = _aProviders.end(); while ( it != end ) { Reference< XTypeDescriptionEnumerationAccess >xEnumAccess( (*it), UNO_QUERY ); OSL_ENSURE( xEnumAccess.is(), "### no XTypeDescriptionEnumerationAccess!" ); if ( xEnumAccess.is() ) aStack.push( xEnumAccess ); it++; } return Reference< XTypeDescriptionEnumeration >( new TypeDescriptionEnumerationImpl( moduleName, types, depth, aStack ) ); } //################################################################################################## //################################################################################################## //################################################################################################## //================================================================================================== class SimpleTypeDescriptionImpl : public WeakImplHelper1< XTypeDescription > { TypeClass _eTC; OUString _aName; public: SimpleTypeDescriptionImpl( TypeClass eTC, const OUString & rName ) : _eTC( eTC ) , _aName( rName ) {} // XTypeDescription virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); }; // XTypeDescription //__________________________________________________________________________________________________ TypeClass SimpleTypeDescriptionImpl::getTypeClass() throw(::com::sun::star::uno::RuntimeException) { return _eTC; } //__________________________________________________________________________________________________ OUString SimpleTypeDescriptionImpl::getName() throw(::com::sun::star::uno::RuntimeException) { return _aName; } //================================================================================================== class SequenceTypeDescriptionImpl : public WeakImplHelper1< XIndirectTypeDescription > { Reference< XTypeDescription > _xElementTD; public: SequenceTypeDescriptionImpl( const Reference< XTypeDescription > & xElementTD ) : _xElementTD( xElementTD ) {} // XTypeDescription virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); // XIndirectTypeDescription virtual Reference< XTypeDescription > SAL_CALL getReferencedType() throw(::com::sun::star::uno::RuntimeException); }; // XTypeDescription //__________________________________________________________________________________________________ TypeClass SequenceTypeDescriptionImpl::getTypeClass() throw(::com::sun::star::uno::RuntimeException) { return TypeClass_SEQUENCE; } //__________________________________________________________________________________________________ OUString SequenceTypeDescriptionImpl::getName() throw(::com::sun::star::uno::RuntimeException) { return (OUString( RTL_CONSTASCII_USTRINGPARAM("[]") ) + _xElementTD->getName()); } // XIndirectTypeDescription //__________________________________________________________________________________________________ Reference< XTypeDescription > SequenceTypeDescriptionImpl::getReferencedType() throw(::com::sun::star::uno::RuntimeException) { return _xElementTD; } //================================================================================================== class ArrayTypeDescriptionImpl : public WeakImplHelper1< XArrayTypeDescription > { Reference< XTypeDescription > _xElementTD; Mutex _aDimensionMutex; sal_Int32 _nDimensions; Sequence< sal_Int32 > _seqDimensions; OUString _sDimensions; void initDimensions(const OUString& rSDimensions); public: ArrayTypeDescriptionImpl( const Reference< XTypeDescription > & xElementTD, sal_Int32 nDimensions, const OUString& rSDimensions ) : _xElementTD( xElementTD ) , _nDimensions( nDimensions ) , _seqDimensions( Sequence< sal_Int32 >(nDimensions) ) , _sDimensions( rSDimensions ) { initDimensions( rSDimensions ); } virtual ~ArrayTypeDescriptionImpl() {} // XTypeDescription virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); // XArrayTypeDescription virtual Reference< XTypeDescription > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException); virtual sal_Int32 SAL_CALL getNumberOfDimensions() throw(::com::sun::star::uno::RuntimeException); virtual Sequence< sal_Int32 > SAL_CALL getDimensions() throw(::com::sun::star::uno::RuntimeException); }; //__________________________________________________________________________________________________ static sal_Int32 unicodeToInteger( sal_Int8 base, const sal_Unicode *s ) { sal_Int32 r = 0; sal_Int32 negative = 0; if (*s == '-') { negative = 1; s++; } if (base == 8 && *s == '0') s++; else if (base == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) s += 2; for (; *s; s++) { if (*s <= '9' && *s >= '0') r = (r * base) + (*s - '0'); else if (base > 10 && *s <= 'f' && *s >= 'a') r = (r * base) + (*s - 'a' + 10); else if (base > 10 && *s <= 'F' && *s >= 'A') r = (r * base) + (*s - 'A' + 10); else break; } if (negative) r *= -1; return r; } //__________________________________________________________________________________________________ void ArrayTypeDescriptionImpl::initDimensions(const OUString& rSDimensions) { MutexGuard aGuard( _aDimensionMutex ); sal_Int32 * pDimensions = _seqDimensions.getArray(); OUString tmp(rSDimensions); sal_Unicode* p = (sal_Unicode*)tmp.getStr()+1; sal_Unicode* pOffset = p; sal_Int32 len = tmp.getLength() - 1 ; sal_Int32 i = 0; while ( len > 0) { pOffset++; if (*pOffset == ']') { *pOffset = '\0'; pOffset += 2; len -= 3; pDimensions[i++] = unicodeToInteger(10, p); p = pOffset; } else len--; } } // XTypeDescription //__________________________________________________________________________________________________ TypeClass ArrayTypeDescriptionImpl::getTypeClass() throw(::com::sun::star::uno::RuntimeException) { return TypeClass_ARRAY; } //__________________________________________________________________________________________________ OUString ArrayTypeDescriptionImpl::getName() throw(::com::sun::star::uno::RuntimeException) { return (_xElementTD->getName() + _sDimensions); } // XArrayTypeDescription //__________________________________________________________________________________________________ Reference< XTypeDescription > ArrayTypeDescriptionImpl::getType() throw(::com::sun::star::uno::RuntimeException) { return _xElementTD; } //__________________________________________________________________________________________________ sal_Int32 ArrayTypeDescriptionImpl::getNumberOfDimensions() throw(::com::sun::star::uno::RuntimeException) { return _nDimensions; } //__________________________________________________________________________________________________ Sequence< sal_Int32 > ArrayTypeDescriptionImpl::getDimensions() throw(::com::sun::star::uno::RuntimeException) { return _seqDimensions; } //################################################################################################## //################################################################################################## //################################################################################################## //__________________________________________________________________________________________________ inline Any ManagerImpl::getSimpleType( const OUString & rName ) { Any aRet; if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("string") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_STRING, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("long") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_LONG, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned long") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_LONG, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("boolean") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_BOOLEAN, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("char") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_CHAR, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("byte") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_BYTE, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("short") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_SHORT, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned short") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_SHORT, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("hyper") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_HYPER, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned hyper") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_HYPER, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("float") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_FLOAT, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("double") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_DOUBLE, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("any") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_ANY, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("void") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_VOID, rName ) ); else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("type") )) aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_TYPE, rName ) ); return aRet; } namespace { Reference< XTypeDescription > resolveTypedefs( Reference< XTypeDescription > const & type) { Reference< XTypeDescription > resolved(type); while (resolved->getTypeClass() == TypeClass_TYPEDEF) { resolved = Reference< XIndirectTypeDescription >( type, UNO_QUERY_THROW)->getReferencedType(); } return resolved; } bool isNonVoidNonExceptionType(Reference< XTypeDescription > const & type) { switch (type->getTypeClass()) { case TypeClass_BOOLEAN: case TypeClass_BYTE: case TypeClass_SHORT: case TypeClass_UNSIGNED_SHORT: case TypeClass_LONG: case TypeClass_UNSIGNED_LONG: case TypeClass_HYPER: case TypeClass_UNSIGNED_HYPER: case TypeClass_FLOAT: case TypeClass_DOUBLE: case TypeClass_CHAR: case TypeClass_STRING: case TypeClass_TYPE: case TypeClass_ANY: case TypeClass_SEQUENCE: case TypeClass_ENUM: case TypeClass_STRUCT: case TypeClass_INTERFACE: return true; default: return false; } } class InstantiatedStruct: public WeakImplHelper1< XStructTypeDescription > { public: InstantiatedStruct( Reference< XStructTypeDescription > const & structType, std::vector< Reference< XTypeDescription > > const & arguments); virtual TypeClass SAL_CALL getTypeClass() throw (RuntimeException) { return TypeClass_STRUCT; } virtual OUString SAL_CALL getName() throw (RuntimeException); virtual Reference< XTypeDescription > SAL_CALL getBaseType() throw (RuntimeException) { return m_struct->getBaseType(); } virtual Sequence< Reference< XTypeDescription > > SAL_CALL getMemberTypes() throw (RuntimeException); virtual Sequence< OUString > SAL_CALL getMemberNames() throw (RuntimeException) { return m_struct->getMemberNames(); } virtual Sequence< OUString > SAL_CALL getTypeParameters() throw (RuntimeException) { return Sequence< OUString >(); } virtual Sequence< Reference< XTypeDescription > > SAL_CALL getTypeArguments() throw (RuntimeException) { return m_arguments; } private: Reference< XStructTypeDescription > m_struct; Sequence< Reference< XTypeDescription > > m_arguments; }; InstantiatedStruct::InstantiatedStruct( Reference< XStructTypeDescription > const & structType, std::vector< Reference< XTypeDescription > > const & arguments): m_struct(structType), m_arguments(static_cast< sal_Int32 >(arguments.size())) { for (std::vector< Reference< XTypeDescription > >::size_type i = 0; i < arguments.size(); ++i) { m_arguments[static_cast< sal_Int32 >(i)] = arguments[i]; } } OUString InstantiatedStruct::getName() throw (RuntimeException) { OUStringBuffer buf(m_struct->getName()); buf.append(static_cast< sal_Unicode >('<')); for (sal_Int32 i = 0; i < m_arguments.getLength(); ++i) { if (i != 0) { buf.append(static_cast< sal_Unicode >(',')); } buf.append(m_arguments[i]->getName()); } buf.append(static_cast< sal_Unicode >('>')); return buf.makeStringAndClear(); } Sequence< Reference< XTypeDescription > > InstantiatedStruct::getMemberTypes() throw (RuntimeException) { Sequence< Reference< XTypeDescription > > types(m_struct->getMemberTypes()); for (sal_Int32 i = 0; i < types.getLength(); ++i) { if (types[i]->getTypeClass() == TypeClass_UNKNOWN) { Sequence< OUString > parameters(m_struct->getTypeParameters()); OSL_ASSERT(parameters.getLength() == m_arguments.getLength()); for (sal_Int32 j = 0; j < parameters.getLength(); ++j) { if (parameters[j] == types[i]->getName()) { types[i] = m_arguments[j]; break; } } } } return types; } } Reference< XTypeDescription > ManagerImpl::getInstantiatedStruct( OUString const & name) { sal_Int32 i = name.indexOf('<'); OSL_ASSERT(i >= 0); Reference< XStructTypeDescription > structType( getByHierarchicalName(name.copy(0, i)), UNO_QUERY); std::vector< Reference< XTypeDescription > > args; bool good = structType.is(); if (good) { do { ++i; // skip '<' or ',' sal_Int32 j = i; for (sal_Int32 level = 0; j != name.getLength(); ++j) { sal_Unicode c = name[j]; if (c == ',') { if (level == 0) { break; } } else if (c == '<') { ++level; } else if (c == '>') { if (level == 0) { break; } --level; } } if (j != name.getLength()) { Reference< XTypeDescription > type( getByHierarchicalName(name.copy(i, j - i)), UNO_QUERY); if (isNonVoidNonExceptionType(resolveTypedefs(type))) { args.push_back(type); } else { good = false; break; } } i = j; } while (i != name.getLength() && name[i] != '>'); good = good && i == name.getLength() - 1 && name[i] == '>' && !args.empty(); } // args.size() cannot exceed SAL_MAX_INT32, as each argument consumes at // least one position within an rtl::OUString (which is no longer than // SAL_MAX_INT32): if (!good || (args.size() != sal::static_int_cast< sal_uInt32 >( structType->getTypeParameters().getLength()))) { throw NoSuchElementException(name, static_cast< OWeakObject * >(this)); } return new InstantiatedStruct(structType, args); } // XHierarchicalNameAccess //__________________________________________________________________________________________________ Any ManagerImpl::getByHierarchicalName( const OUString & rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) { Any aRet; if (_bCaching) aRet = _aElements.getValue( rName ); if (rName.getLength() && !aRet.hasValue()) { sal_Int32 nIndex; if (rName[0] == '[') // test for sequence { Reference< XTypeDescription > xElemType( getByHierarchicalName( rName.copy( 2 ) ), UNO_QUERY_THROW ); aRet <<= Reference< XTypeDescription >( new SequenceTypeDescriptionImpl( xElemType ) ); } else if (rName[rName.getLength()-1] == ']') // test for array { sal_Int32 nIndex2 = 0, nTokens = 0; do { rName.getToken( 0, '[', nIndex2 ); nTokens++; } while( nIndex2 != -1 ); sal_Int32 nDims = nTokens - 1; sal_Int32 dimOffset = rName.indexOf('['); Reference< XTypeDescription > xElemType( getByHierarchicalName( rName.copy( 0, dimOffset ) ), UNO_QUERY_THROW ); aRet <<= Reference< XTypeDescription >( new ArrayTypeDescriptionImpl( xElemType, nDims, rName.copy(dimOffset) ) ); } // test for interface member names: else if ((nIndex = rName.indexOf( ':' )) >= 0) { Reference< XInterfaceTypeDescription > xIfaceTD( getByHierarchicalName( rName.copy( 0, nIndex ) ), UNO_QUERY_THROW ); const Sequence< Reference< XInterfaceMemberTypeDescription > > & rMembers = xIfaceTD->getMembers(); const Reference< XInterfaceMemberTypeDescription > * pMembers = rMembers.getConstArray(); for ( sal_Int32 nPos = rMembers.getLength(); nPos--; ) { if (rName == pMembers[nPos]->getName()) { aRet <<= Reference< XTypeDescription >( pMembers[nPos], UNO_QUERY_THROW ); break; } } if (! aRet.hasValue()) { // member not found: throw NoSuchElementException( rName, static_cast< OWeakObject * >(this) ); } } // test for instantiated polymorphic struct types: else if (rName.indexOf('<') >= 0) { aRet <<= getInstantiatedStruct(rName); } else if (rName.indexOf( '.' ) < 0) // test for simple/ build in types { aRet = getSimpleType( rName ); } if (! aRet.hasValue()) { // last, try callback chain for ( ProviderVector::const_iterator iPos( _aProviders.begin() ); iPos != _aProviders.end(); ++iPos ) { try { if ((aRet = (*iPos)->getByHierarchicalName( rName )).hasValue()) { break; } } catch (NoSuchElementException &) { } } } // update cache if (_bCaching && aRet.hasValue()) _aElements.setValue( rName, aRet ); } if (! aRet.hasValue()) { throw NoSuchElementException( rName, static_cast< OWeakObject * >(this) ); } return aRet; } //__________________________________________________________________________________________________ sal_Bool ManagerImpl::hasByHierarchicalName( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException) { try { return getByHierarchicalName( rName ).hasValue(); } catch (NoSuchElementException &) { } return sal_False; } } namespace stoc_bootstrap { //================================================================================================== Reference< XInterface > SAL_CALL ManagerImpl_create( Reference< XComponentContext > const & xContext ) SAL_THROW( (::com::sun::star::uno::Exception) ) { sal_Int32 nCacheSize = CACHE_SIZE; if (xContext.is()) { xContext->getValueByName( OUString( RTL_CONSTASCII_USTRINGPARAM( "/implementations/" IMPLNAME "/CacheSize"))) >>= nCacheSize; } return Reference< XInterface >( *new stoc_tdmgr::ManagerImpl( xContext, nCacheSize ) ); } }