blob: 879f1c6ab5c384fd8cb3806f77a6ef3b23761ba1 [file] [log] [blame]
/**************************************************************
*
* 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_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( "&amp;" );
break;
case '"':
rBuffer.appendAscii( "&quot;" );
break;
case '\'':
rBuffer.appendAscii( "&apos;" );
break;
case '<':
rBuffer.appendAscii( "&lt;" );
break;
case '>':
rBuffer.appendAscii( "&gt;" );
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