diff options
Diffstat (limited to 'ucb/source/ucp/hierarchy/hierarchydata.cxx')
-rw-r--r-- | ucb/source/ucp/hierarchy/hierarchydata.cxx | 1266 |
1 files changed, 1266 insertions, 0 deletions
diff --git a/ucb/source/ucp/hierarchy/hierarchydata.cxx b/ucb/source/ucp/hierarchy/hierarchydata.cxx new file mode 100644 index 000000000000..d2e8f5031527 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydata.cxx @@ -0,0 +1,1266 @@ +/************************************************************************* + * + * 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_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - HierarchyEntry::move + --> Rewrite to use XNamed ( once this is supported by config db api ). + + *************************************************************************/ +#include "hierarchydata.hxx" + +#include <vector> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#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> +#ifndef _COM_SUN_STAR_UTIL_XOFFICEINSTALLTIONDIRECTORIES_HPP_ +#include <com/sun/star/util/XOfficeInstallationDirectories.hpp> +#endif +#include "hierarchyprovider.hxx" +#include "hierarchyuri.hxx" + +using namespace com::sun::star; + +namespace hierarchy_ucp +{ + +//========================================================================= +struct HierarchyEntry::iterator_Impl +{ + HierarchyEntryData entry; + uno::Reference< container::XHierarchicalNameAccess > dir; + uno::Reference< util::XOfficeInstallationDirectories > officeDirs; + uno::Sequence< rtl::OUString> names; + sal_Int32 pos; + iterator_Impl() + : officeDirs( 0 ), pos( -1 /* before first */ ) {}; +}; + +//========================================================================= +void makeXMLName( const rtl::OUString & rIn, rtl::OUStringBuffer & rBuffer ) +{ + sal_Int32 nCount = rIn.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const sal_Unicode c = rIn.getStr()[ n ]; + switch ( c ) + { + case '&': + rBuffer.appendAscii( "&" ); + break; + + case '"': + rBuffer.appendAscii( """ ); + break; + + case '\'': + rBuffer.appendAscii( "'" ); + break; + + case '<': + rBuffer.appendAscii( "<" ); + break; + + case '>': + rBuffer.appendAscii( ">" ); + break; + + default: + rBuffer.append( c ); + break; + } + } +} + +//========================================================================= +//========================================================================= +// +// HierarchyEntry Implementation. +// +//========================================================================= +//========================================================================= + +#define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess" +#define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess" + +// describe path of cfg entry +#define CFGPROPERTY_NODEPATH "nodepath" + +//========================================================================= +HierarchyEntry::HierarchyEntry( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + HierarchyContentProvider* pProvider, + const rtl::OUString& rURL ) +: m_xSMgr( rSMgr ), + m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ), + m_bTriedToGetRootReadAccess( sal_False ) +{ + HierarchyUri aUri( rURL ); + m_aServiceSpecifier = aUri.getService(); + + if ( pProvider ) + { + m_xConfigProvider + = pProvider->getConfigProvider( m_aServiceSpecifier ); + m_xRootReadAccess + = pProvider->getRootConfigReadNameAccess( m_aServiceSpecifier ); + } + + // Note: do not init m_aPath in init list. createPathFromHierarchyURL + // needs m_xSMgr 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_ENSURE( sal_False, "HierarchyEntry - Invalid URL!" ); +} + +//========================================================================= +sal_Bool HierarchyEntry::hasData() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess + = getRootReadAccess(); + + OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" ); + + if ( xRootReadAccess.is() ) + return xRootReadAccess->hasByHierarchicalName( m_aPath ); + + return sal_False; +} + +//========================================================================= +sal_Bool HierarchyEntry::getData( HierarchyEntryData& rData ) +{ + try + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess + = getRootReadAccess(); + + OSL_ENSURE( xRootReadAccess.is(), + "HierarchyEntry::getData - No root!" ); + + if ( xRootReadAccess.is() ) + { + rtl::OUString aTitlePath = m_aPath; + aTitlePath += rtl::OUString::createFromAscii( "/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 sal_False; + + rtl::OUString aValue; + + // Get Title value. + if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath ) + >>= aValue ) ) + { + OSL_ENSURE( sal_False, + "HierarchyEntry::getData - " + "Got no Title value!" ); + return sal_False; + } + + rData.setTitle( aValue ); + + // Get TargetURL value. + rtl::OUString aTargetURLPath = m_aPath; + aTargetURLPath += rtl::OUString::createFromAscii( "/TargetURL" ); + if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath ) + >>= aValue ) ) + { + OSL_ENSURE( sal_False, + "HierarchyEntry::getData - " + "Got no TargetURL value!" ); + return sal_False; + } + + // TargetURL property may contain a reference to the Office + // installation directory. To ensure a reloctable office + // installation, the path to the office installtion directory must + // never be stored directly. A placeholder is used instead. Replace + // it by actual installation directory. + if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) ) + aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue ); + rData.setTargetURL( aValue ); + + rtl::OUString aTypePath = m_aPath; + aTypePath += rtl::OUString::createFromAscii( "/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_ENSURE( sal_False, + "HierarchyEntry::getData - " + "Unknown Type value!" ); + return sal_False; + } + } + } + + rData.setName( m_aName ); + return sal_True; + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( container::NoSuchElementException const & ) + { + // getByHierarchicalName + + OSL_ENSURE( sal_False, + "HierarchyEntry::getData - caught NoSuchElementException!" ); + } + return sal_False; +} + +//========================================================================= +sal_Bool HierarchyEntry::setData( + const HierarchyEntryData& rData, sal_Bool bCreate ) +{ + try + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_xConfigProvider.is() ) + m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( m_aServiceSpecifier ), + uno::UNO_QUERY ); + + if ( m_xConfigProvider.is() ) + { + // Create parent's key. It must exist! + + rtl::OUString aParentPath; + sal_Bool bRoot = sal_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.copy( 0, nPos ); + bRoot = sal_False; + } + + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + + aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_NODEPATH ) ); + aProperty.Value <<= aParentPath; + aArguments[ 0 ] <<= aProperty; + + uno::Reference< util::XChangesBatch > xBatch( + m_xConfigProvider->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + 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! + + sal_Bool bExists = sal_True; + uno::Any aMyKey; + + try + { + uno::Reference< container::XNameAccess > xNameAccess; + + if ( bRoot ) + { + xNameAccess = xParentNameAccess; + } + else + { + xParentNameAccess->getByName( + rtl::OUString::createFromAscii( "Children" ) ) + >>= xNameAccess; + } + + if ( xNameAccess->hasByName( m_aName ) ) + aMyKey = xNameAccess->getByName( m_aName ); + else + bExists = sal_False; + } + catch ( container::NoSuchElementException const & ) + { + bExists = sal_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 + { + if ( !bCreate ) + return sal_True; + + // 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 = uno::Reference< lang::XSingleServiceFactory >( + xParentNameAccess, uno::UNO_QUERY ); + } + else + { + // Append new entry to parents child list, + // which is a set of entries. + xParentNameAccess->getByName( + rtl::OUString::createFromAscii( + "Children" ) ) >>= xFac; + } + + OSL_ENSURE( xFac.is(), + "HierarchyEntry::setData - No factory!" ); + + if ( xFac.is() ) + { + xNameReplace + = uno::Reference< container::XNameReplace >( + xFac->createInstance(), uno::UNO_QUERY ); + + OSL_ENSURE( xNameReplace.is(), + "HierarchyEntry::setData - No name replace!" ); + + if ( xNameReplace.is() ) + { + xContainer + = uno::Reference< container::XNameContainer >( + xFac, uno::UNO_QUERY ); + + OSL_ENSURE( xContainer.is(), + "HierarchyEntry::setData - No container!" ); + } + } + } + + if ( xNameReplace.is() ) + { + // Set Title value. + xNameReplace->replaceByName( + rtl::OUString::createFromAscii( "Title" ), + uno::makeAny( 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 installtion + // directory must never be stored directly. Use a + // placeholder instead. + rtl::OUString aValue( rData.getTargetURL() ); + if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) ) + aValue + = m_xOfficeInstDirs->makeRelocatableURL( aValue ); + + xNameReplace->replaceByName( + rtl::OUString::createFromAscii( "TargetURL" ), + uno::makeAny( aValue ) ); + + // Set Type value. + sal_Int32 nType + = rData.getType() == HierarchyEntryData::LINK ? 0 : 1; + xNameReplace->replaceByName( + rtl::OUString::createFromAscii( "Type" ), + uno::makeAny( nType ) ); + + if ( xContainer.is() ) + xContainer->insertByName( + m_aName, uno::makeAny( xNameReplace ) ); + + // Commit changes. + xBatch->commitChanges(); + return sal_True; + } + } + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( lang::IllegalArgumentException const & ) + { + // replaceByName, insertByName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::setData - caught IllegalArgumentException!" ); + } + catch ( container::NoSuchElementException const & ) + { + // replaceByName, getByName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::setData - caught NoSuchElementException!" ); + } + catch ( container::ElementExistException const & ) + { + // insertByName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::setData - caught ElementExistException!" ); + } + catch ( lang::WrappedTargetException const & ) + { + // replaceByName, insertByName, getByName, commitChanges + + OSL_ENSURE( + sal_False, + "HierarchyEntry::setData - caught WrappedTargetException!" ); + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( + sal_False, + "HierarchyEntry::setData - caught Exception!" ); + } + + return sal_False; +} + +//========================================================================= +sal_Bool HierarchyEntry::move( + const rtl::OUString& rNewURL, const HierarchyEntryData& rData ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + rtl::OUString aNewPath = createPathFromHierarchyURL( rNewURL ); + + if ( aNewPath == m_aPath ) + return sal_True; + +#if 0 + // In the "near future"... ( not yet implemented in config db ) + + - get update access for m_aPath + - update access -> XNamed + - xNamed::setName( newName ) + - updateaccess commit +#else + + sal_Bool bOldRoot = sal_True; + uno::Reference< util::XChangesBatch > xOldParentBatch; + + rtl::OUString aNewKey; + sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' ); + if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH ) + aNewKey = rNewURL.copy( nURLPos + 1 ); + else + { + OSL_ENSURE( sal_False, "HierarchyEntry::move - Invalid URL!" ); + return sal_False; + } + + sal_Bool bNewRoot = sal_True; + uno::Reference< util::XChangesBatch > xNewParentBatch; + + sal_Bool bDifferentParents = sal_True; + + try + { + if ( !m_xConfigProvider.is() ) + m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( m_aServiceSpecifier ), + uno::UNO_QUERY ); + + if ( !m_xConfigProvider.is() ) + return sal_False; + + rtl::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.copy( 0, nPos ); + bOldRoot = sal_False; + } + + rtl::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.copy( 0, nPos ); + bNewRoot = sal_False; + } + + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + + aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_NODEPATH ) ); + aProperty.Value <<= aOldParentPath; + aArguments[ 0 ] <<= aProperty; + + xOldParentBatch = uno::Reference< util::XChangesBatch >( + m_xConfigProvider->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + READWRITE_SERVICE_NAME ) ), + aArguments ), + uno::UNO_QUERY ); + + OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" ); + + if ( !xOldParentBatch.is() ) + return sal_False; + + if ( aOldParentPath == aNewParentPath ) + { + bDifferentParents = sal_False; + xNewParentBatch = xOldParentBatch; + } + else + { + bDifferentParents = sal_True; + + aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_NODEPATH ) ); + aProperty.Value <<= aNewParentPath; + aArguments[ 0 ] <<= aProperty; + + xNewParentBatch = uno::Reference< util::XChangesBatch >( + m_xConfigProvider->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + READWRITE_SERVICE_NAME ) ), + aArguments ), + uno::UNO_QUERY ); + + OSL_ENSURE( + xNewParentBatch.is(), "HierarchyEntry::move - No batch!" ); + + if ( !xNewParentBatch.is() ) + return sal_False; + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( sal_False, "HierarchyEntry::move - caught Exception!" ); + return sal_False; + } + + ////////////////////////////////////////////////////////////////////// + // (1) Get entry... + ////////////////////////////////////////////////////////////////////// + + uno::Any aEntry; + uno::Reference< container::XNameAccess > xOldParentNameAccess; + uno::Reference< container::XNameContainer > xOldNameContainer; + + try + { + xOldParentNameAccess + = uno::Reference< container::XNameAccess >( + xOldParentBatch, uno::UNO_QUERY ); + + OSL_ENSURE( xOldParentNameAccess.is(), + "HierarchyEntry::move - No name access!" ); + + if ( !xOldParentNameAccess.is() ) + return sal_False; + + if ( bOldRoot ) + { + xOldNameContainer = uno::Reference< container::XNameContainer >( + xOldParentNameAccess, uno::UNO_QUERY ); + } + else + { + xOldParentNameAccess->getByName( + rtl::OUString::createFromAscii( "Children" ) ) + >>= xOldNameContainer; + } + + aEntry = xOldNameContainer->getByName( m_aName ); + } + catch ( container::NoSuchElementException const & ) + { + // getByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught NoSuchElementException!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + // getByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught WrappedTargetException!" ); + return sal_False; + } + + ////////////////////////////////////////////////////////////////////// + // (2) Remove entry... Note: Insert BEFORE remove does not work! + ////////////////////////////////////////////////////////////////////// + + try + { + xOldNameContainer->removeByName( m_aName ); + xOldParentBatch->commitChanges(); + } + catch ( container::NoSuchElementException const & ) + { + // getByName, removeByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught NoSuchElementException!" ); + return sal_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 sal_False; + + uno::Reference< container::XNameAccess > xNewParentNameAccess; + if ( bDifferentParents ) + xNewParentNameAccess + = uno::Reference< container::XNameAccess >( + xNewParentBatch, uno::UNO_QUERY ); + else + xNewParentNameAccess = xOldParentNameAccess; + + OSL_ENSURE( xNewParentNameAccess.is(), + "HierarchyEntry::move - No name access!" ); + + if ( !xNewParentNameAccess.is() ) + return sal_False; + + uno::Reference< container::XNameContainer > xNewNameContainer; + if ( bDifferentParents ) + { + if ( bNewRoot ) + { + xNewNameContainer + = uno::Reference< container::XNameContainer >( + xNewParentNameAccess, uno::UNO_QUERY ); + } + else + { + xNewParentNameAccess->getByName( + rtl::OUString::createFromAscii( "Children" ) ) + >>= xNewNameContainer; + } + } + else + xNewNameContainer = xOldNameContainer; + + if ( !xNewNameContainer.is() ) + return sal_False; + + xNewNameReplace->replaceByName( + rtl::OUString::createFromAscii( "Title" ), + uno::makeAny( rData.getTitle() ) ); + + // TargetURL property may contain a reference to the Office + // installation directory. To ensure a reloctable office + // installation, the path to the office installtion + // directory must never be stored directly. Use a placeholder + // instead. + rtl::OUString aValue( rData.getTargetURL() ); + if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) ) + aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue ); + xNewNameReplace->replaceByName( + rtl::OUString::createFromAscii( "TargetURL" ), + uno::makeAny( aValue ) ); + sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1; + xNewNameReplace->replaceByName( + rtl::OUString::createFromAscii( "Type" ), + uno::makeAny( nType ) ); + + xNewNameContainer->insertByName( aNewKey, aEntry ); + xNewParentBatch->commitChanges(); + } + catch ( container::NoSuchElementException const & ) + { + // replaceByName, insertByName, getByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught NoSuchElementException!" ); + return sal_False; + } + catch ( lang::IllegalArgumentException const & ) + { + // replaceByName, insertByName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::move - caught IllegalArgumentException!" ); + return sal_False; + } + catch ( container::ElementExistException const & ) + { + // insertByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught ElementExistException!" ); + return sal_False; + } + catch ( lang::WrappedTargetException const & ) + { + // replaceByName, insertByName, getByName + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught WrappedTargetException!" ); + return sal_False; + } + +#if 0 + ////////////////////////////////////////////////////////////////////// + // (4) Commit changes... + ////////////////////////////////////////////////////////////////////// + + try + { + xNewParentBatch->commitChanges(); + + if ( bDifferentParents ) + xOldParentBatch->commitChanges(); + } + catch ( lang::WrappedTargetException const & ) + { + // commitChanges + + OSL_ENSURE( sal_False, + "HierarchyEntry::move - caught WrappedTargetException!" ); + return sal_False; + } +#endif + + return sal_True; +#endif +} + +//========================================================================= +sal_Bool HierarchyEntry::remove() +{ + try + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_xConfigProvider.is() ) + m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( m_aServiceSpecifier ), + uno::UNO_QUERY ); + + if ( m_xConfigProvider.is() ) + { + // Create parent's key. It must exist! + + rtl::OUString aParentPath; + sal_Bool bRoot = sal_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.copy( 0, nPos ); + bRoot = sal_False; + } + + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + + aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_NODEPATH ) ); + aProperty.Value <<= aParentPath; + aArguments[ 0 ] <<= aProperty; + + uno::Reference< util::XChangesBatch > xBatch( + m_xConfigProvider->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + 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 = uno::Reference< container::XNameContainer >( + xParentNameAccess, uno::UNO_QUERY ); + } + else + { + // Append new entry to parents child list, + // which is a set of entries. + xParentNameAccess->getByName( + rtl::OUString::createFromAscii( "Children" ) ) + >>= xContainer; + } + + OSL_ENSURE( xContainer.is(), + "HierarchyEntry::remove - No container!" ); + + if ( xContainer.is() ) + { + xContainer->removeByName( m_aName ); + xBatch->commitChanges(); + return sal_True; + } + } + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( container::NoSuchElementException const & ) + { + // getByName, removeByName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::remove - caught NoSuchElementException!" ); + } + catch ( lang::WrappedTargetException const & ) + { + // getByName, commitChanges + + OSL_ENSURE( + sal_False, + "HierarchyEntry::remove - caught WrappedTargetException!" ); + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( sal_False, + "HierarchyEntry::remove - caught Exception!" ); + } + + return sal_False; +} + +//========================================================================= +sal_Bool HierarchyEntry::first( iterator& it ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( it.m_pImpl->pos == -1 ) + { + // Init... + + try + { + uno::Reference< container::XHierarchicalNameAccess > + xRootHierNameAccess = getRootReadAccess(); + + if ( xRootHierNameAccess.is() ) + { + uno::Reference< container::XNameAccess > xNameAccess; + + if ( m_aPath.getLength() > 0 ) + { + rtl::OUString aPath = m_aPath; + aPath += rtl::OUString::createFromAscii( "/Children" ); + + xRootHierNameAccess->getByHierarchicalName( aPath ) + >>= xNameAccess; + } + else + xNameAccess + = uno::Reference< container::XNameAccess >( + xRootHierNameAccess, uno::UNO_QUERY ); + + OSL_ENSURE( xNameAccess.is(), + "HierarchyEntry::first - No name access!" ); + + if ( xNameAccess.is() ) + it.m_pImpl->names = xNameAccess->getElementNames(); + + uno::Reference< container::XHierarchicalNameAccess > + xHierNameAccess( xNameAccess, uno::UNO_QUERY ); + + OSL_ENSURE( xHierNameAccess.is(), + "HierarchyEntry::first - No hier. name access!" ); + + it.m_pImpl->dir = xHierNameAccess; + + it.m_pImpl->officeDirs = m_xOfficeInstDirs; + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( container::NoSuchElementException const& ) + { + // getByHierarchicalName + + OSL_ENSURE( + sal_False, + "HierarchyEntry::first - caught NoSuchElementException!" ); + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( sal_False, + "HierarchyEntry::first - caught Exception!" ); + } + } + + if ( it.m_pImpl->names.getLength() == 0 ) + return sal_False; + + it.m_pImpl->pos = 0; + return sal_True; +} + +//========================================================================= +sal_Bool HierarchyEntry::next( iterator& it ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( it.m_pImpl->pos == -1 ) + return first( it ); + + ++(it.m_pImpl->pos); + + return ( it.m_pImpl->pos < it.m_pImpl->names.getLength() ); +} + +//========================================================================= +rtl::OUString HierarchyEntry::createPathFromHierarchyURL( + const HierarchyUri& rURI ) +{ + // Transform path.... + // folder/subfolder/subsubfolder + // --> ['folder']/Children/['subfolder']/Children/['subsubfolder'] + + const rtl::OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash. + sal_Int32 nLen = aPath.getLength(); + + if ( nLen ) + { + rtl::OUStringBuffer aNewPath; + aNewPath.appendAscii( "['" ); + + sal_Int32 nStart = 0; + sal_Int32 nEnd = aPath.indexOf( '/' ); + + do + { + if ( nEnd == -1 ) + nEnd = nLen; + + rtl::OUString aToken = aPath.copy( nStart, nEnd - nStart ); + makeXMLName( aToken, aNewPath ); + + if ( nEnd != nLen ) + { + aNewPath.appendAscii( "']/Children/['" ); + nStart = nEnd + 1; + nEnd = aPath.indexOf( '/', nStart ); + } + else + aNewPath.appendAscii( "']" ); + } + while ( nEnd != nLen ); + + return aNewPath.makeStringAndClear(); + } + + return aPath; +} + +//========================================================================= +uno::Reference< container::XHierarchicalNameAccess > +HierarchyEntry::getRootReadAccess() +{ + if ( !m_xRootReadAccess.is() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( !m_xRootReadAccess.is() ) + { + if ( m_bTriedToGetRootReadAccess ) // #82494# + { + OSL_ENSURE( sal_False, + "HierarchyEntry::getRootReadAccess - " + "Unable to read any config data! -> #82494#" ); + return uno::Reference< container::XHierarchicalNameAccess >(); + } + + try + { + if ( !m_xConfigProvider.is() ) + m_xConfigProvider + = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( m_aServiceSpecifier ), + uno::UNO_QUERY ); + + if ( m_xConfigProvider.is() ) + { + // Create Root object. + + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + aProperty.Name = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( CFGPROPERTY_NODEPATH ) ); + aProperty.Value <<= rtl::OUString(); // root path + aArguments[ 0 ] <<= aProperty; + + m_bTriedToGetRootReadAccess = sal_True; + + m_xRootReadAccess + = uno::Reference< container::XHierarchicalNameAccess >( + m_xConfigProvider->createInstanceWithArguments( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + READ_SERVICE_NAME ) ), + aArguments ), + uno::UNO_QUERY ); + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( sal_False, + "HierarchyEntry::getRootReadAccess - " + "caught Exception!" ); + } + } + } + return m_xRootReadAccess; +} + +//========================================================================= +//========================================================================= +// +// HierarchyEntry::iterator Implementation. +// +//========================================================================= +//========================================================================= + +HierarchyEntry::iterator::iterator() +{ + m_pImpl = new iterator_Impl; +} + +//========================================================================= +HierarchyEntry::iterator::~iterator() +{ + delete m_pImpl; +} + +//========================================================================= +const HierarchyEntryData& HierarchyEntry::iterator::operator*() const +{ + if ( ( m_pImpl->pos != -1 ) + && ( m_pImpl->dir.is() ) + && ( m_pImpl->pos < m_pImpl->names.getLength() ) ) + { + try + { + rtl::OUStringBuffer aKey; + aKey.appendAscii( "['" ); + makeXMLName( m_pImpl->names.getConstArray()[ m_pImpl->pos ], aKey ); + aKey.appendAscii( "']" ); + + rtl::OUString aTitle = aKey.makeStringAndClear(); + rtl::OUString aTargetURL = aTitle; + rtl::OUString aType = aTitle; + + aTitle += rtl::OUString::createFromAscii( "/Title" ); + aTargetURL += rtl::OUString::createFromAscii( "/TargetURL" ); + aType += rtl::OUString::createFromAscii( "/Type" ); + + rtl::OUString aValue; + m_pImpl->dir->getByHierarchicalName( aTitle ) >>= aValue; + m_pImpl->entry.setTitle( aValue ); + + m_pImpl->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 installtion directory must + // never be stored directly. A placeholder is used instead. Replace + // it by actual installation directory. + if ( m_pImpl->officeDirs.is() && ( aValue.getLength() > 0 ) ) + aValue = m_pImpl->officeDirs->makeAbsoluteURL( aValue ); + m_pImpl->entry.setTargetURL( aValue ); + + if ( m_pImpl->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 ( m_pImpl->dir->getByHierarchicalName( aType ) >>= nType ) + { + if ( nType == 0 ) + { + m_pImpl->entry.setType( HierarchyEntryData::LINK ); + } + else if ( nType == 1 ) + { + m_pImpl->entry.setType( HierarchyEntryData::FOLDER ); + } + else + { + OSL_ENSURE( sal_False, + "HierarchyEntry::getData - " + "Unknown Type value!" ); + } + } + } + + m_pImpl->entry.setName( + m_pImpl->names.getConstArray()[ m_pImpl->pos ] ); + } + catch ( container::NoSuchElementException const & ) + { + m_pImpl->entry = HierarchyEntryData(); + } + } + + return m_pImpl->entry; +} + +} // namespace hierarchy_ucp |