diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /ucb/source/ucp/hierarchy/hierarchydata.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-cb75148ebd0135178ff46f89a30139c44f8d2040.tar.xz libreoffice-cb75148ebd0135178ff46f89a30139c44f8d2040.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ucb/source/ucp/hierarchy/hierarchydata.cxx')
-rw-r--r-- | ucb/source/ucp/hierarchy/hierarchydata.cxx | 1098 |
1 files changed, 1098 insertions, 0 deletions
diff --git a/ucb/source/ucp/hierarchy/hierarchydata.cxx b/ucb/source/ucp/hierarchy/hierarchydata.cxx new file mode 100644 index 000000000..3e802a4fd --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydata.cxx @@ -0,0 +1,1098 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + + +/************************************************************************** + TODO + ************************************************************************** + + - HierarchyEntry::move + --> Rewrite to use XNamed ( once this is supported by config db api ). + + *************************************************************************/ +#include "hierarchydata.hxx" + +#include <tools/diagnose_ex.h> +#include <rtl/ustrbuf.hxx> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XNameReplace.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/util/XOfficeInstallationDirectories.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <comphelper/propertysequence.hxx> +#include "hierarchyprovider.hxx" +#include "hierarchyuri.hxx" + +using namespace com::sun::star; + +namespace hierarchy_ucp +{ + + +static void makeXMLName( const OUString & rIn, OUStringBuffer & rBuffer ) +{ + sal_Int32 nCount = rIn.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const sal_Unicode c = rIn[ n ]; + switch ( c ) + { + case '&': + rBuffer.append( "&" ); + break; + + case '"': + rBuffer.append( """ ); + break; + + case '\'': + rBuffer.append( "'" ); + break; + + case '<': + rBuffer.append( "<" ); + break; + + case '>': + rBuffer.append( ">" ); + break; + + default: + rBuffer.append( c ); + break; + } + } +} + + +// HierarchyEntry Implementation. + + +constexpr OUStringLiteral READ_SERVICE_NAME = u"com.sun.star.ucb.HierarchyDataReadAccess"; +constexpr OUStringLiteral READWRITE_SERVICE_NAME = u"com.sun.star.ucb.HierarchyDataReadWriteAccess"; + +// describe path of cfg entry +constexpr OUStringLiteral CFGPROPERTY_NODEPATH = u"nodepath"; + + +HierarchyEntry::HierarchyEntry( + const uno::Reference< uno::XComponentContext >& rxContext, + HierarchyContentProvider* pProvider, + const OUString& rURL ) +: m_xContext( rxContext ), + m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ), + m_bTriedToGetRootReadAccess( false ) +{ + HierarchyUri aUri( rURL ); + m_aServiceSpecifier = aUri.getService(); + + m_xConfigProvider + = pProvider->getConfigProvider( m_aServiceSpecifier ); + m_xRootReadAccess + = pProvider->getRootConfigReadNameAccess( m_aServiceSpecifier ); + + // Note: do not init m_aPath in init list. createPathFromHierarchyURL + // needs m_xContext and m_aMutex. + m_aPath = createPathFromHierarchyURL( aUri ); + + // Extract language independent name from URL. + sal_Int32 nPos = rURL.lastIndexOf( '/' ); + if ( nPos > HIERARCHY_URL_SCHEME_LENGTH ) + m_aName = rURL.copy( nPos + 1 ); + else + OSL_FAIL( "HierarchyEntry - Invalid URL!" ); +} + + +bool HierarchyEntry::hasData() +{ + uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess + = getRootReadAccess(); + + OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" ); + + if ( xRootReadAccess.is() ) + return xRootReadAccess->hasByHierarchicalName( m_aPath ); + + return false; +} + + +bool HierarchyEntry::getData( HierarchyEntryData& rData ) +{ + try + { + uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess + = getRootReadAccess(); + + OSL_ENSURE( xRootReadAccess.is(), + "HierarchyEntry::getData - No root!" ); + + if ( xRootReadAccess.is() ) + { + OUString aTitlePath = m_aPath + "/Title"; + + // Note: Avoid NoSuchElementExceptions, because exceptions are + // relatively 'expensive'. Checking for availability of + // title value is sufficient here, because if it is + // there, the other values will be available too. + if ( !xRootReadAccess->hasByHierarchicalName( aTitlePath ) ) + return false; + + OUString aValue; + + // Get Title value. + if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath ) + >>= aValue ) ) + { + OSL_FAIL( "HierarchyEntry::getData - " + "Got no Title value!" ); + return false; + } + + rData.setTitle( aValue ); + + // Get TargetURL value. + OUString aTargetURLPath = m_aPath + "/TargetURL"; + if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath ) + >>= aValue ) ) + { + OSL_FAIL( "HierarchyEntry::getData - " + "Got no TargetURL value!" ); + return false; + } + + // TargetURL property may contain a reference to the Office + // installation directory. To ensure a reloctable office + // installation, the path to the office installation directory must + // never be stored directly. A placeholder is used instead. Replace + // it by actual installation directory. + if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() ) + aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue ); + rData.setTargetURL( aValue ); + + OUString aTypePath = m_aPath + "/Type"; + if ( xRootReadAccess->hasByHierarchicalName( aTypePath ) ) + { + // Might not be present since it was introduced long after + // Title and TargetURL (#82433#)... So not getting it is + // not an error. + + // Get Type value. + sal_Int32 nType = 0; + if ( xRootReadAccess->getByHierarchicalName( aTypePath ) + >>= nType ) + { + if ( nType == 0 ) + { + rData.setType( HierarchyEntryData::LINK ); + } + else if ( nType == 1 ) + { + rData.setType( HierarchyEntryData::FOLDER ); + } + else + { + OSL_FAIL( "HierarchyEntry::getData - " + "Unknown Type value!" ); + return false; + } + } + } + + rData.setName( m_aName ); + return true; + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + return false; +} + + +bool HierarchyEntry::setData( const HierarchyEntryData& rData ) +{ + try + { + std::unique_lock aGuard( m_aMutex ); + + if ( !m_xConfigProvider.is() ) + m_xConfigProvider.set( + m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext), + uno::UNO_QUERY ); + + if ( m_xConfigProvider.is() ) + { + // Create parent's key. It must exist! + + OUString aParentPath; + bool bRoot = true; + + sal_Int32 nPos = m_aPath.lastIndexOf( '/' ); + if ( nPos != -1 ) + { + // Skip "/Children" segment of the path, too. + nPos = m_aPath.lastIndexOf( '/', nPos - 1 ); + + OSL_ENSURE( nPos != -1, + "HierarchyEntry::setData - Wrong path!" ); + + aParentPath += m_aPath.subView( 0, nPos ); + bRoot = false; + } + + uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence( + { + {CFGPROPERTY_NODEPATH, uno::Any(aParentPath)} + })); + + uno::Reference< util::XChangesBatch > xBatch( + m_xConfigProvider->createInstanceWithArguments( + READWRITE_SERVICE_NAME, + aArguments ), + uno::UNO_QUERY ); + + OSL_ENSURE( xBatch.is(), + "HierarchyEntry::setData - No batch!" ); + + uno::Reference< container::XNameAccess > xParentNameAccess( + xBatch, uno::UNO_QUERY ); + + OSL_ENSURE( xParentNameAccess.is(), + "HierarchyEntry::setData - No name access!" ); + + if ( xBatch.is() && xParentNameAccess.is() ) + { + // Try to create own key. It must not exist! + + bool bExists = true; + uno::Any aMyKey; + + try + { + uno::Reference< container::XNameAccess > xNameAccess; + + if ( bRoot ) + { + xNameAccess = xParentNameAccess; + } + else + { + xParentNameAccess->getByName("Children") >>= xNameAccess; + } + + if ( xNameAccess->hasByName( m_aName ) ) + aMyKey = xNameAccess->getByName( m_aName ); + else + bExists = false; + } + catch ( container::NoSuchElementException const & ) + { + bExists = false; + } + + uno::Reference< container::XNameReplace > xNameReplace; + uno::Reference< container::XNameContainer > xContainer; + + if ( bExists ) + { + // Key exists. Replace values. + + aMyKey >>= xNameReplace; + + OSL_ENSURE( xNameReplace.is(), + "HierarchyEntry::setData - No name replace!" ); + } + else + { + // Key does not exist. Create / fill / insert it. + + uno::Reference< lang::XSingleServiceFactory > xFac; + + if ( bRoot ) + { + // Special handling for children of root, + // which is not an entry. It's only a set + // of entries. + xFac.set( xParentNameAccess, uno::UNO_QUERY ); + } + else + { + // Append new entry to parents child list, + // which is a set of entries. + xParentNameAccess->getByName("Children") >>= xFac; + } + + OSL_ENSURE( xFac.is(), + "HierarchyEntry::setData - No factory!" ); + + if ( xFac.is() ) + { + xNameReplace.set( xFac->createInstance(), uno::UNO_QUERY ); + + OSL_ENSURE( xNameReplace.is(), + "HierarchyEntry::setData - No name replace!" ); + + if ( xNameReplace.is() ) + { + xContainer.set( xFac, uno::UNO_QUERY ); + + OSL_ENSURE( xContainer.is(), + "HierarchyEntry::setData - No container!" ); + } + } + } + + if ( xNameReplace.is() ) + { + // Set Title value. + xNameReplace->replaceByName( + "Title", + uno::Any( rData.getTitle() ) ); + + // Set TargetURL value. + + // TargetURL property may contain a reference to the Office + // installation directory. To ensure a reloctable office + // installation, the path to the office installation + // directory must never be stored directly. Use a + // placeholder instead. + OUString aValue( rData.getTargetURL() ); + if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() ) + aValue + = m_xOfficeInstDirs->makeRelocatableURL( aValue ); + + xNameReplace->replaceByName( + "TargetURL", + uno::Any( aValue ) ); + + // Set Type value. + sal_Int32 nType + = rData.getType() == HierarchyEntryData::LINK ? 0 : 1; + xNameReplace->replaceByName( + "Type", + uno::Any( nType ) ); + + if ( xContainer.is() ) + xContainer->insertByName( + m_aName, uno::Any( xNameReplace ) ); + + // Commit changes. + xBatch->commitChanges(); + return true; + } + } + } + } + catch ( lang::IllegalArgumentException const & ) + { + // replaceByName, insertByName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( container::NoSuchElementException const & ) + { + // replaceByName, getByName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + catch ( container::ElementExistException const & ) + { + // insertByName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + catch ( lang::WrappedTargetException const & ) + { + // replaceByName, insertByName, getByName, commitChanges + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + + return false; +} + + +bool HierarchyEntry::move( + const OUString& rNewURL, const HierarchyEntryData& rData ) +{ + OUString aNewPath = createPathFromHierarchyURL( HierarchyUri(rNewURL) ); + + std::unique_lock aGuard( m_aMutex ); + + if ( aNewPath == m_aPath ) + return true; + + bool bOldRoot = true; + uno::Reference< util::XChangesBatch > xOldParentBatch; + + OUString aNewKey; + sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' ); + if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH ) + aNewKey = rNewURL.copy( nURLPos + 1 ); + else + { + OSL_FAIL( "HierarchyEntry::move - Invalid URL!" ); + return false; + } + + bool bNewRoot = true; + uno::Reference< util::XChangesBatch > xNewParentBatch; + + bool bDifferentParents = true; + + try + { + if ( !m_xConfigProvider.is() ) + m_xConfigProvider.set( + m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext), + uno::UNO_QUERY ); + + if ( !m_xConfigProvider.is() ) + return false; + + OUString aOldParentPath; + sal_Int32 nPos = m_aPath.lastIndexOf( '/' ); + if ( nPos != -1 ) + { + // Skip "/Children" segment of the path, too. + nPos = m_aPath.lastIndexOf( '/', nPos - 1 ); + + OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" ); + + aOldParentPath += m_aPath.subView( 0, nPos ); + bOldRoot = false; + } + + OUString aNewParentPath; + nPos = aNewPath.lastIndexOf( '/' ); + if ( nPos != -1 ) + { + // Skip "/Children" segment of the path, too. + nPos = aNewPath.lastIndexOf( '/', nPos - 1 ); + + OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" ); + + aNewParentPath += aNewPath.subView( 0, nPos ); + bNewRoot = false; + } + + uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence( + { + {CFGPROPERTY_NODEPATH, uno::Any(aOldParentPath)} + })); + + xOldParentBatch.set( + m_xConfigProvider->createInstanceWithArguments( + READWRITE_SERVICE_NAME, + aArguments ), + uno::UNO_QUERY ); + + OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" ); + + if ( !xOldParentBatch.is() ) + return false; + + if ( aOldParentPath == aNewParentPath ) + { + bDifferentParents = false; + xNewParentBatch = xOldParentBatch; + } + else + { + bDifferentParents = true; + + uno::Sequence<uno::Any> aArguments2(comphelper::InitAnyPropertySequence( + { + {CFGPROPERTY_NODEPATH, uno::Any(aNewParentPath)} + })); + + xNewParentBatch.set( + m_xConfigProvider->createInstanceWithArguments( + READWRITE_SERVICE_NAME, + aArguments2 ), + uno::UNO_QUERY ); + + OSL_ENSURE( + xNewParentBatch.is(), "HierarchyEntry::move - No batch!" ); + + if ( !xNewParentBatch.is() ) + return false; + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + return false; + } + + + // (1) Get entry... + + + uno::Any aEntry; + uno::Reference< container::XNameAccess > xOldParentNameAccess; + uno::Reference< container::XNameContainer > xOldNameContainer; + + try + { + xOldParentNameAccess.set( xOldParentBatch, uno::UNO_QUERY ); + + OSL_ENSURE( xOldParentNameAccess.is(), + "HierarchyEntry::move - No name access!" ); + + if ( !xOldParentNameAccess.is() ) + return false; + + if ( bOldRoot ) + { + xOldNameContainer.set( xOldParentNameAccess, uno::UNO_QUERY ); + } + else + { + xOldParentNameAccess->getByName("Children") >>= xOldNameContainer; + } + + aEntry = xOldNameContainer->getByName( m_aName ); + } + catch ( container::NoSuchElementException const & ) + { + // getByName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + return false; + } + catch ( lang::WrappedTargetException const & ) + { + // getByName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + return false; + } + + + // (2) Remove entry... Note: Insert BEFORE remove does not work! + + + try + { + xOldNameContainer->removeByName( m_aName ); + xOldParentBatch->commitChanges(); + } + catch ( container::NoSuchElementException const & ) + { + // getByName, removeByName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + return false; + } + + + // (3) Insert entry at new parent... + + + try + { + uno::Reference< container::XNameReplace > xNewNameReplace; + aEntry >>= xNewNameReplace; + + OSL_ENSURE( xNewNameReplace.is(), + "HierarchyEntry::move - No name replace!" ); + + if ( !xNewNameReplace.is() ) + return false; + + uno::Reference< container::XNameAccess > xNewParentNameAccess; + if ( bDifferentParents ) + xNewParentNameAccess.set( xNewParentBatch, uno::UNO_QUERY ); + else + xNewParentNameAccess = xOldParentNameAccess; + + OSL_ENSURE( xNewParentNameAccess.is(), + "HierarchyEntry::move - No name access!" ); + + if ( !xNewParentNameAccess.is() ) + return false; + + uno::Reference< container::XNameContainer > xNewNameContainer; + if ( bDifferentParents ) + { + if ( bNewRoot ) + { + xNewNameContainer.set( xNewParentNameAccess, uno::UNO_QUERY ); + } + else + { + xNewParentNameAccess->getByName("Children") >>= xNewNameContainer; + } + } + else + xNewNameContainer = xOldNameContainer; + + if ( !xNewNameContainer.is() ) + return false; + + xNewNameReplace->replaceByName( + "Title", + uno::Any( rData.getTitle() ) ); + + // TargetURL property may contain a reference to the Office + // installation directory. To ensure a reloctable office + // installation, the path to the office installation + // directory must never be stored directly. Use a placeholder + // instead. + OUString aValue( rData.getTargetURL() ); + if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() ) + aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue ); + xNewNameReplace->replaceByName( + "TargetURL", + uno::Any( aValue ) ); + sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1; + xNewNameReplace->replaceByName( + "Type", + uno::Any( nType ) ); + + xNewNameContainer->insertByName( aNewKey, aEntry ); + xNewParentBatch->commitChanges(); + } + catch ( container::NoSuchElementException const & ) + { + // replaceByName, insertByName, getByName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + return false; + } + catch ( lang::IllegalArgumentException const & ) + { + // replaceByName, insertByName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + return false; + } + catch ( container::ElementExistException const & ) + { + // insertByName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + return false; + } + catch ( lang::WrappedTargetException const & ) + { + // replaceByName, insertByName, getByName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + return false; + } + + return true; +} + + +bool HierarchyEntry::remove() +{ + try + { + std::unique_lock aGuard( m_aMutex ); + + if ( !m_xConfigProvider.is() ) + m_xConfigProvider.set( + m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext), + uno::UNO_QUERY ); + + if ( m_xConfigProvider.is() ) + { + // Create parent's key. It must exist! + + OUString aParentPath; + bool bRoot = true; + + sal_Int32 nPos = m_aPath.lastIndexOf( '/' ); + if ( nPos != -1 ) + { + // Skip "/Children" segment of the path, too. + nPos = m_aPath.lastIndexOf( '/', nPos - 1 ); + + OSL_ENSURE( nPos != -1, + "HierarchyEntry::remove - Wrong path!" ); + + aParentPath += m_aPath.subView( 0, nPos ); + bRoot = false; + } + + uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence( + { + {CFGPROPERTY_NODEPATH, uno::Any(aParentPath)} + })); + + uno::Reference< util::XChangesBatch > xBatch( + m_xConfigProvider->createInstanceWithArguments( + READWRITE_SERVICE_NAME, + aArguments ), + uno::UNO_QUERY ); + + OSL_ENSURE( xBatch.is(), + "HierarchyEntry::remove - No batch!" ); + + uno::Reference< container::XNameAccess > xParentNameAccess( + xBatch, uno::UNO_QUERY ); + + OSL_ENSURE( xParentNameAccess.is(), + "HierarchyEntry::remove - No name access!" ); + + if ( xBatch.is() && xParentNameAccess.is() ) + { + uno::Reference< container::XNameContainer > xContainer; + + if ( bRoot ) + { + // Special handling for children of root, + // which is not an entry. It's only a set + // of entries. + xContainer.set( xParentNameAccess, uno::UNO_QUERY ); + } + else + { + // Append new entry to parents child list, + // which is a set of entries. + xParentNameAccess->getByName("Children") >>= xContainer; + } + + OSL_ENSURE( xContainer.is(), + "HierarchyEntry::remove - No container!" ); + + if ( xContainer.is() ) + { + xContainer->removeByName( m_aName ); + xBatch->commitChanges(); + return true; + } + } + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( container::NoSuchElementException const & ) + { + // getByName, removeByName + + OSL_FAIL( + "HierarchyEntry::remove - caught NoSuchElementException!" ); + } + catch ( lang::WrappedTargetException const & ) + { + // getByName, commitChanges + + OSL_FAIL( + "HierarchyEntry::remove - caught WrappedTargetException!" ); + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + + return false; +} + + +bool HierarchyEntry::first( iterator & it ) +{ + if ( it.pos == -1 ) + { + // Init... + + try + { + uno::Reference< container::XHierarchicalNameAccess > + xRootHierNameAccess = getRootReadAccess(); + + if ( xRootHierNameAccess.is() ) + { + uno::Reference< container::XNameAccess > xNameAccess; + + if ( !m_aPath.isEmpty() ) + { + OUString aPath = m_aPath + "/Children"; + + xRootHierNameAccess->getByHierarchicalName( aPath ) + >>= xNameAccess; + } + else + xNameAccess.set( xRootHierNameAccess, uno::UNO_QUERY ); + + OSL_ENSURE( xNameAccess.is(), + "HierarchyEntry::first - No name access!" ); + + if ( xNameAccess.is() ) + it.names = xNameAccess->getElementNames(); + + uno::Reference< container::XHierarchicalNameAccess > + xHierNameAccess( xNameAccess, uno::UNO_QUERY ); + + OSL_ENSURE( xHierNameAccess.is(), + "HierarchyEntry::first - No hier. name access!" ); + + it.dir = xHierNameAccess; + + it.officeDirs = m_xOfficeInstDirs; + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( container::NoSuchElementException const& ) + { + // getByHierarchicalName + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + catch ( uno::Exception const & ) + { + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + } + + if ( !it.names.hasElements() ) + return false; + + it.pos = 0; + return true; +} + + +bool HierarchyEntry::next( iterator& it ) +{ + if ( it.pos == -1 ) + return first( it ); + + ++it.pos; + + return ( it.pos < it.names.getLength() ); +} + + +OUString HierarchyEntry::createPathFromHierarchyURL( + const HierarchyUri& rURI ) +{ + // Transform path... + // folder/subfolder/subsubfolder + // --> ['folder']/Children/['subfolder']/Children/['subsubfolder'] + + const OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash. + sal_Int32 nLen = aPath.getLength(); + + if ( nLen ) + { + OUStringBuffer aNewPath; + aNewPath.append( "['" ); + + sal_Int32 nStart = 0; + sal_Int32 nEnd = aPath.indexOf( '/' ); + + do + { + if ( nEnd == -1 ) + nEnd = nLen; + + OUString aToken = aPath.copy( nStart, nEnd - nStart ); + makeXMLName( aToken, aNewPath ); + + if ( nEnd != nLen ) + { + aNewPath.append( "']/Children/['" ); + nStart = nEnd + 1; + nEnd = aPath.indexOf( '/', nStart ); + } + else + aNewPath.append( "']" ); + } + while ( nEnd != nLen ); + + return aNewPath.makeStringAndClear(); + } + + return aPath; +} + + +uno::Reference< container::XHierarchicalNameAccess > +HierarchyEntry::getRootReadAccess() +{ + if ( !m_xRootReadAccess.is() ) + { + std::unique_lock aGuard( m_aMutex ); + if ( !m_xRootReadAccess.is() ) + { + if ( m_bTriedToGetRootReadAccess ) + { + OSL_FAIL( "HierarchyEntry::getRootReadAccess - " + "Unable to read any config data! -> #82494#" ); + return uno::Reference< container::XHierarchicalNameAccess >(); + } + + try + { + if ( !m_xConfigProvider.is() ) + m_xConfigProvider.set( + m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext), + uno::UNO_QUERY ); + + if ( m_xConfigProvider.is() ) + { + // Create Root object. + + uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence( + { + {CFGPROPERTY_NODEPATH, uno::Any(OUString())} // root path + })); + + m_bTriedToGetRootReadAccess = true; + + m_xRootReadAccess.set( + m_xConfigProvider->createInstanceWithArguments( + READ_SERVICE_NAME, + aArguments ), + uno::UNO_QUERY ); + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + } + } + return m_xRootReadAccess; +} + + +// HierarchyEntry::iterator Implementation. + + +const HierarchyEntryData& HierarchyEntry::iterator::operator*() +{ + if ( ( pos != -1 ) + && ( dir.is() ) + && ( pos < names.getLength() ) ) + { + try + { + OUStringBuffer aKey; + aKey.append( "['" ); + makeXMLName( names.getConstArray()[ pos ], aKey ); + aKey.append( "']" ); + + OUString aTitle = aKey.makeStringAndClear(); + OUString aTargetURL = aTitle; + OUString aType = aTitle; + + aTitle += "/Title"; + aTargetURL += "/TargetURL"; + aType += "/Type"; + + OUString aValue; + dir->getByHierarchicalName( aTitle ) >>= aValue; + entry.setTitle( aValue ); + + dir->getByHierarchicalName( aTargetURL ) >>= aValue; + + // TargetURL property may contain a reference to the Office + // installation directory. To ensure a reloctable office + // installation, the path to the office installation directory must + // never be stored directly. A placeholder is used instead. Replace + // it by actual installation directory. + if ( officeDirs.is() && !aValue.isEmpty() ) + aValue = officeDirs->makeAbsoluteURL( aValue ); + entry.setTargetURL( aValue ); + + if ( dir->hasByHierarchicalName( aType ) ) + { + // Might not be present since it was introduced long + // after Title and TargetURL (#82433#)... So not getting + // it is not an error. + + // Get Type value. + sal_Int32 nType = 0; + if ( dir->getByHierarchicalName( aType ) >>= nType ) + { + if ( nType == 0 ) + { + entry.setType( HierarchyEntryData::LINK ); + } + else if ( nType == 1 ) + { + entry.setType( HierarchyEntryData::FOLDER ); + } + else + { + OSL_FAIL( "HierarchyEntry::getData - " + "Unknown Type value!" ); + } + } + } + + entry.setName( + names.getConstArray()[ pos ] ); + } + catch ( container::NoSuchElementException const & ) + { + entry = HierarchyEntryData(); + } + } + + return entry; +} + +} // namespace hierarchy_ucp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |