summaryrefslogtreecommitdiff
path: root/stoc/source/registry_tdprovider/rdbtdp_tdenumeration.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'stoc/source/registry_tdprovider/rdbtdp_tdenumeration.cxx')
-rw-r--r--stoc/source/registry_tdprovider/rdbtdp_tdenumeration.cxx643
1 files changed, 643 insertions, 0 deletions
diff --git a/stoc/source/registry_tdprovider/rdbtdp_tdenumeration.cxx b/stoc/source/registry_tdprovider/rdbtdp_tdenumeration.cxx
new file mode 100644
index 000000000000..7104fbf57d92
--- /dev/null
+++ b/stoc/source/registry_tdprovider/rdbtdp_tdenumeration.cxx
@@ -0,0 +1,643 @@
+/*************************************************************************
+ *
+ * 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"
+
+//=========================================================================
+// 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
+