diff options
Diffstat (limited to 'stoc/source/registry_tdprovider/tdprovider.cxx')
-rw-r--r-- | stoc/source/registry_tdprovider/tdprovider.cxx | 632 |
1 files changed, 632 insertions, 0 deletions
diff --git a/stoc/source/registry_tdprovider/tdprovider.cxx b/stoc/source/registry_tdprovider/tdprovider.cxx new file mode 100644 index 000000000000..1d62657beba9 --- /dev/null +++ b/stoc/source/registry_tdprovider/tdprovider.cxx @@ -0,0 +1,632 @@ +/************************************************************************* + * + * 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 <uno/dispatcher.h> +#include <uno/mapping.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/compbase4.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include <cppuhelper/weakref.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> +#include "com/sun/star/uno/RuntimeException.hpp" + +#include "registry/reader.hxx" +#include "registry/version.h" +#include "base.hxx" +#include "rdbtdp_tdenumeration.hxx" +#include "structtypedescription.hxx" + +#define SERVICENAME "com.sun.star.reflection.TypeDescriptionProvider" +#define IMPLNAME "com.sun.star.comp.stoc.RegistryTypeDescriptionProvider" + +using namespace com::sun::star; +using namespace com::sun::star::beans; +using namespace com::sun::star::registry; + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_bootstrap +{ +uno::Sequence< OUString > rdbtdp_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 rdbtdp_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_rdbtdp +{ +struct MutexHolder +{ + Mutex _aComponentMutex; +}; +//================================================================================================== +class ProviderImpl + : public MutexHolder + , public WeakComponentImplHelper4< XServiceInfo, + XHierarchicalNameAccess, + XTypeDescriptionEnumerationAccess, + XInitialization > +{ + // XHierarchicalNameAccess + XTypeDescriptionEnumerationAccess wrapper + // first asking the tdmgr instance, then looking up locally + class TypeDescriptionManagerWrapper + : public ::cppu::WeakImplHelper2< + container::XHierarchicalNameAccess, + reflection::XTypeDescriptionEnumerationAccess> + { + com::sun::star::uno::Reference<container::XHierarchicalNameAccess> + m_xTDMgr; + com::sun::star::uno::Reference<container::XHierarchicalNameAccess> + m_xThisProvider; + public: + TypeDescriptionManagerWrapper( ProviderImpl * pProvider ) + : m_xTDMgr( pProvider->_xContext->getValueByName( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.reflection." + "theTypeDescriptionManager") ) ), + UNO_QUERY_THROW ), + m_xThisProvider( pProvider ) + {} + // XHierarchicalNameAccess + virtual Any SAL_CALL getByHierarchicalName( OUString const & name ) + throw (container::NoSuchElementException, RuntimeException); + virtual sal_Bool SAL_CALL hasByHierarchicalName( OUString const & name ) + throw (RuntimeException); + + // XTypeDescriptionEnumerationAccess + virtual uno::Reference< + reflection::XTypeDescriptionEnumeration > SAL_CALL + createTypeDescriptionEnumeration( + const ::rtl::OUString& moduleName, + const uno::Sequence< uno::TypeClass >& types, + reflection::TypeDescriptionSearchDepth depth ) + throw ( reflection::NoSuchTypeNameException, + reflection::InvalidTypeNameException, + uno::RuntimeException ); + }; + friend class TypeDescriptionManagerWrapper; + + com::sun::star::uno::Reference< XComponentContext > _xContext; + com::sun::star::uno::WeakReference<XHierarchicalNameAccess> _xTDMgr; + com::sun::star::uno::Reference< XHierarchicalNameAccess > getTDMgr() SAL_THROW( () ); + + RegistryKeyList _aBaseKeys; + +protected: + virtual void SAL_CALL disposing(); + +public: + ProviderImpl( const com::sun::star::uno::Reference< XComponentContext > & xContext ); + virtual ~ProviderImpl(); + + // 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); + + // 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 ); +}; +//__________________________________________________________________________________________________ +ProviderImpl::ProviderImpl( const com::sun::star::uno::Reference< XComponentContext > & xContext ) + : WeakComponentImplHelper4< + XServiceInfo, XHierarchicalNameAccess, + XTypeDescriptionEnumerationAccess, XInitialization >( _aComponentMutex ) + , _xContext( xContext ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +ProviderImpl::~ProviderImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +//______________________________________________________________________________ +Any ProviderImpl::TypeDescriptionManagerWrapper::getByHierarchicalName( + OUString const & name ) throw (container::NoSuchElementException, + RuntimeException) +{ + try + { + // first try tdmgr: + return m_xTDMgr->getByHierarchicalName( name ); + } + catch (container::NoSuchElementException &) + { + // then lookup locally: + return m_xThisProvider->getByHierarchicalName( name ); + } +} + +//______________________________________________________________________________ +sal_Bool ProviderImpl::TypeDescriptionManagerWrapper::hasByHierarchicalName( + OUString const & name ) throw (RuntimeException) +{ + try + { + return getByHierarchicalName( name ).hasValue(); + } + catch (container::NoSuchElementException &) + { + return false; + } +} + +//______________________________________________________________________________ +uno::Reference< reflection::XTypeDescriptionEnumeration > SAL_CALL +ProviderImpl::TypeDescriptionManagerWrapper::createTypeDescriptionEnumeration( + const ::rtl::OUString& moduleName, + const uno::Sequence< uno::TypeClass >& types, + reflection::TypeDescriptionSearchDepth depth ) + throw ( reflection::NoSuchTypeNameException, + reflection::InvalidTypeNameException, + uno::RuntimeException ) +{ + try + { + // first try tdmgr: + uno::Reference< reflection::XTypeDescriptionEnumerationAccess > xTDEA( + m_xTDMgr, uno::UNO_QUERY_THROW ); + return + xTDEA->createTypeDescriptionEnumeration( moduleName, types, depth ); + } + catch (reflection::NoSuchTypeNameException &) + { + // then lookup locally: + uno::Reference< reflection::XTypeDescriptionEnumerationAccess > xTDEA( + m_xThisProvider, uno::UNO_QUERY_THROW ); + return + xTDEA->createTypeDescriptionEnumeration( moduleName, types, depth ); + } +} + +//__________________________________________________________________________________________________ +com::sun::star::uno::Reference< XHierarchicalNameAccess > ProviderImpl::getTDMgr() + SAL_THROW( () ) +{ + // harden weak reference: + com::sun::star::uno::Reference<container::XHierarchicalNameAccess> xTDMgr( + _xTDMgr ); + if (! xTDMgr.is()) + { + xTDMgr.set( new TypeDescriptionManagerWrapper(this) ); + { + MutexGuard guard( _aComponentMutex ); + _xTDMgr = xTDMgr; + } + } + return xTDMgr; +} + +//__________________________________________________________________________________________________ +void ProviderImpl::disposing() +{ + _xContext.clear(); + + for ( RegistryKeyList::const_iterator iPos( _aBaseKeys.begin() ); + iPos != _aBaseKeys.end(); ++iPos ) + { + (*iPos)->closeKey(); + } + _aBaseKeys.clear(); +} + +// XInitialization +//__________________________________________________________________________________________________ +void ProviderImpl::initialize( + const Sequence< Any > & args ) + throw (Exception, RuntimeException) +{ + // registries to read from + Any const * pRegistries = args.getConstArray(); + for ( sal_Int32 nPos = 0; nPos < args.getLength(); ++nPos ) + { + com::sun::star::uno::Reference< XSimpleRegistry > xRegistry( pRegistries[ nPos ], UNO_QUERY ); + if (xRegistry.is() && xRegistry->isValid()) + { + com::sun::star::uno::Reference< XRegistryKey > xKey( xRegistry->getRootKey()->openKey( + OUString( RTL_CONSTASCII_USTRINGPARAM("/UCR") ) ) ); + if (xKey.is() && xKey->isValid()) + { + _aBaseKeys.push_back( xKey ); + } + } + } +} + +// XServiceInfo +//__________________________________________________________________________________________________ +OUString ProviderImpl::getImplementationName() + throw(::com::sun::star::uno::RuntimeException) +{ + return stoc_bootstrap::rdbtdp_getImplementationName(); +} +//__________________________________________________________________________________________________ +sal_Bool ProviderImpl::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 > ProviderImpl::getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + return stoc_bootstrap::rdbtdp_getSupportedServiceNames(); +} + +// XHierarchicalNameAccess +//__________________________________________________________________________________________________ +Any SAL_CALL ProviderImpl::getByHierarchicalName( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException, com::sun::star::container::NoSuchElementException) +{ + Any aRet; + + // read from registry + OUString aKey( rName.replace( '.', '/' ) ); + for ( RegistryKeyList::const_iterator iPos( _aBaseKeys.begin() ); + !aRet.hasValue() && iPos != _aBaseKeys.end(); ++iPos ) + { + try + { + com::sun::star::uno::Reference< XRegistryKey > xBaseKey( *iPos ); + com::sun::star::uno::Reference< XRegistryKey > xKey( xBaseKey->openKey( aKey ) ); + if (xKey.is()) + { + // closes key in it's dtor (which is + // called even in case of exceptions). + RegistryKeyCloser aCloser( xKey ); + + if ( xKey->isValid() ) + { + if (xKey->getValueType() == RegistryValueType_BINARY) + { + Sequence< sal_Int8 > aBytes( xKey->getBinaryValue() ); + com::sun::star::uno::Reference< XTypeDescription > xTD( + createTypeDescription( aBytes, + getTDMgr(), + true ) ); + if ( xTD.is() ) + aRet <<= xTD; + } + } + } + else // might be a constant + { + sal_Int32 nIndex = aKey.lastIndexOf( '/' ); + if (nIndex > 0) + { + // open module + com::sun::star::uno::Reference< XRegistryKey > xKey2( xBaseKey->openKey( aKey.copy( 0, nIndex ) ) ); + if (xKey2.is()) + { + // closes key in it's dtor (which is + // called even in case of exceptions). + RegistryKeyCloser aCloser( xKey2 ); + + if ( xKey2->isValid() ) + { + if (xKey2->getValueType() == RegistryValueType_BINARY) + { + Sequence< sal_Int8 > aBytes( xKey2->getBinaryValue() ); + typereg::Reader aReader( + aBytes.getConstArray(), aBytes.getLength(), + false, TYPEREG_VERSION_1); + + if (aReader.getTypeClass() == RT_TYPE_MODULE || + aReader.getTypeClass() == RT_TYPE_CONSTANTS || + aReader.getTypeClass() == RT_TYPE_ENUM) + { + OUString aFieldName( aKey.copy( nIndex+1, aKey.getLength() - nIndex -1 ) ); + sal_Int16 nPos = aReader.getFieldCount(); + while (nPos--) + { + if (aFieldName.equals( + aReader.getFieldName(nPos))) + break; + } + if (nPos >= 0) + aRet = getRTValue( + aReader.getFieldValue(nPos)); + } + } + } + } + } + } + } + catch ( InvalidRegistryException const & ) + { + OSL_ENSURE( sal_False, + "ProviderImpl::getByHierarchicalName " + "- Caught InvalidRegistryException!" ); + + // openKey, closeKey, getValueType, getBinaryValue, isValid + + // Don't stop iteration in this case. + } + } + + if ( !aRet.hasValue() ) + throw NoSuchElementException( + rName, static_cast< cppu::OWeakObject * >( this ) ); + + return aRet; +} + +//__________________________________________________________________________________________________ +sal_Bool ProviderImpl::hasByHierarchicalName( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException) +{ + try + { + return getByHierarchicalName( rName ).hasValue(); + } + catch (NoSuchElementException &) + { + } + return sal_False; +} + +// XTypeDescriptionEnumerationAccess +//__________________________________________________________________________________________________ +// virtual +com::sun::star::uno::Reference< XTypeDescriptionEnumeration > SAL_CALL +ProviderImpl::createTypeDescriptionEnumeration( + const OUString & moduleName, + const Sequence< TypeClass > & types, + TypeDescriptionSearchDepth depth ) + throw ( NoSuchTypeNameException, + InvalidTypeNameException, + RuntimeException ) +{ + return com::sun::star::uno::Reference< XTypeDescriptionEnumeration >( + TypeDescriptionEnumerationImpl::createInstance( getTDMgr(), + moduleName, + types, + depth, + _aBaseKeys ).get() ); +} + +//__________________________________________________________________________________________________ +// global helper function + +com::sun::star::uno::Reference< XTypeDescription > resolveTypedefs( + com::sun::star::uno::Reference< XTypeDescription > const & type) +{ + com::sun::star::uno::Reference< XTypeDescription > resolved(type); + while (resolved->getTypeClass() == TypeClass_TYPEDEF) { + resolved = com::sun::star::uno::Reference< XIndirectTypeDescription >( + resolved, UNO_QUERY_THROW)->getReferencedType(); + } + return resolved; +} + +com::sun::star::uno::Reference< XTypeDescription > createTypeDescription( + const Sequence< sal_Int8 > & rData, + const com::sun::star::uno::Reference< XHierarchicalNameAccess > & xNameAccess, + bool bReturnEmptyRefForUnknownType ) +{ + typereg::Reader aReader( + rData.getConstArray(), rData.getLength(), false, TYPEREG_VERSION_1); + + OUString aName( aReader.getTypeName().replace( '/', '.' ) ); + + switch (aReader.getTypeClass()) + { + case RT_TYPE_INTERFACE: + { + sal_uInt16 n = aReader.getSuperTypeCount(); + com::sun::star::uno::Sequence< rtl::OUString > aBaseTypeNames(n); + {for (sal_uInt16 i = 0; i < n; ++i) { + aBaseTypeNames[i] = aReader.getSuperTypeName(i).replace( + '/', '.'); + }} + sal_uInt16 n2 = aReader.getReferenceCount(); + com::sun::star::uno::Sequence< rtl::OUString > + aOptionalBaseTypeNames(n2); + {for (sal_uInt16 i = 0; i < n2; ++i) { + OSL_ASSERT( + aReader.getReferenceSort(i) == RT_REF_SUPPORTS + && aReader.getReferenceFlags(i) == RT_ACCESS_OPTIONAL); + aOptionalBaseTypeNames[i] = aReader.getReferenceTypeName(i); + }} + return com::sun::star::uno::Reference< XTypeDescription >( + new InterfaceTypeDescriptionImpl( xNameAccess, + aName, + aBaseTypeNames, + aOptionalBaseTypeNames, + rData, + aReader.isPublished() ) ); + } + + case RT_TYPE_MODULE: + { + com::sun::star::uno::Reference< + XTypeDescriptionEnumerationAccess > xTDEA( + xNameAccess, UNO_QUERY ); + + OSL_ENSURE( xTDEA.is(), + "No XTypeDescriptionEnumerationAccess!" ); + + return com::sun::star::uno::Reference< XTypeDescription >( + new ModuleTypeDescriptionImpl( xTDEA, aName ) ); + } + + case RT_TYPE_STRUCT: + { + rtl::OUString superTypeName; + if (aReader.getSuperTypeCount() == 1) { + superTypeName = aReader.getSuperTypeName(0).replace( + '/', '.'); + } + return com::sun::star::uno::Reference< XTypeDescription >( + new stoc::registry_tdprovider::StructTypeDescription( + xNameAccess, aName, superTypeName, rData, + aReader.isPublished())); + } + + case RT_TYPE_ENUM: + return com::sun::star::uno::Reference< XTypeDescription >( + new EnumTypeDescriptionImpl( xNameAccess, + aName, + getRTValueAsInt32( + aReader.getFieldValue( 0 ) ), + rData, aReader.isPublished() ) ); + + case RT_TYPE_EXCEPTION: + { + rtl::OUString superTypeName; + if (aReader.getSuperTypeCount() == 1) { + superTypeName = aReader.getSuperTypeName(0).replace( + '/', '.'); + } + return com::sun::star::uno::Reference< XTypeDescription >( + new CompoundTypeDescriptionImpl( + xNameAccess, TypeClass_EXCEPTION, aName, superTypeName, + rData, aReader.isPublished())); + } + + case RT_TYPE_TYPEDEF: + return com::sun::star::uno::Reference< XTypeDescription >( + new TypedefTypeDescriptionImpl( xNameAccess, + aName, + aReader.getSuperTypeName(0) + .replace( '/', '.' ), + aReader.isPublished() ) ); + case RT_TYPE_SERVICE: + return com::sun::star::uno::Reference< XTypeDescription >( + new ServiceTypeDescriptionImpl( + xNameAccess, aName, rData, aReader.isPublished() ) ); + + case RT_TYPE_CONSTANTS: + return com::sun::star::uno::Reference< XTypeDescription >( + new ConstantsTypeDescriptionImpl( + aName, rData, aReader.isPublished() ) ); + + case RT_TYPE_SINGLETON: + return com::sun::star::uno::Reference< XTypeDescription >( + new SingletonTypeDescriptionImpl( xNameAccess, + aName, + aReader.getSuperTypeName(0) + .replace( '/', '.' ), + aReader.isPublished() ) ); + case RT_TYPE_INVALID: + case RT_TYPE_OBJECT: // deprecated and not used + case RT_TYPE_UNION: // deprecated and not used + OSL_ENSURE( sal_False, "createTypeDescription - Unsupported Type!" ); + break; + + default: + OSL_ENSURE( sal_False, "createTypeDescription - Unknown Type!" ); + break; + } + + // Unknown type. + + if ( bReturnEmptyRefForUnknownType ) + return com::sun::star::uno::Reference< XTypeDescription >(); + + return com::sun::star::uno::Reference< XTypeDescription >( + new TypeDescriptionImpl( TypeClass_UNKNOWN, aName ) ); +} + +} + +namespace stoc_bootstrap +{ +//================================================================================================== +com::sun::star::uno::Reference< XInterface > SAL_CALL ProviderImpl_create( + com::sun::star::uno::Reference< XComponentContext > const & xContext ) + throw(::com::sun::star::uno::Exception) +{ + return com::sun::star::uno::Reference< XInterface >( *new stoc_rdbtdp::ProviderImpl( xContext ) ); +} +} |