diff options
Diffstat (limited to 'stoc/source/tdmanager')
-rw-r--r-- | stoc/source/tdmanager/lrucache.hxx | 247 | ||||
-rw-r--r-- | stoc/source/tdmanager/makefile.mk | 49 | ||||
-rw-r--r-- | stoc/source/tdmanager/tdmgr.cxx | 1163 | ||||
-rw-r--r-- | stoc/source/tdmanager/tdmgr_check.cxx | 556 | ||||
-rw-r--r-- | stoc/source/tdmanager/tdmgr_common.hxx | 60 | ||||
-rw-r--r-- | stoc/source/tdmanager/tdmgr_tdenumeration.cxx | 187 | ||||
-rw-r--r-- | stoc/source/tdmanager/tdmgr_tdenumeration.hxx | 89 |
7 files changed, 2351 insertions, 0 deletions
diff --git a/stoc/source/tdmanager/lrucache.hxx b/stoc/source/tdmanager/lrucache.hxx new file mode 100644 index 000000000000..fadc0a59b7bf --- /dev/null +++ b/stoc/source/tdmanager/lrucache.hxx @@ -0,0 +1,247 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _LRU_CACHE_HXX_ +#define _LRU_CACHE_HXX_ + +// __CACHE_DIAGNOSE forces cache size to 4 and works only for OUString keys +// #define __CACHE_DIAGNOSE 1 + +#include <osl/mutex.hxx> +#include "rtl/ustring.hxx" + +#include <hash_map> + + +/** Implementation of a least recently used (lru) cache. + <br> + @author Daniel Boelzle +*/ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +class LRU_Cache +{ + struct CacheEntry + { + t_Key aKey; + t_Val aVal; + CacheEntry * pPred; + CacheEntry * pSucc; + }; + typedef ::std::hash_map< t_Key, CacheEntry *, t_KeyHash, t_KeyEqual > t_Key2Element; + + mutable ::osl::Mutex _aCacheMutex; + sal_Int32 _nCachedElements; + t_Key2Element _aKey2Element; + + CacheEntry * _pBlock; + mutable CacheEntry * _pHead; + mutable CacheEntry * _pTail; + inline void toFront( CacheEntry * pEntry ) const; + +public: + /** Constructor: + <br> + @param nCachedElements number of elements to be cached; default param set to 128 + */ + inline LRU_Cache( sal_Int32 nCachedElements = 128 ); + /** Destructor: releases all cached elements and keys. + <br> + */ + inline ~LRU_Cache(); + + /** Retrieves a value from the cache. Returns default constructed value, + if none was found. + <br> + @param rKey a key + @return value + */ + inline t_Val getValue( t_Key const & rKey ) const; + /** Sets a value to be cached for given key. + <br> + @param rKey a key + @param rValue a value + */ + inline void setValue( t_Key const & rKey, t_Val const & rValue ); + /** Tests whether a value is cached for given key. + <br> + @param rKey a key + @return true, if value is cached + */ + inline sal_Bool hasValue( t_Key const & rKey ) const; + /** Clears the cache, thus releasing all cached elements and keys. + <br> + */ + inline void clear(); +}; +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::LRU_Cache( sal_Int32 nCachedElements ) +#ifdef __CACHE_DIAGNOSE + : _nCachedElements( 4 ) +#else + : _nCachedElements( nCachedElements ) +#endif + , _pBlock( 0 ) +{ + if (_nCachedElements > 0) + { + _pBlock = new CacheEntry[_nCachedElements]; + _pHead = _pBlock; + _pTail = _pBlock + _nCachedElements -1; + for ( sal_Int32 nPos = _nCachedElements; nPos--; ) + { + _pBlock[nPos].pPred = _pBlock + nPos -1; + _pBlock[nPos].pSucc = _pBlock + nPos +1; + } + } +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::~LRU_Cache() +{ + delete [] _pBlock; +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::toFront( + CacheEntry * pEntry ) const +{ + if (pEntry != _pHead) + { + // cut out element + if (pEntry == _pTail) + { + _pTail = pEntry->pPred; + } + else + { + pEntry->pSucc->pPred = pEntry->pPred; + pEntry->pPred->pSucc = pEntry->pSucc; + } + // push to front + _pHead->pPred = pEntry; + pEntry->pSucc = _pHead; + _pHead = pEntry; + } +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline sal_Bool LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::hasValue( + t_Key const & rKey ) const +{ + ::osl::MutexGuard aGuard( _aCacheMutex ); + typename t_Key2Element::const_iterator const iFind( _aKey2Element.find( rKey ) ); + return (iFind != _aKey2Element.end()); +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline t_Val LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::getValue( + t_Key const & rKey ) const +{ + ::osl::MutexGuard aGuard( _aCacheMutex ); + const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) ); + if (iFind != _aKey2Element.end()) + { + CacheEntry * pEntry = (*iFind).second; + toFront( pEntry ); +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> retrieved element \"" ); + OSL_TRACE( ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( "\" from cache <\n" ); +#endif + return pEntry->aVal; + } + return t_Val(); +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::setValue( + t_Key const & rKey, t_Val const & rValue ) +{ + if (_nCachedElements > 0) + { + ::osl::MutexGuard aGuard( _aCacheMutex ); + typename t_Key2Element::const_iterator const iFind( _aKey2Element.find( rKey ) ); + + CacheEntry * pEntry; + if (iFind == _aKey2Element.end()) + { + pEntry = _pTail; // erase last element +#ifdef __CACHE_DIAGNOSE + if (pEntry->aKey.getLength()) + { + OSL_TRACE( "> kicking element \"" ); + OSL_TRACE( ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( "\" from cache <\n" ); + } +#endif + _aKey2Element.erase( pEntry->aKey ); + _aKey2Element[ pEntry->aKey = rKey ] = pEntry; + } + else + { + pEntry = (*iFind).second; +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> replacing element \"" ); + OSL_TRACE( ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( "\" in cache <\n" ); +#endif + } + pEntry->aVal = rValue; + toFront( pEntry ); + } +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::clear() +{ + ::osl::MutexGuard aGuard( _aCacheMutex ); + _aKey2Element.clear(); + for ( sal_Int32 nPos = _nCachedElements; nPos--; ) + { + _pBlock[nPos].aKey = t_Key(); + _pBlock[nPos].aVal = t_Val(); + } +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> cleared cache <\n" ); +#endif +} + +//================================================================================================== +struct FctHashOUString : public ::std::unary_function< ::rtl::OUString const &, size_t > +{ + size_t operator()( ::rtl::OUString const & rKey ) const + { return (size_t)rKey.hashCode(); } +}; + +/** Template instance for OUString keys, Any values.<br> +*/ +typedef LRU_Cache< ::rtl::OUString, ::com::sun::star::uno::Any, + FctHashOUString, ::std::equal_to< ::rtl::OUString > > + LRU_CacheAnyByOUString; + + +#endif diff --git a/stoc/source/tdmanager/makefile.mk b/stoc/source/tdmanager/makefile.mk new file mode 100644 index 000000000000..dbc4e762afff --- /dev/null +++ b/stoc/source/tdmanager/makefile.mk @@ -0,0 +1,49 @@ +#************************************************************************* +# +# 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 +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = typemgr +ENABLE_EXCEPTIONS=TRUE +BOOTSTRAP_SERVICE=TRUE +UNOUCROUT= $(OUT)$/inc$/bootstrap + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/tdmgr.obj \ + $(SLO)$/tdmgr_check.obj \ + $(SLO)$/tdmgr_tdenumeration.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/source/tdmanager/tdmgr.cxx b/stoc/source/tdmanager/tdmgr.cxx new file mode 100644 index 000000000000..390881bb0d1d --- /dev/null +++ b/stoc/source/tdmanager/tdmgr.cxx @@ -0,0 +1,1163 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 ) ); +} + +} + diff --git a/stoc/source/tdmanager/tdmgr_check.cxx b/stoc/source/tdmanager/tdmgr_check.cxx new file mode 100644 index 000000000000..0a19403532bf --- /dev/null +++ b/stoc/source/tdmanager/tdmgr_check.cxx @@ -0,0 +1,556 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "tdmgr_common.hxx" +#include "rtl/ustrbuf.hxx" +#include "typelib/typedescription.h" +#include "com/sun/star/beans/PropertyAttribute.hpp" +#include "com/sun/star/reflection/XConstantsTypeDescription.hpp" +#include "com/sun/star/reflection/XIndirectTypeDescription.hpp" +#include "com/sun/star/reflection/XEnumTypeDescription.hpp" +#include "com/sun/star/reflection/XStructTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" +#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp" +#include "com/sun/star/reflection/XServiceTypeDescription2.hpp" +#include "com/sun/star/reflection/XSingletonTypeDescription2.hpp" + + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::stoc_tdmgr; + +namespace { + +OUString getTypeClassName( TypeClass tc ) +{ + typelib_EnumTypeDescription * typeDescr = 0; + OUString name = OUSTR("com.sun.star.uno.TypeClass"); + typelib_typedescription_getByName( + reinterpret_cast<typelib_TypeDescription **>(&typeDescr), name.pData ); + OSL_ASSERT( typeDescr != 0 ); + if (typeDescr == 0) + return OUSTR("Cannot get type description of ") + name; + typelib_typedescription_complete( + reinterpret_cast<typelib_TypeDescription **>(&typeDescr) ); + + sal_Int32 const * pValues = typeDescr->pEnumValues; + sal_Int32 nPos = typeDescr->nEnumValues; + while (nPos--) + { + if (pValues[ nPos ] == (sal_Int32) tc) + break; + } + if (nPos >= 0) + name = typeDescr->ppEnumNames[ nPos ]; + else + name = OUSTR("unknown TypeClass value: ") + + OUString::valueOf( (sal_Int32) tc ); + + typelib_typedescription_release( + reinterpret_cast<typelib_TypeDescription *>(typeDescr) ); + return name; +} + +OUString getPropertyFlagsAsString( sal_Int16 attributes ) +{ + OUStringBuffer buf; + if ((attributes & beans::PropertyAttribute::MAYBEVOID) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("MAYBEVOID, ") ); + if ((attributes & beans::PropertyAttribute::BOUND) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("BOUND, ") ); + if ((attributes & beans::PropertyAttribute::CONSTRAINED) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("CONSTRAINED, ") ); + if ((attributes & beans::PropertyAttribute::TRANSIENT) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("TRANSIENT, ") ); + if ((attributes & beans::PropertyAttribute::READONLY) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("READONLY, ") ); + if ((attributes & beans::PropertyAttribute::MAYBEAMBIGUOUS) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("MAYBEAMBIGUOUS, ") ); + if ((attributes & beans::PropertyAttribute::MAYBEDEFAULT) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("MAYBEDEFAULT, ") ); + if ((attributes & beans::PropertyAttribute::REMOVEABLE) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("REMOVEABLE, ") ); + if ((attributes & beans::PropertyAttribute::OPTIONAL) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("OPTIONAL") ); + else if (buf.getLength() > 0) + buf.setLength( buf.getLength() - 2 ); // truncate ", " + return buf.makeStringAndClear(); +} + +void typeError( OUString const & msg, OUString const & context ) +{ + OUStringBuffer buf; + if (context.getLength() > 0) { + buf.append( static_cast<sal_Unicode>('[') ); + buf.append( context ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); + } + buf.append( msg ); + throw IncompatibleTypeException( buf.makeStringAndClear() ); +} + +template<typename T> +void checkSeq( Sequence< Reference<T> > const & newTypes, + Sequence< Reference<T> > const & existingTypes, + OUString const & context, + bool optionalMode = false ) +{ + sal_Int32 len = newTypes.getLength(); + if (len != existingTypes.getLength()) + { + if (!optionalMode || len < newTypes.getLength()) + typeError( OUSTR("Different number of types!"), context ); + len = existingTypes.getLength(); + } + + Reference<T> const * pNewTypes = newTypes.getConstArray(); + Reference<T> const * pExistingTypes = existingTypes.getConstArray(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + OUStringBuffer buf; + buf.append( context ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", position ") ); + buf.append( pos ); + check( pNewTypes[pos].get(), pExistingTypes[pos].get(), + buf.makeStringAndClear() ); + } +} + +void checkEnum( + Reference<reflection::XEnumTypeDescription> const & xNewTD, + Reference<reflection::XEnumTypeDescription> const & xExistingTD ) +{ + if (xNewTD->getEnumNames() != xExistingTD->getEnumNames()) + typeError( OUSTR("ENUM names don't match!"), xNewTD->getName() ); + if (xNewTD->getEnumValues() != xExistingTD->getEnumValues()) + typeError( OUSTR("ENUM values don't match!"), xNewTD->getName() ); +} + +void checkStruct( + Reference<reflection::XCompoundTypeDescription> const & xNewTD, + Reference<reflection::XCompoundTypeDescription> const & xExistingTD ) +{ + check( xNewTD->getBaseType(), xExistingTD->getBaseType(), + xNewTD->getName() + OUSTR(", base type") ); + checkSeq( xNewTD->getMemberTypes(), xExistingTD->getMemberTypes(), + xNewTD->getName() + OUSTR(", member types") ); + + if (xNewTD->getMemberNames() != xExistingTD->getMemberNames()) + typeError( OUSTR("Different member names!"), xNewTD->getName() ); + + if (xNewTD->getTypeClass() == TypeClass_STRUCT) + { + Reference<reflection::XStructTypeDescription> xNewStructTD( + xNewTD, UNO_QUERY ); + Reference<reflection::XStructTypeDescription> xExistingStructTD( + xExistingTD, UNO_QUERY ); + if (xNewStructTD.is() && xExistingStructTD.is()) + { + if (xNewStructTD->getTypeParameters() != + xExistingStructTD->getTypeParameters()) + typeError( OUSTR("Different type parameters of instantiated " + "polymorphic STRUCT!"), xNewTD->getName() ); + checkSeq( xNewStructTD->getTypeArguments(), + xExistingStructTD->getTypeArguments(), + xNewTD->getName() + OUSTR(", argument types") ); + } + else if (xNewStructTD.is() || xExistingStructTD.is()) + typeError( OUSTR("Mixing polymorphic STRUCT types " + "with non-polymorphic!"), xNewTD->getName() ); + } +} + +void checkInterface( + Reference<reflection::XInterfaceTypeDescription2> const & xNewTD, + Reference<reflection::XInterfaceTypeDescription2> const & xExistingTD ) +{ + checkSeq( xNewTD->getBaseTypes(), xExistingTD->getBaseTypes(), + xNewTD->getName() + OUSTR(", base types") ); + checkSeq(xNewTD->getOptionalBaseTypes(),xExistingTD->getOptionalBaseTypes(), + xNewTD->getName() + OUSTR(", optional base types") ); + checkSeq( xNewTD->getMembers(), xExistingTD->getMembers(), + xNewTD->getName() + OUSTR(", members") ); +} + +void checkRestParam( Reference<reflection::XParameter> const & xNewParam, + Reference<reflection::XParameter> const & xExistingParam, + OUString const & context ) +{ + if (xNewParam->isRestParameter() != xExistingParam->isRestParameter()) + typeError( OUSTR("Different ... parameters specified!"), context ); +} + +void checkRestParam( Reference<reflection::XMethodParameter> const &, + Reference<reflection::XMethodParameter> const &, + OUString const & ) +{ +} + +template<typename T> +void checkParameters( Sequence< Reference<T> > const & newParams, + Sequence< Reference<T> > const & existingParams, + OUString const & context_ ) +{ + sal_Int32 len = newParams.getLength(); + if (len != existingParams.getLength()) + typeError( OUSTR("Different number of parameters!"), context_ ); + Reference<T> const * pNewParams = newParams.getConstArray(); + Reference<T> const * pExistingParams = existingParams.getConstArray(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + Reference<T> const & xNewParam = pNewParams[pos]; + Reference<T> const & xExistingParam = pExistingParams[pos]; + + OUStringBuffer buf; + buf.append( context_ ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", parameter ") ); + buf.append( pos ); + OSL_ASSERT( pos == xNewParam->getPosition() && + pos == xExistingParam->getPosition() ); + OUString context( buf.makeStringAndClear() ); + + if (xNewParam->getName() != xExistingParam->getName()) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("Name differs: ") ); + buf.append( xNewParam->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); + buf.append( xExistingParam->getName() ); + typeError( buf.makeStringAndClear(), context ); + } + check( xNewParam->getType(), xExistingParam->getType(), context ); + + if (xNewParam->isIn() != xExistingParam->isIn()) + typeError( OUSTR("IN attribute differs!"), context ); + if (xNewParam->isOut() != xExistingParam->isOut()) + typeError( OUSTR("OUT attribute differs!"), context ); + checkRestParam( xNewParam, xExistingParam, context ); + } +} + +static void checkMethod( + Reference<reflection::XInterfaceMethodTypeDescription> const & xNewTD, + Reference<reflection::XInterfaceMethodTypeDescription> const & xExistingTD ) +{ + check( xNewTD->getReturnType(), xExistingTD->getReturnType(), + xNewTD->getName() ); + + if (xNewTD->isOneway() != xExistingTD->isOneway()) + typeError( OUSTR("Methods have differing OneWay attribute!"), + xNewTD->getName() ); + + checkParameters( xNewTD->getParameters(), xExistingTD->getParameters(), + xNewTD->getName() ); + + checkSeq( xNewTD->getExceptions(), xExistingTD->getExceptions(), + xNewTD->getName() + OUSTR(", declared exceptions") ); +} + +void checkAttribute( + Reference<reflection::XInterfaceAttributeTypeDescription2> const & xNewTD, + Reference<reflection::XInterfaceAttributeTypeDescription2> + const & xExistingTD ) +{ + if (xNewTD->isReadOnly() != xExistingTD->isReadOnly()) + typeError( OUSTR("ReadOnly attribute differs!"), xNewTD->getName() ); + + check( xNewTD->getType(), xExistingTD->getType(), + xNewTD->getName() + OUSTR(", attribute type") ); + + if (xNewTD->isBound() != xExistingTD->isBound()) + typeError( OUSTR("Bound attribute differs!"), xNewTD->getName() ); + + checkSeq( xNewTD->getGetExceptions(), xExistingTD->getGetExceptions(), + xNewTD->getName() + OUSTR(", getter exceptions") ); + checkSeq( xNewTD->getSetExceptions(), xExistingTD->getSetExceptions(), + xNewTD->getName() + OUSTR(", setter exceptions") ); +} + +void checkProperty( + Reference<reflection::XPropertyTypeDescription> const & xNewTD, + Reference<reflection::XPropertyTypeDescription> const & xExistingTD ) +{ + if (xNewTD->getPropertyFlags() != xExistingTD->getPropertyFlags()) + { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "Different set of property flags: { ") ); + buf.append( getPropertyFlagsAsString( + xNewTD->getPropertyFlags() ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" } (new), { ") ); + buf.append( getPropertyFlagsAsString( + xExistingTD->getPropertyFlags() ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" } (existing)!") ); + typeError( buf.makeStringAndClear(), xNewTD->getName() ); + } + + check( xNewTD->getPropertyTypeDescription(), + xExistingTD->getPropertyTypeDescription(), + xNewTD->getName() ); +} + +void checkSingleton( + Reference<reflection::XSingletonTypeDescription2> const & xNewTD, + Reference<reflection::XSingletonTypeDescription2> const & xExistingTD ) +{ + sal_Bool ifaceBased = xNewTD->isInterfaceBased(); + if (ifaceBased != xExistingTD->isInterfaceBased()) + typeError( + OUSTR("Mixing interface and NON-interface based singletons!"), + xNewTD->getName() ); + if (ifaceBased) + check( xNewTD->getInterface(), xExistingTD->getInterface(), + xNewTD->getName() ); + else + check( xNewTD->getService().get(), xExistingTD->getService().get(), + xNewTD->getName() ); +} + +void checkService( + Reference<reflection::XServiceTypeDescription2> const & xNewTD, + Reference<reflection::XServiceTypeDescription2> const & xExistingTD ) +{ + sal_Bool singleIfaceBased = xNewTD->isSingleInterfaceBased(); + if (singleIfaceBased != xExistingTD->isSingleInterfaceBased()) + typeError( OUSTR("Mixing interface and NON-interface based services!"), + xNewTD->getName() ); + if (singleIfaceBased) + { + check( xNewTD->getInterface(), xExistingTD->getInterface(), + xNewTD->getName() ); + Sequence< Reference<reflection::XServiceConstructorDescription> > + newCtors( xNewTD->getConstructors() ); + Sequence< Reference<reflection::XServiceConstructorDescription> > + existingCtors( xExistingTD->getConstructors() ); + sal_Int32 len = newCtors.getLength(); + if (len != existingCtors.getLength()) + typeError( OUSTR("Different number of service constructors!"), + xNewTD->getName() ); + Reference<reflection::XServiceConstructorDescription> const * + pNewCtors = newCtors.getConstArray(); + Reference<reflection::XServiceConstructorDescription> const * + pExistingCtors = existingCtors.getConstArray(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + Reference<reflection::XServiceConstructorDescription> const & + xNewCtor = pNewCtors[pos]; + Reference<reflection::XServiceConstructorDescription> const & + xExistingCtor = pExistingCtors[pos]; + + if (xNewCtor->getName() != xExistingCtor->getName()) + { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "Different constructor names: ") ); + buf.append( xNewCtor->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (new), ") ); + buf.append( xExistingCtor->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (existing)!") ); + typeError( buf.makeStringAndClear(), xNewTD->getName() ); + } + + OUStringBuffer buf; + buf.append( xNewTD->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", constructor ") ); + buf.append( xNewCtor->getName() ); + OUString context( buf.makeStringAndClear() ); + checkParameters( xNewCtor->getParameters(), + xExistingCtor->getParameters(), + context ); + checkSeq( xNewCtor->getExceptions(), xExistingCtor->getExceptions(), + context + OUSTR(", exceptions") ); + } + } + else // old-style service descriptions: + { + checkSeq( xNewTD->getMandatoryServices(), + xExistingTD->getMandatoryServices(), + xNewTD->getName() + OUSTR(", mandatory services") ); + checkSeq( xNewTD->getOptionalServices(), + xExistingTD->getOptionalServices(), + xNewTD->getName() + OUSTR(", optional services"), + true /* optionalMode */ ); + checkSeq( xNewTD->getMandatoryInterfaces(), + xExistingTD->getMandatoryInterfaces(), + xNewTD->getName() + OUSTR(", mandatory interfaces") ); + checkSeq( xNewTD->getOptionalInterfaces(), + xExistingTD->getOptionalInterfaces(), + xNewTD->getName() + OUSTR(", optional interfaces"), + true /* optionalMode */ ); + + Sequence< Reference<reflection::XPropertyTypeDescription> > + newProperties( xNewTD->getProperties() ); + Sequence< Reference<reflection::XPropertyTypeDescription> > + existingProperties( xExistingTD->getProperties() ); + checkSeq( newProperties, existingProperties, + xNewTD->getName() + OUSTR(", properties"), + true /* optionalMode */ ); + if (newProperties.getLength() > existingProperties.getLength()) + { + // check whether all added properties are OPTIONAL: + Reference<reflection::XPropertyTypeDescription> const * + pNewProperties = newProperties.getConstArray(); + for ( sal_Int32 pos = existingProperties.getLength() + 1; + pos < newProperties.getLength(); ++pos ) + { + if ((pNewProperties[pos]->getPropertyFlags() & + beans::PropertyAttribute::OPTIONAL) == 0) + typeError( OUSTR("New property is not OPTIONAL!"), + pNewProperties[pos]->getName() ); + } + } + } +} + +} + +namespace stoc_tdmgr { + +void check( Reference<reflection::XTypeDescription> const & xNewTD, + Reference<reflection::XTypeDescription> const & xExistingTD, + OUString const & context ) +{ + if (xNewTD == xExistingTD) + return; + if (xNewTD->getName() != xExistingTD->getName()) + { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("Different type names: ") ); + buf.append( xNewTD->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (new), ") ); + buf.append( xExistingTD->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (existing)!") ); + typeError( buf.makeStringAndClear(), context ); + } + + TypeClass tc = xNewTD->getTypeClass(); + if (tc != xExistingTD->getTypeClass()) + { + OUStringBuffer buf; + buf.append( xNewTD->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + " has different type classes: ") ); + buf.append( getTypeClassName( tc ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (new), ") ); + buf.append( getTypeClassName( xExistingTD->getTypeClass() ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (existing)!") ); + typeError( buf.makeStringAndClear(), context ); + } + + switch (tc) + { + case TypeClass_ENUM: + checkEnum( Reference<reflection::XEnumTypeDescription>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XEnumTypeDescription>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_TYPEDEF: + case TypeClass_SEQUENCE: + check( Reference<reflection::XIndirectTypeDescription>( + xNewTD, UNO_QUERY_THROW )->getReferencedType(), + Reference<reflection::XIndirectTypeDescription>( + xExistingTD, UNO_QUERY_THROW )->getReferencedType() ); + break; + + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: + checkStruct( Reference<reflection::XCompoundTypeDescription>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XCompoundTypeDescription>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_INTERFACE: + checkInterface( Reference<reflection::XInterfaceTypeDescription2>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XInterfaceTypeDescription2>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_SERVICE: + checkService( Reference<reflection::XServiceTypeDescription2>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XServiceTypeDescription2>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_INTERFACE_METHOD: + checkMethod( Reference<reflection::XInterfaceMethodTypeDescription>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XInterfaceMethodTypeDescription>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + case TypeClass_INTERFACE_ATTRIBUTE: + checkAttribute( + Reference<reflection::XInterfaceAttributeTypeDescription2>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XInterfaceAttributeTypeDescription2>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_PROPERTY: + checkProperty( Reference<reflection::XPropertyTypeDescription>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XPropertyTypeDescription>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_CONSTANT: + if (Reference<reflection::XConstantTypeDescription>( + xNewTD, UNO_QUERY_THROW )->getConstantValue() != + Reference<reflection::XConstantTypeDescription>( + xExistingTD, UNO_QUERY_THROW )->getConstantValue()) + typeError( OUSTR("Different constant value!"), xNewTD->getName() ); + break; + case TypeClass_CONSTANTS: + checkSeq( Reference<reflection::XConstantsTypeDescription>( + xNewTD, UNO_QUERY_THROW )->getConstants(), + Reference<reflection::XConstantsTypeDescription>( + xExistingTD, UNO_QUERY_THROW )->getConstants(), + xNewTD->getName() ); + break; + + case TypeClass_SINGLETON: + checkSingleton( Reference<reflection::XSingletonTypeDescription2>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XSingletonTypeDescription2>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + default: + break; + } +} + +} diff --git a/stoc/source/tdmanager/tdmgr_common.hxx b/stoc/source/tdmanager/tdmgr_common.hxx new file mode 100644 index 000000000000..5d640e99f919 --- /dev/null +++ b/stoc/source/tdmanager/tdmgr_common.hxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STOC_TDMGR_COMMON_HXX +#define _STOC_TDMGR_COMMON_HXX + +#include <rtl/unload.h> + +#include "com/sun/star/reflection/XTypeDescription.hpp" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) +#define ARLEN(x) (sizeof (x) / sizeof *(x)) + + +namespace css = ::com::sun::star; + +namespace stoc_tdmgr +{ + extern rtl_StandardModuleCount g_moduleCount; + +struct IncompatibleTypeException +{ + ::rtl::OUString m_cause; + IncompatibleTypeException( ::rtl::OUString const & cause ) + : m_cause( cause ) {} +}; + +void check( + css::uno::Reference<css::reflection::XTypeDescription> const & xNewTD, + css::uno::Reference<css::reflection::XTypeDescription> const & xExistingTD, + ::rtl::OUString const & context = ::rtl::OUString() ); +/* throw (css::uno::RuntimeException, IncompatibleTypeException) */ + +} // namespace stoc_tdmgr + +#endif /* _STOC_TDMGR_COMMON_HXX */ diff --git a/stoc/source/tdmanager/tdmgr_tdenumeration.cxx b/stoc/source/tdmanager/tdmgr_tdenumeration.cxx new file mode 100644 index 000000000000..c1815c932db5 --- /dev/null +++ b/stoc/source/tdmanager/tdmgr_tdenumeration.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/diagnose.h> +#include "tdmgr_common.hxx" +#include "tdmgr_tdenumeration.hxx" + +using namespace com::sun::star; + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_tdmgr +{ + +//========================================================================= +//========================================================================= +// +// TypeDescriptionEnumerationImpl Implementation. +// +//========================================================================= +//========================================================================= + +TypeDescriptionEnumerationImpl::TypeDescriptionEnumerationImpl( + const rtl::OUString & rModuleName, + const com::sun::star::uno::Sequence< + com::sun::star::uno::TypeClass > & rTypes, + com::sun::star::reflection::TypeDescriptionSearchDepth eDepth, + const TDEnumerationAccessStack & rTDEAS ) +: m_aModuleName( rModuleName ), + m_aTypes( rTypes ), + m_eDepth( eDepth ), + m_aChildren( rTDEAS ) +{ + ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt ); +} + +//========================================================================= +// virtual +TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl() +{ + ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt ); +} + +//========================================================================= +// +// XEnumeration (base of XTypeDescriptionEnumeration) methods +// +//========================================================================= + +// virtual +sal_Bool SAL_CALL TypeDescriptionEnumerationImpl::hasMoreElements() + throw ( uno::RuntimeException ) +{ + uno::Reference< reflection::XTypeDescriptionEnumeration > xEnum + = queryCurrentChildEnumeration(); + if ( xEnum.is() ) + return xEnum->hasMoreElements(); + + return sal_False; +} + +//========================================================================= +// virtual +uno::Any SAL_CALL TypeDescriptionEnumerationImpl::nextElement() + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< reflection::XTypeDescriptionEnumeration > xEnum + = queryCurrentChildEnumeration(); + if ( xEnum.is() ) + return xEnum->nextElement(); + + throw container::NoSuchElementException( + rtl::OUString::createFromAscii( + "No further elements in enumeration!" ), + static_cast< cppu::OWeakObject * >( this ) ); +} + +//========================================================================= +// +// XTypeDescriptionEnumeration methods +// +//========================================================================= + +// virtual +uno::Reference< reflection::XTypeDescription > SAL_CALL +TypeDescriptionEnumerationImpl::nextTypeDescription() + throw ( container::NoSuchElementException, + uno::RuntimeException ) +{ + uno::Reference< reflection::XTypeDescriptionEnumeration > xEnum + = queryCurrentChildEnumeration(); + if ( xEnum.is() ) + return xEnum->nextTypeDescription(); + + throw container::NoSuchElementException( + rtl::OUString::createFromAscii( + "No further elements in enumeration!" ), + static_cast< cppu::OWeakObject * >( this ) ); +} + +//========================================================================= +uno::Reference< reflection::XTypeDescriptionEnumeration > +TypeDescriptionEnumerationImpl::queryCurrentChildEnumeration() +{ + osl::MutexGuard aGuard( m_aMutex ); + + for (;;) + { + if ( m_xEnum.is() ) + { + if ( m_xEnum->hasMoreElements() ) + { + return m_xEnum; + } + else + { + // Forget about enumeration without further elements. Try next. + m_xEnum.clear(); + } + } + + // Note: m_xEnum is always null here. + + if ( m_aChildren.empty() ) + { + // No child enumerations left. + return m_xEnum; + } + + try + { + m_xEnum = + m_aChildren.top()->createTypeDescriptionEnumeration( + m_aModuleName, m_aTypes, m_eDepth ); + } + catch ( reflection::NoSuchTypeNameException const & ) + { + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryCurrentChildEnumeration " + "- Caught NoSuchTypeNameException!" ); + } + catch ( reflection::InvalidTypeNameException const & ) + { + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryCurrentChildEnumeration " + "- Caught InvalidTypeNameException!" ); + } + + // We're done with this enumeration access in any case (Either + // enumeration was successfully created or creation failed for some + // reason). + m_aChildren.pop(); + } + + // unreachable +} + +} // namespace stoc_tdmgr + diff --git a/stoc/source/tdmanager/tdmgr_tdenumeration.hxx b/stoc/source/tdmanager/tdmgr_tdenumeration.hxx new file mode 100644 index 000000000000..1b383af538c1 --- /dev/null +++ b/stoc/source/tdmanager/tdmgr_tdenumeration.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STOC_TDMGR_TDENUMERATION_HXX +#define _STOC_TDMGR_TDENUMERATION_HXX + +#include <stack> +#include <osl/mutex.hxx> +#include <com/sun/star/reflection/XTypeDescriptionEnumeration.hpp> +#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> +#include <cppuhelper/implbase1.hxx> + +namespace stoc_tdmgr +{ + +typedef std::stack< com::sun::star::uno::Reference< + com::sun::star::reflection::XTypeDescriptionEnumerationAccess > > + TDEnumerationAccessStack; + +class TypeDescriptionEnumerationImpl + : public cppu::WeakImplHelper1< + com::sun::star::reflection::XTypeDescriptionEnumeration > +{ +public: + TypeDescriptionEnumerationImpl( + const rtl::OUString & rModuleName, + const com::sun::star::uno::Sequence< + com::sun::star::uno::TypeClass > & rTypes, + com::sun::star::reflection::TypeDescriptionSearchDepth eDepth, + const TDEnumerationAccessStack & rTDEAS ); + virtual ~TypeDescriptionEnumerationImpl(); + + // XEnumeration (base of XTypeDescriptionEnumeration) + virtual sal_Bool SAL_CALL hasMoreElements() + throw ( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Any SAL_CALL nextElement() + throw ( ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException ); + + // XTypeDescriptionEnumeration + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XTypeDescription > SAL_CALL + nextTypeDescription() + throw ( ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException ); + +private: + com::sun::star::uno::Reference< + com::sun::star::reflection::XTypeDescriptionEnumeration > + queryCurrentChildEnumeration(); + + osl::Mutex m_aMutex; + rtl::OUString m_aModuleName; + com::sun::star::uno::Sequence< com::sun::star::uno::TypeClass > m_aTypes; + com::sun::star::reflection::TypeDescriptionSearchDepth m_eDepth; + TDEnumerationAccessStack m_aChildren; + com::sun::star::uno::Reference< + com::sun::star::reflection::XTypeDescriptionEnumeration > m_xEnum; +}; + +} // namespace stoc_tdmgr + +#endif /* _STOC_TDMGR_TDENUMERATION_HXX */ + |