summaryrefslogtreecommitdiff
path: root/ucb/source/ucp/hierarchy/hierarchydata.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'ucb/source/ucp/hierarchy/hierarchydata.cxx')
-rw-r--r--ucb/source/ucp/hierarchy/hierarchydata.cxx1266
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( "&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