| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_stoc.hxx" |
| |
| //========================================================================= |
| // Todo: |
| // |
| // - closeKey() calls (according to JSC not really needed because XRegistry |
| // implementation closes key in it's dtor. |
| // |
| //========================================================================= |
| #include <osl/diagnose.h> |
| #include <rtl/ustrbuf.hxx> |
| #include "com/sun/star/reflection/XPublished.hpp" |
| #include "cppuhelper/implbase1.hxx" |
| #include "registry/reader.hxx" |
| #include "registry/version.h" |
| #include "base.hxx" |
| #include "rdbtdp_tdenumeration.hxx" |
| |
| using namespace com::sun::star; |
| |
| namespace { |
| |
| class IndividualConstantTypeDescriptionImpl: |
| public cppu::ImplInheritanceHelper1< |
| stoc_rdbtdp::ConstantTypeDescriptionImpl, |
| com::sun::star::reflection::XPublished > |
| { |
| public: |
| IndividualConstantTypeDescriptionImpl( |
| rtl::OUString const & name, com::sun::star::uno::Any const & value, |
| bool published): |
| cppu::ImplInheritanceHelper1< |
| stoc_rdbtdp::ConstantTypeDescriptionImpl, |
| com::sun::star::reflection::XPublished >(name, value), |
| m_published(published) {} |
| |
| virtual sal_Bool SAL_CALL isPublished() |
| throw (::com::sun::star::uno::RuntimeException) |
| { return m_published; } |
| |
| private: |
| bool m_published; |
| }; |
| |
| } |
| |
| namespace stoc_rdbtdp |
| { |
| |
| //========================================================================= |
| //========================================================================= |
| // |
| // TypeDescriptionEnumerationImpl Implementation. |
| // |
| //========================================================================= |
| //========================================================================= |
| |
| // static |
| rtl::Reference< TypeDescriptionEnumerationImpl > |
| TypeDescriptionEnumerationImpl::createInstance( |
| const uno::Reference< container::XHierarchicalNameAccess > & xTDMgr, |
| const rtl::OUString & rModuleName, |
| const uno::Sequence< uno::TypeClass > & rTypes, |
| reflection::TypeDescriptionSearchDepth eDepth, |
| const RegistryKeyList & rBaseKeys ) |
| throw ( reflection::NoSuchTypeNameException, |
| reflection::InvalidTypeNameException, |
| uno::RuntimeException ) |
| { |
| if ( rModuleName.getLength() == 0 ) |
| { |
| // Enumeration for root requested. |
| return rtl::Reference< TypeDescriptionEnumerationImpl >( |
| new TypeDescriptionEnumerationImpl( |
| xTDMgr, rBaseKeys, rTypes, eDepth ) ); |
| } |
| |
| RegistryKeyList aModuleKeys; |
| |
| rtl::OUString aKey( rModuleName.replace( '.', '/' ) ); |
| |
| bool bOpenKeySucceeded = false; |
| |
| const RegistryKeyList::const_iterator end = rBaseKeys.end(); |
| RegistryKeyList::const_iterator it = rBaseKeys.begin(); |
| |
| while ( it != end ) |
| { |
| uno::Reference< registry::XRegistryKey > xKey; |
| try |
| { |
| xKey = (*it)->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() ) |
| { |
| bOpenKeySucceeded = true; |
| |
| if ( xKey->getValueType() |
| == registry::RegistryValueType_BINARY ) |
| { |
| uno::Sequence< sal_Int8 > aBytes( |
| xKey->getBinaryValue() ); |
| |
| typereg::Reader aReader( |
| aBytes.getConstArray(), aBytes.getLength(), false, |
| TYPEREG_VERSION_1); |
| |
| rtl::OUString aName( |
| aReader.getTypeName().replace( '/', '.' ) ); |
| |
| if ( aReader.getTypeClass() == RT_TYPE_MODULE ) |
| { |
| // Do not close xKey! |
| aCloser.reset(); |
| |
| aModuleKeys.push_back( xKey ); |
| } |
| } |
| } |
| else |
| { |
| OSL_ENSURE( |
| sal_False, |
| "TypeDescriptionEnumerationImpl::createInstance " |
| "- Invalid registry key!" ); |
| } |
| } |
| } |
| catch ( registry::InvalidRegistryException const & ) |
| { |
| // openKey, getValueType, getBinaryValue |
| |
| OSL_ENSURE( sal_False, |
| "TypeDescriptionEnumerationImpl::createInstance " |
| "- Caught InvalidRegistryException!" ); |
| } |
| |
| it++; |
| } |
| |
| if ( !bOpenKeySucceeded ) |
| throw reflection::NoSuchTypeNameException(); |
| |
| if ( aModuleKeys.size() == 0 ) |
| throw reflection::InvalidTypeNameException(); |
| |
| return rtl::Reference< TypeDescriptionEnumerationImpl >( |
| new TypeDescriptionEnumerationImpl( |
| xTDMgr, aModuleKeys, rTypes, eDepth ) ); |
| } |
| |
| //========================================================================= |
| TypeDescriptionEnumerationImpl::TypeDescriptionEnumerationImpl( |
| const uno::Reference< container::XHierarchicalNameAccess > & xTDMgr, |
| const RegistryKeyList & rModuleKeys, |
| const uno::Sequence< uno::TypeClass > & rTypes, |
| reflection::TypeDescriptionSearchDepth eDepth ) |
| : m_aModuleKeys( rModuleKeys ), |
| m_aTypes( rTypes ), |
| m_eDepth( eDepth ), |
| m_xTDMgr( xTDMgr ) |
| { |
| g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); |
| } |
| |
| //========================================================================= |
| // virtual |
| TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl() |
| { |
| RegistryKeyList::const_iterator it = m_aModuleKeys.begin(); |
| RegistryKeyList::const_iterator end = m_aModuleKeys.end(); |
| /* |
| @@@ in case we enumerate root and queryMore was never called, then |
| m_aModuleKeys contains open root keys which where passed from |
| tdprov and must not be closed by us. |
| |
| while ( it != end ) |
| { |
| try |
| { |
| if ( (*it)->isValid() ) |
| (*it)->closeKey(); |
| } |
| catch (...) |
| { |
| // No exceptions from dtors, please! |
| OSL_ENSURE( sal_False, |
| "TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl " |
| "- Caught exception!" ); |
| } |
| |
| it++; |
| } |
| */ |
| it = m_aCurrentModuleSubKeys.begin(); |
| end = m_aCurrentModuleSubKeys.end(); |
| while ( it != end ) |
| { |
| try |
| { |
| if ( (*it)->isValid() ) |
| (*it)->closeKey(); |
| } |
| catch (Exception &) |
| { |
| // No exceptions from dtors, please! |
| OSL_ENSURE( sal_False, |
| "TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl " |
| "- Caught exception!" ); |
| } |
| |
| it++; |
| } |
| |
| g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); |
| } |
| |
| //========================================================================= |
| // |
| // XEnumeration (base of XTypeDescriptionEnumeration) methods |
| // |
| //========================================================================= |
| |
| // virtual |
| sal_Bool SAL_CALL TypeDescriptionEnumerationImpl::hasMoreElements() |
| throw ( uno::RuntimeException ) |
| { |
| return queryMore(); |
| } |
| |
| //========================================================================= |
| // virtual |
| uno::Any SAL_CALL TypeDescriptionEnumerationImpl::nextElement() |
| throw ( container::NoSuchElementException, |
| lang::WrappedTargetException, |
| uno::RuntimeException ) |
| { |
| return uno::Any( uno::makeAny( nextTypeDescription() ) ); |
| } |
| |
| //========================================================================= |
| // |
| // XTypeDescriptionEnumeration methods |
| // |
| //========================================================================= |
| |
| // virtual |
| uno::Reference< reflection::XTypeDescription > SAL_CALL |
| TypeDescriptionEnumerationImpl::nextTypeDescription() |
| throw ( container::NoSuchElementException, |
| uno::RuntimeException ) |
| { |
| uno::Reference< reflection::XTypeDescription > xTD( queryNext() ); |
| |
| if ( xTD.is() ) |
| return xTD; |
| |
| throw container::NoSuchElementException( |
| rtl::OUString::createFromAscii( |
| "No further elements in enumeration!" ), |
| static_cast< cppu::OWeakObject * >( this ) ); |
| } |
| |
| //========================================================================= |
| bool TypeDescriptionEnumerationImpl::match( |
| RTTypeClass eType1, uno::TypeClass eType2 ) |
| { |
| switch ( eType1 ) |
| { |
| case RT_TYPE_INTERFACE: |
| return eType2 == uno::TypeClass_INTERFACE; |
| |
| case RT_TYPE_MODULE: |
| return eType2 == uno::TypeClass_MODULE; |
| |
| case RT_TYPE_STRUCT: |
| return eType2 == uno::TypeClass_STRUCT; |
| |
| case RT_TYPE_ENUM: |
| return eType2 == uno::TypeClass_ENUM; |
| |
| case RT_TYPE_EXCEPTION: |
| return eType2 == uno::TypeClass_EXCEPTION; |
| |
| case RT_TYPE_TYPEDEF: |
| return eType2 == uno::TypeClass_TYPEDEF; |
| |
| case RT_TYPE_SERVICE: |
| return eType2 == uno::TypeClass_SERVICE; |
| |
| case RT_TYPE_SINGLETON: |
| return eType2 == uno::TypeClass_SINGLETON; |
| |
| case RT_TYPE_CONSTANTS: |
| return eType2 == uno::TypeClass_CONSTANTS; |
| |
| case RT_TYPE_UNION: |
| return eType2 == uno::TypeClass_UNION; |
| |
| default: |
| return false; |
| } |
| } |
| |
| //========================================================================= |
| bool TypeDescriptionEnumerationImpl::queryMore() |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| for (;;) |
| { |
| if ( !m_aCurrentModuleSubKeys.empty() || !m_aTypeDescs.empty() ) |
| { |
| // Okay, there is at least one more element. |
| return true; |
| } |
| |
| if ( m_aModuleKeys.empty() ) |
| { |
| // No module keys (therefore no elements) left. |
| return false; |
| } |
| |
| // Note: m_aCurrentModuleSubKeys is always empty AND m_aModuleKeys is |
| // never empty when ariving here. |
| // ==> select new module key, fill m_aCurrentModuleSubKeys |
| |
| uno::Sequence< uno::Reference< registry::XRegistryKey > > aKeys; |
| try |
| { |
| aKeys = m_aModuleKeys.front()->openKeys(); |
| for ( sal_Int32 n = 0; n < aKeys.getLength(); ++n ) |
| { |
| uno::Reference< registry::XRegistryKey > xKey = aKeys[ n ]; |
| |
| // closes key in it's dtor (which is |
| // called even in case of exceptions). |
| RegistryKeyCloser aCloser( xKey ); |
| |
| try |
| { |
| if ( xKey->isValid() ) |
| { |
| if ( xKey->getValueType() |
| == registry::RegistryValueType_BINARY ) |
| { |
| bool bIncludeIt = (m_aTypes.getLength() == 0); |
| bool bNeedTypeClass = |
| ((m_aTypes.getLength() > 0) || |
| (m_eDepth |
| == reflection::TypeDescriptionSearchDepth_INFINITE)); |
| if ( bNeedTypeClass ) |
| { |
| uno::Sequence< sal_Int8 > aBytes( |
| xKey->getBinaryValue() ); |
| |
| typereg::Reader aReader( |
| aBytes.getConstArray(), aBytes.getLength(), |
| false, TYPEREG_VERSION_1); |
| |
| RTTypeClass eTypeClass = aReader.getTypeClass(); |
| |
| // Does key match requested types? Empty |
| // sequence means include all. |
| if ( m_aTypes.getLength() > 0 ) |
| { |
| for ( sal_Int32 m = 0; |
| m < m_aTypes.getLength(); |
| ++m ) |
| { |
| if ( match(eTypeClass, m_aTypes[ m ]) ) |
| { |
| bIncludeIt = true; |
| break; |
| } |
| } |
| } |
| |
| if ( m_eDepth == |
| reflection::TypeDescriptionSearchDepth_INFINITE ) |
| { |
| if ( eTypeClass == RT_TYPE_MODULE ) |
| { |
| // Do not close xKey! |
| aCloser.reset(); |
| |
| // Remember new module key. |
| m_aModuleKeys.push_back( xKey ); |
| } |
| } |
| } |
| |
| if ( bIncludeIt ) |
| { |
| // Do not close xKey! |
| aCloser.reset(); |
| |
| m_aCurrentModuleSubKeys.push_back( xKey ); |
| } |
| } |
| } |
| else |
| { |
| OSL_ENSURE( sal_False, |
| "TypeDescriptionEnumerationImpl::queryMore " |
| "- Invalid registry key!" ); |
| } |
| |
| } |
| catch ( registry::InvalidRegistryException const & ) |
| { |
| // getValueType, getBinaryValue |
| |
| OSL_ENSURE( sal_False, |
| "TypeDescriptionEnumerationImpl::queryMore " |
| "- Caught InvalidRegistryException!" ); |
| |
| // Don't stop iterating! |
| } |
| } |
| } |
| catch ( registry::InvalidRegistryException const & ) |
| { |
| // openKeys |
| |
| for ( sal_Int32 n = 0; n < aKeys.getLength(); ++n ) |
| { |
| try |
| { |
| aKeys[ n ]->closeKey(); |
| } |
| catch ( registry::InvalidRegistryException const & ) |
| { |
| OSL_ENSURE( sal_False, |
| "TypeDescriptionEnumerationImpl::queryMore " |
| "- Caught InvalidRegistryException!" ); |
| } |
| } |
| } |
| |
| ///////////////////////////////////////////////////////////////////// |
| // Special handling for constants contained directly in module. |
| ///////////////////////////////////////////////////////////////////// |
| |
| // Constants requested? |
| bool bIncludeConstants = ( m_aTypes.getLength() == 0 ); |
| if ( !bIncludeConstants ) |
| { |
| for ( sal_Int32 m = 0; m < m_aTypes.getLength(); ++m ) |
| { |
| if ( m_aTypes[ m ] == uno::TypeClass_CONSTANT ) |
| { |
| bIncludeConstants = true; |
| break; |
| } |
| } |
| |
| } |
| |
| if ( bIncludeConstants ) |
| { |
| if ( m_aModuleKeys.front()->getValueType() |
| == registry::RegistryValueType_BINARY ) |
| { |
| try |
| { |
| uno::Sequence< sal_Int8 > aBytes( |
| m_aModuleKeys.front()->getBinaryValue() ); |
| |
| typereg::Reader aReader( |
| aBytes.getConstArray(), aBytes.getLength(), false, |
| TYPEREG_VERSION_1); |
| |
| if ( aReader.getTypeClass() == RT_TYPE_MODULE ) |
| { |
| sal_uInt16 nFields = aReader.getFieldCount(); |
| while ( nFields-- ) |
| { |
| rtl::OUStringBuffer aName( |
| aReader.getTypeName().replace( '/', '.' ) ); |
| aName.appendAscii( "." ); |
| aName.append( aReader.getFieldName( nFields ) ); |
| |
| uno::Any aValue( |
| getRTValue( |
| aReader.getFieldValue( nFields ) ) ); |
| |
| m_aTypeDescs.push_back( |
| new IndividualConstantTypeDescriptionImpl( |
| aName.makeStringAndClear(), aValue, |
| ( ( aReader.getFieldFlags( nFields ) |
| & RT_ACCESS_PUBLISHED ) |
| != 0 ) ) ); |
| } |
| } |
| } |
| catch ( registry::InvalidRegistryException const & ) |
| { |
| // getBinaryValue |
| |
| OSL_ENSURE( sal_False, |
| "TypeDescriptionEnumerationImpl::queryMore " |
| "- Caught InvalidRegistryException!" ); |
| } |
| } |
| } |
| |
| ///////////////////////////////////////////////////////////////////// |
| |
| /* |
| @@@ m_aModuleKeys.front() may have open sub keys (may be contained in |
| both m_aModuleKeys and m_aCurrentModuleSubKeys)! |
| |
| try |
| { |
| m_aModuleKeys.front()->closeKey(); |
| } |
| catch ( registry::InvalidRegistryException const & ) |
| { |
| OSL_ENSURE( sal_False, |
| "TypeDescriptionEnumerationImpl::queryMore " |
| "- Caught InvalidRegistryException!" ); |
| } |
| */ |
| // We're done with this module key, even if there were errors. |
| m_aModuleKeys.pop_front(); |
| } |
| |
| // unreachable |
| } |
| |
| //========================================================================= |
| uno::Reference< reflection::XTypeDescription > |
| TypeDescriptionEnumerationImpl::queryNext() |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| for (;;) |
| { |
| if ( !queryMore() ) |
| return uno::Reference< reflection::XTypeDescription >(); |
| |
| uno::Reference< reflection::XTypeDescription > xTD; |
| |
| if ( !m_aTypeDescs.empty() ) |
| { |
| xTD = m_aTypeDescs.front(); |
| m_aTypeDescs.pop_front(); |
| return xTD; |
| } |
| |
| // Note: xKey is already opened. |
| uno::Reference< registry::XRegistryKey > |
| xKey( m_aCurrentModuleSubKeys.front() ); |
| /* |
| @@@ xKey may still be contained in m_aModuleKeys, too |
| |
| // closes key in it's dtor (which is |
| // called even in case of exceptions). |
| RegistryKeyCloser aCloser( xKey ); |
| */ |
| try |
| { |
| { |
| if ( xKey->isValid() ) |
| { |
| if ( xKey->getValueType() |
| == registry::RegistryValueType_BINARY ) |
| { |
| uno::Sequence< sal_Int8 > aBytes( |
| xKey->getBinaryValue() ); |
| |
| xTD = createTypeDescription( aBytes, |
| m_xTDMgr, |
| false ); |
| OSL_ENSURE( xTD.is(), |
| "TypeDescriptionEnumerationImpl::queryNext " |
| "- No XTypeDescription created!" ); |
| } |
| } |
| else |
| { |
| OSL_ENSURE( sal_False, |
| "TypeDescriptionEnumerationImpl::queryNext " |
| "- Invalid registry key!" ); |
| } |
| } |
| } |
| catch ( registry::InvalidRegistryException const & ) |
| { |
| // getValueType, getBinaryValue |
| |
| OSL_ENSURE( sal_False, |
| "TypeDescriptionEnumerationImpl::queryNext " |
| "- Caught InvalidRegistryException!" ); |
| } |
| |
| // We're done with this key, even if there were errors. |
| m_aCurrentModuleSubKeys.pop_front(); |
| |
| if ( xTD.is() ) |
| return xTD; |
| |
| // next try... |
| |
| } // for (;;) |
| } |
| |
| } // namespace stoc_rdbtdp |
| |