/************************************************************** * * 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 #include #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