| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_stoc.hxx" |
| #include <osl/diagnose.h> |
| #include <osl/mutex.hxx> |
| #include "rtl/ustrbuf.hxx" |
| #include <cppuhelper/factory.hxx> |
| #ifndef _CPPUHELPER_IMPLBASE5_HXX_ |
| #include <cppuhelper/compbase5.hxx> |
| #endif |
| #include <cppuhelper/implbase1.hxx> |
| #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ |
| #include <cppuhelper/implementationentry.hxx> |
| #endif |
| #include "tdmgr_common.hxx" |
| #include "tdmgr_tdenumeration.hxx" |
| #include "lrucache.hxx" |
| |
| #include <com/sun/star/lang/XServiceInfo.hpp> |
| #include <com/sun/star/lang/XSingleServiceFactory.hpp> |
| #include <com/sun/star/lang/XEventListener.hpp> |
| #include <com/sun/star/lang/XTypeProvider.hpp> |
| #include <com/sun/star/lang/XComponent.hpp> |
| #include <com/sun/star/lang/XInitialization.hpp> |
| #include <com/sun/star/container/XHierarchicalNameAccess.hpp> |
| #include <com/sun/star/container/XSet.hpp> |
| #include <com/sun/star/container/XContentEnumerationAccess.hpp> |
| #include <com/sun/star/reflection/XTypeDescription.hpp> |
| #include <com/sun/star/reflection/XArrayTypeDescription.hpp> |
| #include <com/sun/star/reflection/XIndirectTypeDescription.hpp> |
| #include <com/sun/star/reflection/XInterfaceTypeDescription.hpp> |
| #include "com/sun/star/reflection/XStructTypeDescription.hpp" |
| #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> |
| #include <com/sun/star/registry/XRegistryKey.hpp> |
| #include "com/sun/star/uno/RuntimeException.hpp" |
| |
| #include <algorithm> |
| #include <vector> |
| |
| 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<reflection::XTypeDescriptionEnumerationAccess> 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<reflection::XTypeDescriptionEnumeration> xTDEnum( |
| xTDEnumAccess->createTypeDescriptionEnumeration( |
| OUString() /* all modules */, |
| Sequence<TypeClass>( ar, ARLEN(ar) ), |
| reflection::TypeDescriptionSearchDepth_INFINITE ) ); |
| |
| while (xTDEnum->hasMoreElements()) |
| { |
| Reference<reflection::XTypeDescription> xNewTD; |
| try |
| { |
| xNewTD = xTDEnum->nextTypeDescription(); |
| } |
| catch (container::NoSuchElementException & exc) |
| { |
| throw lang::IllegalArgumentException( |
| OUSTR("NoSuchElementException occured: ") + |
| exc.Message, static_cast<OWeakObject *>(this), |
| -1 /* unknown */ ); |
| } |
| |
| try |
| { |
| OUString newName( xNewTD->getName() ); |
| Reference<reflection::XTypeDescription> 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<OWeakObject *>(this), 0 ); |
| } |
| } |
| } |
| catch (container::NoSuchElementException &) |
| { |
| // type not in: ok |
| } |
| } |
| } |
| catch (reflection::NoSuchTypeNameException & exc) |
| { |
| throw lang::IllegalArgumentException( |
| OUSTR("NoSuchTypeNameException occured: ") + exc.Message, |
| static_cast<OWeakObject *>(this), -1 /* unknown */ ); |
| } |
| catch (reflection::InvalidTypeNameException & exc) |
| { |
| throw lang::IllegalArgumentException( |
| OUSTR("InvalidTypeNameException occured: ") + exc.Message, |
| static_cast<OWeakObject *>(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 ) ); |
| } |
| |
| } |
| |