diff options
Diffstat (limited to 'ucb/source/ucp/hierarchy')
19 files changed, 7545 insertions, 0 deletions
diff --git a/ucb/source/ucp/hierarchy/dynamicresultset.cxx b/ucb/source/ucp/hierarchy/dynamicresultset.cxx new file mode 100644 index 000000000000..0cb8fec28e17 --- /dev/null +++ b/ucb/source/ucp/hierarchy/dynamicresultset.cxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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 + ************************************************************************** + + - This implementation is not a dynamic result set!!! It only implements + the necessary interfaces, but never recognizes/notifies changes!!! + + *************************************************************************/ +#include "hierarchydatasupplier.hxx" +#include "dynamicresultset.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= +//========================================================================= +// +// DynamicResultSet Implementation. +// +//========================================================================= +//========================================================================= + +DynamicResultSet::DynamicResultSet( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< HierarchyContent >& rxContent, + const ucb::OpenCommandArgument2& rCommand ) +: ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ) +{ +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( + m_xSMgr, + m_aCommand.Properties, + new HierarchyResultSetDataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ) ); +} + +//========================================================================= +void DynamicResultSet::initDynamic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( + m_xSMgr, + m_aCommand.Properties, + new HierarchyResultSetDataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ) ); + m_xResultSet2 = m_xResultSet1; +} + diff --git a/ucb/source/ucp/hierarchy/dynamicresultset.hxx b/ucb/source/ucp/hierarchy/dynamicresultset.hxx new file mode 100644 index 000000000000..9553b299b0ad --- /dev/null +++ b/ucb/source/ucp/hierarchy/dynamicresultset.hxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _DYNAMICRESULTSET_HXX +#define _DYNAMICRESULTSET_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultsethelper.hxx> +#include "hierarchycontent.hxx" + +namespace hierarchy_ucp { + +class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper +{ + rtl::Reference< HierarchyContent > m_xContent; + +private: + virtual void initStatic(); + virtual void initDynamic(); + +public: + DynamicResultSet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< HierarchyContent >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand ); +}; + +} + +#endif /* !_DYNAMICRESULTSET_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchycontent.cxx b/ucb/source/ucp/hierarchy/hierarchycontent.cxx new file mode 100644 index 000000000000..2243692549e6 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchycontent.cxx @@ -0,0 +1,2009 @@ +/************************************************************************* + * + * 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 + ************************************************************************** + + - optimize transfer command. "Move" should be implementable much more + efficient! + + ************************************************************************** + + - Root Folder vs. 'normal' Folder + - root doesn't support command 'delete' + - root doesn't support command 'insert' + - root needs not created via XContentCreator - queryContent with root + folder id ( HIERARCHY_ROOT_FOLDER_URL ) always returns a value != 0 + - root has no parent. + + *************************************************************************/ +#include <osl/diagnose.h> + +#include "osl/doublecheckedlocking.h" +#include <rtl/ustring.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> +#include "hierarchycontent.hxx" +#include "hierarchyprovider.hxx" +#include "dynamicresultset.hxx" +#include "hierarchyuri.hxx" + +#include "../inc/urihelper.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= +//========================================================================= +// +// HierarchyContent Implementation. +// +//========================================================================= +//========================================================================= + +// static ( "virtual" ctor ) +HierarchyContent* HierarchyContent::create( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier ) +{ + // Fail, if content does not exist. + HierarchyContentProperties aProps; + if ( !loadData( rxSMgr, pProvider, Identifier, aProps ) ) + return 0; + + return new HierarchyContent( rxSMgr, pProvider, Identifier, aProps ); +} + +//========================================================================= +// static ( "virtual" ctor ) +HierarchyContent* HierarchyContent::create( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const ucb::ContentInfo& Info ) +{ + if ( !Info.Type.getLength() ) + return 0; + + if ( !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ) && + !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_LINK_CONTENT_TYPE ) ) ) + return 0; + +#if 0 + // Fail, if content does exist. + if ( hasData( rxSMgr, pProvider, Identifier ) ) + return 0; +#endif + + return new HierarchyContent( rxSMgr, pProvider, Identifier, Info ); +} + +//========================================================================= +HierarchyContent::HierarchyContent( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const HierarchyContentProperties& rProps ) +: ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_aProps( rProps ), + m_eState( PERSISTENT ), + m_pProvider( pProvider ), + m_bCheckedReadOnly( false ), + m_bIsReadOnly( true ) +{ + setKind( Identifier ); +} + +//========================================================================= +HierarchyContent::HierarchyContent( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + const ucb::ContentInfo& Info ) + : ContentImplHelper( rxSMgr, pProvider, Identifier ), + m_aProps( Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ) + ? HierarchyEntryData::FOLDER + : HierarchyEntryData::LINK ), + m_eState( TRANSIENT ), + m_pProvider( pProvider ), + m_bCheckedReadOnly( false ), + m_bIsReadOnly( true ) +{ + setKind( Identifier ); +} + +//========================================================================= +// virtual +HierarchyContent::~HierarchyContent() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyContent::acquire() + throw( ) +{ + ContentImplHelper::acquire(); +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyContent::release() + throw( ) +{ + ContentImplHelper::release(); +} + +//========================================================================= +// virtual +uno::Any SAL_CALL HierarchyContent::queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet = ContentImplHelper::queryInterface( rType ); + + if ( !aRet.hasValue() ) + { + // Note: isReadOnly may be relative expensive. So avoid calling it + // unless it is really necessary. + aRet = cppu::queryInterface( + rType, static_cast< ucb::XContentCreator * >( this ) ); + if ( aRet.hasValue() ) + { + if ( !isFolder() || isReadOnly() ) + return uno::Any(); + } + } + + return aRet; +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_COMMON_IMPL( HierarchyContent ); + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL HierarchyContent::getTypes() + throw( uno::RuntimeException ) +{ + cppu::OTypeCollection * pCollection = 0; + + if ( isFolder() && !isReadOnly() ) + { + static cppu::OTypeCollection* pFolderTypes = 0; + + pCollection = pFolderTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pFolderTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ), + CPPU_TYPE_REF( ucb::XContentCreator ) ); // !! + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pFolderTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + else + { + static cppu::OTypeCollection* pDocumentTypes = 0; + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pDocumentTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( ucb::XContent ), + CPPU_TYPE_REF( ucb::XCommandProcessor ), + CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), + CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), + CPPU_TYPE_REF( beans::XPropertyContainer ), + CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), + CPPU_TYPE_REF( container::XChild ) ); + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pDocumentTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL HierarchyContent::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.HierarchyContent" ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL +HierarchyContent::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + + if ( m_eKind == LINK ) + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + HIERARCHY_LINK_CONTENT_SERVICE_NAME ); + else if ( m_eKind == FOLDER ) + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + HIERARCHY_FOLDER_CONTENT_SERVICE_NAME ); + else + aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( + HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME ); + + return aSNS; +} + +//========================================================================= +// +// XContent methods. +// +//========================================================================= + +// virtual +rtl::OUString SAL_CALL HierarchyContent::getContentType() + throw( uno::RuntimeException ) +{ + return m_aProps.getContentType(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContentIdentifier > SAL_CALL +HierarchyContent::getIdentifier() + throw( uno::RuntimeException ) +{ + // Transient? + if ( m_eState == TRANSIENT ) + { + // Transient contents have no identifier. + return uno::Reference< ucb::XContentIdentifier >(); + } + + return ContentImplHelper::getIdentifier(); +} + +//========================================================================= +// +// XCommandProcessor methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL HierarchyContent::execute( + const ucb::Command& aCommand, + sal_Int32 /*CommandId*/, + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception, + ucb::CommandAbortedException, + uno::RuntimeException ) +{ + uno::Any aRet; + + if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= getPropertyValues( Properties ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // setPropertyValues + ////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + if ( !aProperties.getLength() ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "No properties!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= setPropertyValues( aProperties, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getPropertySetInfo + ////////////////////////////////////////////////////////////////// + + aRet <<= getPropertySetInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // getCommandInfo + ////////////////////////////////////////////////////////////////// + + aRet <<= getCommandInfo( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "open" ) ) && isFolder() ) + { + ////////////////////////////////////////////////////////////////// + // open command for a folder content + ////////////////////////////////////////////////////////////////// + + ucb::OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + uno::Reference< ucb::XDynamicResultSet > xSet + = new DynamicResultSet( m_xSMgr, this, aOpenCommand ); + aRet <<= xSet; + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "insert" ) ) && + ( m_eKind != ROOT ) && !isReadOnly() ) + { + ////////////////////////////////////////////////////////////////// + // insert + // ( Not available at root folder ) + ////////////////////////////////////////////////////////////////// + + ucb::InsertCommandArgument aArg; + if ( !( aCommand.Argument >>= aArg ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + sal_Int32 nNameClash = aArg.ReplaceExisting + ? ucb::NameClash::OVERWRITE + : ucb::NameClash::ERROR; + insert( nNameClash, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "delete" ) ) && + ( m_eKind != ROOT ) && !isReadOnly() ) + { + ////////////////////////////////////////////////////////////////// + // delete + // ( Not available at root folder ) + ////////////////////////////////////////////////////////////////// + + sal_Bool bDeletePhysical = sal_False; + aCommand.Argument >>= bDeletePhysical; + destroy( bDeletePhysical, Environment ); + + // Remove own and all children's persistent data. + if ( !removeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + Environment, + rtl::OUString::createFromAscii( + "Cannot remove persistent data!" ), + this ); + // Unreachable + } + + // Remove own and all children's Additional Core Properties. + removeAdditionalPropertySet( sal_True ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) && + isFolder() && !isReadOnly() ) + { + ////////////////////////////////////////////////////////////////// + // transfer + // ( Not available at link objects ) + ////////////////////////////////////////////////////////////////// + + ucb::TransferInfo aInfo; + if ( !( aCommand.Argument >>= aInfo ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + transfer( aInfo, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) && + isFolder() && !isReadOnly() ) + { + ////////////////////////////////////////////////////////////////// + // createNewContent + // ( Not available at link objects ) + ////////////////////////////////////////////////////////////////// + + ucb::ContentInfo aInfo; + if ( !( aCommand.Argument >>= aInfo ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= createNewContent( aInfo ); + } + else + { + ////////////////////////////////////////////////////////////////// + // Unsupported command + ////////////////////////////////////////////////////////////////// + + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + return aRet; +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyContent::abort( sal_Int32 /*CommandId*/ ) + throw( uno::RuntimeException ) +{ + // @@@ Generally, no action takes much time... +} + +//========================================================================= +// +// XContentCreator methods. +// +//========================================================================= + +// virtual +uno::Sequence< ucb::ContentInfo > SAL_CALL +HierarchyContent::queryCreatableContentsInfo() + throw( uno::RuntimeException ) +{ + return m_aProps.getCreatableContentsInfo(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > SAL_CALL +HierarchyContent::createNewContent( const ucb::ContentInfo& Info ) + throw( uno::RuntimeException ) +{ + if ( isFolder() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !Info.Type.getLength() ) + return uno::Reference< ucb::XContent >(); + + sal_Bool bCreateFolder = + Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ); + + if ( !bCreateFolder && + !Info.Type.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_LINK_CONTENT_TYPE ) ) ) + return uno::Reference< ucb::XContent >(); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + + OSL_ENSURE( aURL.getLength() > 0, + "HierarchyContent::createNewContent - empty identifier!" ); + + if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() ) + aURL += rtl::OUString::createFromAscii( "/" ); + + if ( bCreateFolder ) + aURL += rtl::OUString::createFromAscii( "New_Folder" ); + else + aURL += rtl::OUString::createFromAscii( "New_Link" ); + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ); + + return create( m_xSMgr, m_pProvider, xId, Info ); + } + else + { + OSL_ENSURE( sal_False, + "createNewContent called on non-folder object!" ); + return uno::Reference< ucb::XContent >(); + } +} + +//========================================================================= +// virtual +rtl::OUString HierarchyContent::getParentURL() +{ + HierarchyUri aUri( m_xIdentifier->getContentIdentifier() ); + return aUri.getParentUri(); +} + +//========================================================================= +//static +sal_Bool HierarchyContent::hasData( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier ) +{ + rtl::OUString aURL = Identifier->getContentIdentifier(); + + // Am I a root folder? + HierarchyUri aUri( aURL ); + if ( aUri.isRootFolder() ) + { + // hasData must always return 'true' for root folder + // even if no persistent data exist!!! + return sal_True; + } + + return HierarchyEntry( rxSMgr, pProvider, aURL ).hasData(); +} + +//========================================================================= +//static +sal_Bool HierarchyContent::loadData( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const uno::Reference< ucb::XContentIdentifier >& Identifier, + HierarchyContentProperties& rProps ) +{ + rtl::OUString aURL = Identifier->getContentIdentifier(); + + // Am I a root folder? + HierarchyUri aUri( aURL ); + if ( aUri.isRootFolder() ) + { + rProps = HierarchyContentProperties( HierarchyEntryData::FOLDER ); + } + else + { + HierarchyEntry aEntry( rxSMgr, pProvider, aURL ); + HierarchyEntryData aData; + if ( !aEntry.getData( aData ) ) + return sal_False; + + rProps = HierarchyContentProperties( aData ); + } + return sal_True; +} + +//========================================================================= +sal_Bool HierarchyContent::storeData() +{ + HierarchyEntry aEntry( + m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() ); + return aEntry.setData( m_aProps.getHierarchyEntryData(), sal_True ); +} + +//========================================================================= +sal_Bool HierarchyContent::renameData( + const uno::Reference< ucb::XContentIdentifier >& xOldId, + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + HierarchyEntry aEntry( + m_xSMgr, m_pProvider, xOldId->getContentIdentifier() ); + return aEntry.move( xNewId->getContentIdentifier(), + m_aProps.getHierarchyEntryData() ); +} + +//========================================================================= +sal_Bool HierarchyContent::removeData() +{ + HierarchyEntry aEntry( + m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() ); + return aEntry.remove(); +} + +//========================================================================= +void HierarchyContent::setKind( + const uno::Reference< ucb::XContentIdentifier >& Identifier ) +{ + if ( m_aProps.getIsFolder() ) + { + // Am I a root folder? + HierarchyUri aUri( Identifier->getContentIdentifier() ); + if ( aUri.isRootFolder() ) + m_eKind = ROOT; + else + m_eKind = FOLDER; + } + else + m_eKind = LINK; +} + +//========================================================================= +bool HierarchyContent::isReadOnly() +{ + if ( !m_bCheckedReadOnly ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( !m_bCheckedReadOnly ) + { + m_bCheckedReadOnly = true; + m_bIsReadOnly = true; + + HierarchyUri aUri( m_xIdentifier->getContentIdentifier() ); + uno::Reference< lang::XMultiServiceFactory > xConfigProv + = m_pProvider->getConfigProvider( aUri.getService() ); + if ( xConfigProv.is() ) + { + uno::Sequence< rtl::OUString > aNames + = xConfigProv->getAvailableServiceNames(); + sal_Int32 nCount = aNames.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + if ( aNames[ n ].equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.ucb.HierarchyDataReadWriteAccess" + ) ) ) + { + m_bIsReadOnly = false; + break; + } + } + } + } + } + + return m_bIsReadOnly; +} + +//========================================================================= +uno::Reference< ucb::XContentIdentifier > +HierarchyContent::makeNewIdentifier( const rtl::OUString& rTitle ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Assemble new content identifier... + HierarchyUri aUri( m_xIdentifier->getContentIdentifier() ); + rtl::OUString aNewURL = aUri.getParentUri(); + aNewURL += rtl::OUString::createFromAscii( "/" ); + aNewURL += ::ucb_impl::urihelper::encodeSegment( rTitle ); + + return uno::Reference< ucb::XContentIdentifier >( + new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ) ); +} + +//========================================================================= +void HierarchyContent::queryChildren( HierarchyContentRefList& rChildren ) +{ + if ( ( m_eKind != FOLDER ) && ( m_eKind != ROOT ) ) + return; + + // Obtain a list with a snapshot of all currently instanciated contents + // from provider and extract the contents which are direct children + // of this content. + + ::ucbhelper::ContentRefList aAllContents; + m_xProvider->queryExistingContents( aAllContents ); + + rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); + sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); + + if ( nURLPos != ( aURL.getLength() - 1 ) ) + { + // No trailing slash found. Append. + aURL += rtl::OUString::createFromAscii( "/" ); + } + + sal_Int32 nLen = aURL.getLength(); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + while ( it != end ) + { + ::ucbhelper::ContentImplHelperRef xChild = (*it); + rtl::OUString aChildURL + = xChild->getIdentifier()->getContentIdentifier(); + + // Is aURL a prefix of aChildURL? + if ( ( aChildURL.getLength() > nLen ) && + ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) + { + sal_Int32 nPos = nLen; + nPos = aChildURL.indexOf( '/', nPos ); + + if ( ( nPos == -1 ) || + ( nPos == ( aChildURL.getLength() - 1 ) ) ) + { + // No further slashes/ only a final slash. It's a child! + rChildren.push_back( + HierarchyContentRef( + static_cast< HierarchyContent * >( xChild.get() ) ) ); + } + } + ++it; + } +} + +//========================================================================= +sal_Bool HierarchyContent::exchangeIdentity( + const uno::Reference< ucb::XContentIdentifier >& xNewId ) +{ + if ( !xNewId.is() ) + return sal_False; + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< ucb::XContent > xThis = this; + + // Already persistent? + if ( m_eState != PERSISTENT ) + { + OSL_ENSURE( sal_False, + "HierarchyContent::exchangeIdentity - Not persistent!" ); + return sal_False; + } + + // Am I the root folder? + if ( m_eKind == ROOT ) + { + OSL_ENSURE( sal_False, "HierarchyContent::exchangeIdentity - " + "Not supported by root folder!" ); + return sal_False; + } + + // Exchange own identitity. + + // Fail, if a content with given id already exists. + if ( !hasData( xNewId ) ) + { + rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); + + aGuard.clear(); + if ( exchange( xNewId ) ) + { + if ( m_eKind == FOLDER ) + { + // Process instanciated children... + + HierarchyContentRefList aChildren; + queryChildren( aChildren ); + + HierarchyContentRefList::const_iterator it = aChildren.begin(); + HierarchyContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + HierarchyContentRef xChild = (*it); + + // Create new content identifier for the child... + uno::Reference< ucb::XContentIdentifier > xOldChildId + = xChild->getIdentifier(); + rtl::OUString aOldChildURL + = xOldChildId->getContentIdentifier(); + rtl::OUString aNewChildURL + = aOldChildURL.replaceAt( + 0, + aOldURL.getLength(), + xNewId->getContentIdentifier() ); + uno::Reference< ucb::XContentIdentifier > xNewChildId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, aNewChildURL ); + + if ( !xChild->exchangeIdentity( xNewChildId ) ) + return sal_False; + + ++it; + } + } + return sal_True; + } + } + + OSL_ENSURE( sal_False, + "HierarchyContent::exchangeIdentity - " + "Panic! Cannot exchange identity!" ); + return sal_False; +} + +//========================================================================= +// static +uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues( + const uno::Reference< lang::XMultiServiceFactory >& rSMgr, + const uno::Sequence< beans::Property >& rProperties, + const HierarchyContentProperties& rData, + HierarchyContentProvider* pProvider, + const rtl::OUString& rContentId ) +{ + // Note: Empty sequence means "get values of all supported properties". + + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow + = new ::ucbhelper::PropertyValueSet( rSMgr ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + uno::Reference< beans::XPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + const beans::Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + + // Process Core properties. + + if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + xRow->appendString ( rProp, rData.getContentType() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + xRow->appendString ( rProp, rData.getTitle() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + xRow->appendBoolean( rProp, rData.getIsDocument() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + xRow->appendBoolean( rProp, rData.getIsFolder() ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + xRow->appendObject( + rProp, uno::makeAny( rData.getCreatableContentsInfo() ) ); + } + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "TargetURL" ) ) ) + { + // TargetURL is only supported by links. + + if ( rData.getIsDocument() ) + xRow->appendString( rProp, rData.getTargetURL() ); + else + xRow->appendVoid( rProp ); + } + else + { + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet + = uno::Reference< beans::XPropertySet >( + pProvider->getAdditionalPropertySet( rContentId, + sal_False ), + uno::UNO_QUERY ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + if ( !xRow->appendPropertySetValue( + xAdditionalPropSet, + rProp ) ) + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + else + { + // Append empty entry. + xRow->appendVoid( rProp ); + } + } + } + } + else + { + // Append all Core Properties. + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "ContentType" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.getContentType() ); + xRow->appendString ( + beans::Property( rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + // @@@ Might actually be read-only! + beans::PropertyAttribute::BOUND ), + rData.getTitle() ); + xRow->appendBoolean( + beans::Property( rtl::OUString::createFromAscii( "IsDocument" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.getIsDocument() ); + xRow->appendBoolean( + beans::Property( rtl::OUString::createFromAscii( "IsFolder" ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + rData.getIsFolder() ); + + if ( rData.getIsDocument() ) + xRow->appendString( + beans::Property( rtl::OUString::createFromAscii( "TargetURL" ), + -1, + getCppuType( + static_cast< const rtl::OUString * >( 0 ) ), + // @@@ Might actually be read-only! + beans::PropertyAttribute::BOUND ), + rData.getTargetURL() ); + xRow->appendObject( + beans::Property( + rtl::OUString::createFromAscii( "CreatableContentsInfo" ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ), + uno::makeAny( rData.getCreatableContentsInfo() ) ); + + // Append all Additional Core Properties. + + uno::Reference< beans::XPropertySet > xSet( + pProvider->getAdditionalPropertySet( rContentId, sal_False ), + uno::UNO_QUERY ); + xRow->appendPropertySet( xSet ); + } + + return uno::Reference< sdbc::XRow >( xRow.get() ); +} + +//========================================================================= +uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues( + const uno::Sequence< beans::Property >& rProperties ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + return getPropertyValues( m_xSMgr, + rProperties, + m_aProps, + m_pProvider, + m_xIdentifier->getContentIdentifier() ); +} + +//========================================================================= +uno::Sequence< uno::Any > HierarchyContent::setPropertyValues( + const uno::Sequence< beans::PropertyValue >& rValues, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Sequence< uno::Any > aRet( rValues.getLength() ); + uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); + sal_Int32 nChanged = 0; + + beans::PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; +// aEvent.PropertyName = + aEvent.PropertyHandle = -1; +// aEvent.OldValue = +// aEvent.NewValue = + + const beans::PropertyValue* pValues = rValues.getConstArray(); + sal_Int32 nCount = rValues.getLength(); + + uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; + + sal_Bool bExchange = sal_False; + rtl::OUString aOldTitle; + rtl::OUString aOldName; + sal_Int32 nTitlePos = -1; + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::PropertyValue& rValue = pValues[ n ]; + + if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + if ( isReadOnly() ) + { + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + // No empty titles! + if ( aNewValue.getLength() > 0 ) + { + if ( aNewValue != m_aProps.getTitle() ) + { + // modified title -> modified URL -> exchange ! + if ( m_eState == PERSISTENT ) + bExchange = sal_True; + + aOldTitle = m_aProps.getTitle(); + aOldName = m_aProps.getName(); + + m_aProps.setTitle( aNewValue ); + m_aProps.setName( + ::ucb_impl::urihelper::encodeSegment( + aNewValue ) ); + + // property change event will be set later... + + // remember position within sequence of values + // (for error handling). + nTitlePos = n; + } + } + else + { + aRet[ n ] <<= lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Empty title not allowed!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "TargetURL" ) ) ) + { + if ( isReadOnly() ) + { + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else + { + // TargetURL is only supported by links. + + if ( m_eKind == LINK ) + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + // No empty target URL's! + if ( aNewValue.getLength() > 0 ) + { + if ( aNewValue != m_aProps.getTargetURL() ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue + = uno::makeAny( m_aProps.getTargetURL() ); + aEvent.NewValue + = uno::makeAny( aNewValue ); + + aChanges.getArray()[ nChanged ] = aEvent; + + m_aProps.setTargetURL( aNewValue ); + nChanged++; + } + } + else + { + aRet[ n ] <<= lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Empty target URL not allowed!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ); + } + } + else + { + aRet[ n ] <<= beans::IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + else + { + aRet[ n ] <<= beans::UnknownPropertyException( + rtl::OUString::createFromAscii( + "TargetURL only supported by links!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + else + { + // Not a Core Property! Maybe it's an Additional Core Property?! + + if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) + { + xAdditionalPropSet = getAdditionalPropertySet( sal_False ); + bTriedToGetAdditonalPropSet = sal_True; + } + + if ( xAdditionalPropSet.is() ) + { + try + { + uno::Any aOldValue = xAdditionalPropSet->getPropertyValue( + rValue.Name ); + if ( aOldValue != rValue.Value ) + { + xAdditionalPropSet->setPropertyValue( + rValue.Name, rValue.Value ); + + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = aOldValue; + aEvent.NewValue = rValue.Value; + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + } + catch ( beans::UnknownPropertyException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::WrappedTargetException const & e ) + { + aRet[ n ] <<= e; + } + catch ( beans::PropertyVetoException const & e ) + { + aRet[ n ] <<= e; + } + catch ( lang::IllegalArgumentException const & e ) + { + aRet[ n ] <<= e; + } + } + else + { + aRet[ n ] <<= uno::Exception( + rtl::OUString::createFromAscii( + "No property set for storing the value!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + } + + if ( bExchange ) + { + uno::Reference< ucb::XContentIdentifier > xOldId + = m_xIdentifier; + uno::Reference< ucb::XContentIdentifier > xNewId + = makeNewIdentifier( m_aProps.getTitle() ); + + aGuard.clear(); + if ( exchangeIdentity( xNewId ) ) + { + // Adapt persistent data. + renameData( xOldId, xNewId ); + + // Adapt Additional Core Properties. + renameAdditionalPropertySet( xOldId->getContentIdentifier(), + xNewId->getContentIdentifier(), + sal_True ); + } + else + { + // Roll-back. + m_aProps.setTitle( aOldTitle ); + m_aProps.setName ( aOldName ); + + aOldTitle = aOldName = rtl::OUString(); + + // Set error . + aRet[ nTitlePos ] <<= uno::Exception( + rtl::OUString::createFromAscii( "Exchange failed!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + + if ( aOldTitle.getLength() ) + { + aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); + aEvent.OldValue = uno::makeAny( aOldTitle ); + aEvent.NewValue = uno::makeAny( m_aProps.getTitle() ); + + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + + if ( nChanged > 0 ) + { + // Save changes, if content was already made persistent. + if ( !bExchange && ( m_eState == PERSISTENT ) ) + { + if ( !storeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot store persistent data!" ), + this ); + // Unreachable + } + } + + aChanges.realloc( nChanged ); + + aGuard.clear(); + notifyPropertiesChange( aChanges ); + } + + return aRet; +} + +//========================================================================= +void HierarchyContent::insert( sal_Int32 nNameClashResolve, + const uno::Reference< + ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Am I the root folder? + if ( m_eKind == ROOT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not supported by root folder!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Check, if all required properties were set. + if ( m_aProps.getTitle().getLength() == 0 ) + { + uno::Sequence< rtl::OUString > aProps( 1 ); + aProps[ 0 ] = rtl::OUString::createFromAscii( "Title" ); + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::MissingPropertiesException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + aProps ) ), + xEnv ); + // Unreachable + } + + // Assemble new content identifier... + + uno::Reference< ucb::XContentIdentifier > xId + = makeNewIdentifier( m_aProps.getTitle() ); + + // Handle possible name clash... + + switch ( nNameClashResolve ) + { + // fail. + case ucb::NameClash::ERROR: + if ( hasData( xId ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::NameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_aProps.getTitle() ) ), + xEnv ); + // Unreachable + } + break; + + // replace existing object. + case ucb::NameClash::OVERWRITE: + break; + + // "invent" a new valid title. + case ucb::NameClash::RENAME: + if ( hasData( xId ) ) + { + sal_Int32 nTry = 0; + + do + { + rtl::OUString aNewId = xId->getContentIdentifier(); + aNewId += rtl::OUString::createFromAscii( "_" ); + aNewId += rtl::OUString::valueOf( ++nTry ); + xId = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewId ); + } + while ( hasData( xId ) && ( nTry < 1000 ) ); + + if ( nTry == 1000 ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString::createFromAscii( + "Unable to resolve name clash!" ), + static_cast< cppu::OWeakObject * >( this ), + nNameClashResolve ) ), + xEnv ); + // Unreachable + } + else + { + rtl::OUString aNewTitle( m_aProps.getTitle() ); + aNewTitle += rtl::OUString::createFromAscii( "_" ); + aNewTitle += rtl::OUString::valueOf( nTry ); + m_aProps.setTitle( aNewTitle ); + } + } + break; + + case ucb::NameClash::KEEP: // deprecated + case ucb::NameClash::ASK: + default: + if ( hasData( xId ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( + ucb::UnsupportedNameClashException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + nNameClashResolve ) ), + xEnv ); + // Unreachable + } + break; + } + + // Identifier changed? + sal_Bool bNewId = ( xId->getContentIdentifier() + != m_xIdentifier->getContentIdentifier() ); + m_xIdentifier = xId; + + if ( !storeData() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( "Cannot store persistent data!" ), + this ); + // Unreachable + } + + m_eState = PERSISTENT; + + if ( bNewId ) + { + aGuard.clear(); + inserted(); + } +} + +//========================================================================= +void HierarchyContent::destroy( sal_Bool bDeletePhysical, + const uno::Reference< + ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + // @@@ take care about bDeletePhysical -> trashcan support + + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + uno::Reference< ucb::XContent > xThis = this; + + // Persistent? + if ( m_eState != PERSISTENT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not persistent!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Am I the root folder? + if ( m_eKind == ROOT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not supported by root folder!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + m_eState = DEAD; + + aGuard.clear(); + deleted(); + + if ( m_eKind == FOLDER ) + { + // Process instanciated children... + + HierarchyContentRefList aChildren; + queryChildren( aChildren ); + + HierarchyContentRefList::const_iterator it = aChildren.begin(); + HierarchyContentRefList::const_iterator end = aChildren.end(); + + while ( it != end ) + { + (*it)->destroy( bDeletePhysical, xEnv ); + ++it; + } + } +} + +//========================================================================= +void HierarchyContent::transfer( + const ucb::TransferInfo& rInfo, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Persistent? + if ( m_eState != PERSISTENT ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::UnsupportedCommandException( + rtl::OUString::createFromAscii( + "Not persistent!" ), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Is source a hierarchy content? + if ( ( rInfo.SourceURL.getLength() < HIERARCHY_URL_SCHEME_LENGTH + 2 ) || + ( rInfo.SourceURL.compareToAscii( HIERARCHY_URL_SCHEME ":/", + HIERARCHY_URL_SCHEME_LENGTH + 2 ) + != 0 ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( ucb::InteractiveBadTransferURLException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + xEnv ); + // Unreachable + } + + // Is source not a parent of me / not me? + rtl::OUString aId = m_xIdentifier->getContentIdentifier(); + sal_Int32 nPos = aId.lastIndexOf( '/' ); + if ( nPos != ( aId.getLength() - 1 ) ) + { + // No trailing slash found. Append. + aId += rtl::OUString::createFromAscii( "/" ); + } + + if ( rInfo.SourceURL.getLength() <= aId.getLength() ) + { + if ( aId.compareTo( + rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Uri")), + -1, + uno::makeAny(rInfo.SourceURL), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_RECURSIVE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Target is equal to or is a child of source!" ), + this ); + // Unreachable + } + } + + ////////////////////////////////////////////////////////////////////// + // 0) Obtain content object for source. + ////////////////////////////////////////////////////////////////////// + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, rInfo.SourceURL ); + + // Note: The static cast is okay here, because its sure that + // m_xProvider is always the HierarchyContentProvider. + rtl::Reference< HierarchyContent > xSource; + + try + { + xSource = static_cast< HierarchyContent * >( + m_xProvider->queryContent( xId ).get() ); + } + catch ( ucb::IllegalIdentifierException const & ) + { + // queryContent + } + + if ( !xSource.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny(xId->getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot instanciate source object!" ), + this ); + // Unreachable + } + + ////////////////////////////////////////////////////////////////////// + // 1) Create new child content. + ////////////////////////////////////////////////////////////////////// + + rtl::OUString aType = xSource->isFolder() + ? rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) + : rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ); + ucb::ContentInfo aContentInfo; + aContentInfo.Type = aType; + aContentInfo.Attributes = 0; + + // Note: The static cast is okay here, because its sure that + // createNewContent always creates a HierarchyContent. + rtl::Reference< HierarchyContent > xTarget + = static_cast< HierarchyContent * >( + createNewContent( aContentInfo ).get() ); + if ( !xTarget.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Folder")), + -1, + uno::makeAny(aId), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_CREATE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "XContentCreator::createNewContent failed!" ), + this ); + // Unreachable + } + + ////////////////////////////////////////////////////////////////////// + // 2) Copy data from source content to child content. + ////////////////////////////////////////////////////////////////////// + + uno::Sequence< beans::Property > aSourceProps + = xSource->getPropertySetInfo( xEnv )->getProperties(); + sal_Int32 nCount = aSourceProps.getLength(); + + if ( nCount ) + { + sal_Bool bHadTitle = ( rInfo.NewTitle.getLength() == 0 ); + + // Get all source values. + uno::Reference< sdbc::XRow > xRow + = xSource->getPropertyValues( aSourceProps ); + + uno::Sequence< beans::PropertyValue > aValues( nCount ); + beans::PropertyValue* pValues = aValues.getArray(); + + const beans::Property* pProps = aSourceProps.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rProp = pProps[ n ]; + beans::PropertyValue& rValue = pValues[ n ]; + + rValue.Name = rProp.Name; + rValue.Handle = rProp.Handle; + + if ( !bHadTitle && rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + // Set new title instead of original. + bHadTitle = sal_True; + rValue.Value <<= rInfo.NewTitle; + } + else + rValue.Value = xRow->getObject( + n + 1, + uno::Reference< container::XNameAccess >() ); + + rValue.State = beans::PropertyState_DIRECT_VALUE; + + if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE ) + { + // Add Additional Core Property. + try + { + xTarget->addProperty( rProp.Name, + rProp.Attributes, + rValue.Value ); + } + catch ( beans::PropertyExistException const & ) + { + } + catch ( beans::IllegalTypeException const & ) + { + } + catch ( lang::IllegalArgumentException const & ) + { + } + } + } + + // Set target values. + xTarget->setPropertyValues( aValues, xEnv ); + } + + ////////////////////////////////////////////////////////////////////// + // 3) Commit (insert) child. + ////////////////////////////////////////////////////////////////////// + + xTarget->insert( rInfo.NameClash, xEnv ); + + ////////////////////////////////////////////////////////////////////// + // 4) Transfer (copy) children of source. + ////////////////////////////////////////////////////////////////////// + + if ( xSource->isFolder() ) + { + HierarchyEntry aFolder( + m_xSMgr, m_pProvider, xId->getContentIdentifier() ); + HierarchyEntry::iterator it; + + while ( aFolder.next( it ) ) + { + const HierarchyEntryData& rResult = *it; + + rtl::OUString aChildId = xId->getContentIdentifier(); + if ( ( aChildId.lastIndexOf( '/' ) + 1 ) != aChildId.getLength() ) + aChildId += rtl::OUString::createFromAscii( "/" ); + + aChildId += rResult.getName(); + + ucb::TransferInfo aInfo; + aInfo.MoveData = sal_False; + aInfo.NewTitle = rtl::OUString(); + aInfo.SourceURL = aChildId; + aInfo.NameClash = rInfo.NameClash; + + // Transfer child to target. + xTarget->transfer( aInfo, xEnv ); + } + } + + ////////////////////////////////////////////////////////////////////// + // 5) Destroy source ( when moving only ) . + ////////////////////////////////////////////////////////////////////// + + if ( rInfo.MoveData ) + { + xSource->destroy( sal_True, xEnv ); + + // Remove all persistent data of source and its children. + if ( !xSource->removeData() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Uri")), + -1, + uno::makeAny( + xSource->m_xIdentifier-> + getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE)); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_WRITE, + uno::Sequence< uno::Any >(&aProps, 1), + xEnv, + rtl::OUString::createFromAscii( + "Cannot remove persistent data of source object!" ), + this ); + // Unreachable + } + + // Remove own and all children's Additional Core Properties. + xSource->removeAdditionalPropertySet( sal_True ); + } +} + +//========================================================================= +//========================================================================= +// +// HierarchyContentProperties Implementation. +// +//========================================================================= +//========================================================================= + +uno::Sequence< ucb::ContentInfo > +HierarchyContentProperties::getCreatableContentsInfo() const +{ + if ( getIsFolder() ) + { + uno::Sequence< ucb::ContentInfo > aSeq( 2 ); + + // Folder. + aSeq.getArray()[ 0 ].Type + = rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ); + aSeq.getArray()[ 0 ].Attributes + = ucb::ContentInfoAttribute::KIND_FOLDER; + + uno::Sequence< beans::Property > aFolderProps( 1 ); + aFolderProps.getArray()[ 0 ] = beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ); + aSeq.getArray()[ 0 ].Properties = aFolderProps; + + // Link. + aSeq.getArray()[ 1 ].Type + = rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ); + aSeq.getArray()[ 1 ].Attributes + = ucb::ContentInfoAttribute::KIND_LINK; + + uno::Sequence< beans::Property > aLinkProps( 2 ); + aLinkProps.getArray()[ 0 ] = beans::Property( + rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ); + aLinkProps.getArray()[ 1 ] = beans::Property( + rtl::OUString::createFromAscii( "TargetURL" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND ); + aSeq.getArray()[ 1 ].Properties = aLinkProps; + + return aSeq; + } + else + { + return uno::Sequence< ucb::ContentInfo >( 0 ); + } +} diff --git a/ucb/source/ucp/hierarchy/hierarchycontent.hxx b/ucb/source/ucp/hierarchy/hierarchycontent.hxx new file mode 100644 index 000000000000..5b7360a87719 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchycontent.hxx @@ -0,0 +1,311 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _HIERARCHYCONTENT_HXX +#define _HIERARCHYCONTENT_HXX + +#include <list> +#include <rtl/ref.hxx> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <ucbhelper/contenthelper.hxx> +#include "hierarchydata.hxx" +#include "hierarchyprovider.hxx" + +namespace com { namespace sun { namespace star { namespace beans { + struct Property; + struct PropertyValue; +} } } } + +namespace com { namespace sun { namespace star { namespace sdbc { + class XRow; +} } } } + +namespace com { namespace sun { namespace star { namespace ucb { + struct TransferInfo; +} } } } + +namespace hierarchy_ucp +{ + +//========================================================================= + +#define HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.HierarchyRootFolderContent" +#define HIERARCHY_FOLDER_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.HierarchyFolderContent" +#define HIERARCHY_LINK_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.HierarchyLinkContent" + +//========================================================================= + +class HierarchyContentProperties +{ +public: + HierarchyContentProperties() {}; + + HierarchyContentProperties( const HierarchyEntryData::Type & rType ) + : m_aData( rType ), + m_aContentType( rType == HierarchyEntryData::FOLDER + ? rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) + : rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ) ) {} + + HierarchyContentProperties( const HierarchyEntryData & rData ) + : m_aData( rData ), + m_aContentType( rData.getType() == HierarchyEntryData::FOLDER + ? rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) + : rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ) ) {} + + const rtl::OUString & getName() const { return m_aData.getName(); } + void setName( const rtl::OUString & rName ) { m_aData.setName( rName ); }; + + const rtl::OUString & getTitle() const { return m_aData.getTitle(); } + void setTitle( const rtl::OUString & rTitle ) + { m_aData.setTitle( rTitle ); }; + + const rtl::OUString & getTargetURL() const + { return m_aData.getTargetURL(); } + void setTargetURL( const rtl::OUString & rURL ) + { m_aData.setTargetURL( rURL ); }; + + const rtl::OUString & getContentType() const { return m_aContentType; } + + sal_Bool getIsFolder() const + { return m_aData.getType() == HierarchyEntryData::FOLDER; } + + sal_Bool getIsDocument() const { return !getIsFolder(); } + + com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > + getCreatableContentsInfo() const; + + const HierarchyEntryData & getHierarchyEntryData() const { return m_aData; } + +private: + HierarchyEntryData m_aData; + rtl::OUString m_aContentType; +}; + +//========================================================================= + +class HierarchyContentProvider; + +class HierarchyContent : public ::ucbhelper::ContentImplHelper, + public com::sun::star::ucb::XContentCreator +{ + enum ContentKind { LINK, FOLDER, ROOT }; + enum ContentState { TRANSIENT, // created via CreateNewContent, + // but did not process "insert" yet + PERSISTENT, // processed "insert" + DEAD // processed "delete" + }; + + HierarchyContentProperties m_aProps; + ContentKind m_eKind; + ContentState m_eState; + HierarchyContentProvider* m_pProvider; + bool m_bCheckedReadOnly; + bool m_bIsReadOnly; + +private: + HierarchyContent( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const HierarchyContentProperties& rProps ); + HierarchyContent( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > + getCommands( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual ::rtl::OUString getParentURL(); + + static sal_Bool hasData( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ); + sal_Bool hasData( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ) + { return hasData( m_xSMgr, m_pProvider, Identifier ); } + static sal_Bool loadData( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + HierarchyContentProperties& rProps ); + sal_Bool storeData(); + sal_Bool renameData( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xOldId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xNewId ); + sal_Bool removeData(); + + void setKind( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ); + + bool isReadOnly(); + + sal_Bool isFolder() const { return ( m_eKind > LINK ); } + + ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier > + makeNewIdentifier( const rtl::OUString& rTitle ); + + typedef rtl::Reference< HierarchyContent > HierarchyContentRef; + typedef std::list< HierarchyContentRef > HierarchyContentRefList; + void queryChildren( HierarchyContentRefList& rChildren ); + + sal_Bool exchangeIdentity( + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& xNewId ); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties ); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void insert( sal_Int32 nNameClashResolve, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void destroy( sal_Bool bDeletePhysical, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void transfer( const ::com::sun::star::ucb::TransferInfo& rInfo, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + +public: + // Create existing content. Fail, if not already exists. + static HierarchyContent* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ); + + // Create new content. Fail, if already exists. + static HierarchyContent* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + HierarchyContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual ~HierarchyContent(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL + getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( ::com::sun::star::uno::RuntimeException ); + + // XContent + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > SAL_CALL + getIdentifier() + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + // XContentCreator + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentInfo > SAL_CALL + queryCreatableContentsInfo() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const HierarchyContentProperties& rData, + HierarchyContentProvider* pProvider, + const ::rtl::OUString& rContentId ); +}; + +} // namespace hierarchy_ucp + +#endif /* !_HIERARCHYCONTENT_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchycontentcaps.cxx b/ucb/source/ucp/hierarchy/hierarchycontentcaps.cxx new file mode 100644 index 000000000000..a5371c213f1c --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchycontentcaps.cxx @@ -0,0 +1,765 @@ +/************************************************************************* + * + * 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 + ************************************************************************** + + ************************************************************************** + + Props/Commands: + + root folder folder link link + (new) (new) + ---------------------------------------------------------------- + ContentType x x x x x + IsDocument x x x x x + IsFolder x x x x x + Title x x x x x + TargetURL x x + CreatableContentsInfo x x x x x + + getCommandInfo x x x x x + getPropertySetInfo x x x x x + getPropertyValues x x x x x + setPropertyValues x x x x x + createNewContent x x + insert x x + delete x x + open x x + transfer x x + + *************************************************************************/ + +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ucb/CommandInfo.hpp> +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include "hierarchycontent.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= +// +// HierarchyContent implementation. +// +//========================================================================= + +#define MAKEPROPSEQUENCE( a ) \ + uno::Sequence< beans::Property >( a, sizeof( a ) / sizeof( a[ 0 ] ) ) + +#define MAKECMDSEQUENCE( a ) \ + uno::Sequence< ucb::CommandInfo >( a, sizeof( a ) / sizeof( a[ 0 ] ) ) + +//========================================================================= +// +// IMPORTENT: If any property data ( name / type / ... ) are changed, then +// HierarchyContent::getPropertyValues(...) must be adapted too! +// +//========================================================================= + +// virtual +uno::Sequence< beans::Property > HierarchyContent::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_eKind == LINK ) + { + //================================================================= + // + // Link: Supported properties + // + //================================================================= + + if ( isReadOnly() ) + { + static beans::Property aLinkPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TargetURL" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aLinkPropertyInfoTable ); + } + else + { + static beans::Property aLinkPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TargetURL" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aLinkPropertyInfoTable ); + } + } + else if ( m_eKind == FOLDER ) + { + //================================================================= + // + // Folder: Supported properties + // + //================================================================= + + if ( isReadOnly() ) + { + static beans::Property aFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aFolderPropertyInfoTable ); + } + else + { + static beans::Property aFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aFolderPropertyInfoTable ); + } + } + else + { + //================================================================= + // + // Root Folder: Supported properties + // + //================================================================= + + // Currently no difference between reonly /read-write + // -> all props ar read-only + + static beans::Property aRootFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Required properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + }; + return MAKEPROPSEQUENCE( aRootFolderPropertyInfoTable ); + } +} + +//========================================================================= +// virtual +uno::Sequence< ucb::CommandInfo > HierarchyContent::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_eKind == LINK ) + { + //================================================================= + // + // Link: Supported commands + // + //================================================================= + + if ( isReadOnly() ) + { + static const ucb::CommandInfo aLinkCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aLinkCommandInfoTable ); + } + else + { + static const ucb::CommandInfo aLinkCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aLinkCommandInfoTable ); + } + } + else if ( m_eKind == FOLDER ) + { + //================================================================= + // + // Folder: Supported commands + // + //================================================================= + + if ( isReadOnly() ) + { + static const ucb::CommandInfo aFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aFolderCommandInfoTable ); + } + else + { + static const ucb::CommandInfo aFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aFolderCommandInfoTable ); + } + } + else + { + //================================================================= + // + // Root Folder: Supported commands + // + //================================================================= + + if ( isReadOnly() ) + { + static const ucb::CommandInfo aRootFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aRootFolderCommandInfoTable ); + } + else + { + static const ucb::CommandInfo aRootFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Required commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ), + -1, + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return MAKECMDSEQUENCE( aRootFolderCommandInfoTable ); + } + } +} 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 diff --git a/ucb/source/ucp/hierarchy/hierarchydata.hxx b/ucb/source/ucp/hierarchy/hierarchydata.hxx new file mode 100644 index 000000000000..769611342baf --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydata.hxx @@ -0,0 +1,149 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _HIERARCHYDATA_HXX +#define _HIERARCHYDATA_HXX + +#include <rtl/ustring.hxx> +#include <osl/mutex.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +namespace com { namespace sun { namespace star { + namespace container { + class XHierarchicalNameAccess; + } + namespace util { + class XOfficeInstallationDirectories; + } +} } } + +namespace hierarchy_ucp +{ + +//========================================================================= + +class HierarchyEntryData +{ +public: + enum Type { NONE, LINK, FOLDER }; + + HierarchyEntryData() : m_aType( NONE ) {} + HierarchyEntryData( const Type & rType ) : m_aType( rType ) {} + + const rtl::OUString & getName() const { return m_aName; } + void setName( const rtl::OUString & rName ) { m_aName = rName; } + + const rtl::OUString & getTitle() const { return m_aTitle; } + void setTitle( const rtl::OUString & rTitle ) { m_aTitle = rTitle; } + + const rtl::OUString & getTargetURL() const { return m_aTargetURL; } + void setTargetURL( const rtl::OUString & rURL ) { m_aTargetURL = rURL; } + + Type getType() const + { return ( m_aType != NONE ) ? m_aType + : m_aTargetURL.getLength() + ? LINK + : FOLDER; } + void setType( const Type & rType ) { m_aType = rType; } + +private: + rtl::OUString m_aName; // Name (language independent) + rtl::OUString m_aTitle; // Title (language dependent) + rtl::OUString m_aTargetURL; // Target URL ( links only ) + Type m_aType; // Type +}; + +//========================================================================= + +class HierarchyContentProvider; +class HierarchyUri; + +class HierarchyEntry +{ + ::rtl::OUString m_aServiceSpecifier; + ::rtl::OUString m_aName; + ::rtl::OUString m_aPath; + ::osl::Mutex m_aMutex; + ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory > m_xConfigProvider; + ::com::sun::star::uno::Reference< + ::com::sun::star::container::XHierarchicalNameAccess > + m_xRootReadAccess; + ::com::sun::star::uno::Reference< + ::com::sun::star::util::XOfficeInstallationDirectories > + m_xOfficeInstDirs; + sal_Bool m_bTriedToGetRootReadAccess; // #82494# + +private: + ::rtl::OUString createPathFromHierarchyURL( const HierarchyUri & rURI ); + ::com::sun::star::uno::Reference< + ::com::sun::star::container::XHierarchicalNameAccess > + getRootReadAccess(); + +public: + HierarchyEntry( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + HierarchyContentProvider* pProvider, + const ::rtl::OUString& rURL ); + + sal_Bool hasData(); + + sal_Bool getData( HierarchyEntryData& rData ); + + sal_Bool setData( const HierarchyEntryData& rData, sal_Bool bCreate ); + + sal_Bool move( const ::rtl::OUString& rNewURL, + const HierarchyEntryData& rData ); + + sal_Bool remove(); + + // Iteration. + + struct iterator_Impl; + + class iterator + { + friend class HierarchyEntry; + + iterator_Impl* m_pImpl; + + public: + iterator(); + ~iterator(); + + const HierarchyEntryData& operator*() const; + }; + + sal_Bool first( iterator& it ); + sal_Bool next ( iterator& it ); +}; + +} // namespace hierarchy_ucp + +#endif /* !_HIERARCHYDATA_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchydatasource.cxx b/ucb/source/ucp/hierarchy/hierarchydatasource.cxx new file mode 100644 index 000000000000..467259caf0eb --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydatasource.cxx @@ -0,0 +1,1116 @@ +/************************************************************************* + * + * 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 + ************************************************************************** + + Note: Configuration Management classes do not support XAggregation. + So I have to wrap the interesting interfaces manually. + + *************************************************************************/ +#include "hierarchydatasource.hxx" +#include <osl/diagnose.h> + +#include "osl/doublecheckedlocking.h" +#include <cppuhelper/interfacecontainer.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/util/XChangesBatch.hpp> +#include <com/sun/star/util/XChangesNotifier.hpp> + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= + +// describe path of cfg entry +#define CFGPROPERTY_NODEPATH "nodepath" +// true->async. update; false->sync. update +#define CFGPROPERTY_LAZYWRITE "lazywrite" + +#define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess" +#define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess" + +#define CONFIG_PROVIDER_SERVICE_NAME \ + "com.sun.star.configuration.ConfigurationProvider" +#define CONFIG_READ_SERVICE_NAME \ + "com.sun.star.configuration.ConfigurationAccess" +#define CONFIG_READWRITE_SERVICE_NAME \ + "com.sun.star.configuration.ConfigurationUpdateAccess" +#define CONFIG_DATA_ROOT_KEY \ + "/org.openoffice.ucb.Hierarchy/Root" + +//========================================================================= + +namespace hcp_impl +{ + +//========================================================================= +// +// HierarchyDataReadAccess Implementation. +// +//========================================================================= + +class HierarchyDataAccess : public cppu::OWeakObject, + public lang::XServiceInfo, + public lang::XTypeProvider, + public lang::XComponent, + public lang::XSingleServiceFactory, + public container::XHierarchicalNameAccess, + public container::XNameContainer, + public util::XChangesNotifier, + public util::XChangesBatch +{ + osl::Mutex m_aMutex; + uno::Reference< uno::XInterface > m_xConfigAccess; + uno::Reference< lang::XComponent > m_xCfgC; + uno::Reference< lang::XSingleServiceFactory > m_xCfgSSF; + uno::Reference< container::XHierarchicalNameAccess > m_xCfgHNA; + uno::Reference< container::XNameContainer > m_xCfgNC; + uno::Reference< container::XNameReplace > m_xCfgNR; + uno::Reference< container::XNameAccess > m_xCfgNA; + uno::Reference< container::XElementAccess > m_xCfgEA; + uno::Reference< util::XChangesNotifier > m_xCfgCN; + uno::Reference< util::XChangesBatch > m_xCfgCB; + bool m_bReadOnly; + +public: + HierarchyDataAccess( const uno::Reference< + uno::XInterface > & xConfigAccess, + bool bReadOnly ); + virtual ~HierarchyDataAccess(); + + // XInterface + XINTERFACE_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XComponent + virtual void SAL_CALL + dispose() + throw ( uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const uno::Reference< lang::XEventListener > & xListener ) + throw ( uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const uno::Reference< + lang::XEventListener > & aListener ) + throw ( uno::RuntimeException ); + + // XSingleServiceFactory + virtual uno::Reference< uno::XInterface > SAL_CALL + createInstance() + throw ( uno::Exception, uno::RuntimeException ); + virtual uno::Reference< uno::XInterface > SAL_CALL + createInstanceWithArguments( const uno::Sequence< uno::Any > & aArguments ) + throw ( uno::Exception, uno::RuntimeException ); + + // XHierarchicalNameAccess + virtual uno::Any SAL_CALL + getByHierarchicalName( const rtl::OUString & aName ) + throw ( container::NoSuchElementException, uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasByHierarchicalName( const rtl::OUString & aName ) + throw ( uno::RuntimeException ); + + // XNameContainer + virtual void SAL_CALL + insertByName( const rtl::OUString & aName, const uno::Any & aElement ) + throw ( lang::IllegalArgumentException, + container::ElementExistException, + lang::WrappedTargetException, + uno::RuntimeException ); + virtual void SAL_CALL + removeByName( const rtl::OUString & Name ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ); + + // XNameReplace ( base of XNameContainer ) + virtual void SAL_CALL + replaceByName( const rtl::OUString & aName, const uno::Any & aElement ) + throw ( lang::IllegalArgumentException, + container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ); + + // XNameAccess ( base of XNameReplace ) + virtual uno::Any SAL_CALL + getByName( const rtl::OUString & aName ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ); + virtual uno::Sequence< rtl::OUString > SAL_CALL + getElementNames() + throw ( uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasByName( const rtl::OUString & aName ) + throw ( uno::RuntimeException ); + + // XElementAccess ( base of XNameAccess ) + virtual uno::Type SAL_CALL + getElementType() + throw ( uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasElements() + throw ( uno::RuntimeException ); + + // XChangesNotifier + virtual void SAL_CALL + addChangesListener( const uno::Reference< + util::XChangesListener > & aListener ) + throw ( uno::RuntimeException ); + virtual void SAL_CALL + removeChangesListener( const uno::Reference< + util::XChangesListener > & aListener ) + throw ( uno::RuntimeException ); + + // XChangesBatch + virtual void SAL_CALL + commitChanges() + throw ( lang::WrappedTargetException, uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasPendingChanges() + throw ( uno::RuntimeException ); + virtual uno::Sequence< util::ElementChange > SAL_CALL + getPendingChanges() + throw ( uno::RuntimeException ); +}; + +} // namespace hcp_impl + +using namespace hcp_impl; + +//========================================================================= +//========================================================================= +// +// HierarchyDataSource Implementation. +// +//========================================================================= +//========================================================================= + +HierarchyDataSource::HierarchyDataSource( + const uno::Reference< lang::XMultiServiceFactory > & rxServiceMgr ) +: m_xSMgr( rxServiceMgr ), + m_pDisposeEventListeners( 0 ) +{ +} + +//========================================================================= +// virtual +HierarchyDataSource::~HierarchyDataSource() +{ + delete m_pDisposeEventListeners; +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_4( HierarchyDataSource, + lang::XTypeProvider, + lang::XServiceInfo, + lang::XComponent, + lang::XMultiServiceFactory ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_4( HierarchyDataSource, + lang::XTypeProvider, + lang::XServiceInfo, + lang::XComponent, + lang::XMultiServiceFactory ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_0( HierarchyDataSource, + rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.HierarchyDataSource" ) ) +{ + uno::Sequence< rtl::OUString > aSNS( 2 ); + aSNS[ 0 ] = rtl::OUString::createFromAscii( + "com.sun.star.ucb.DefaultHierarchyDataSource" ); + aSNS[ 1 ] = rtl::OUString::createFromAscii( + "com.sun.star.ucb.HierarchyDataSource" ); + return aSNS; +} + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( HierarchyDataSource ); + +//========================================================================= +// +// XComponent methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyDataSource::dispose() + throw( uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) + { + lang::EventObject aEvt; + aEvt.Source = static_cast< lang::XComponent * >( this ); + m_pDisposeEventListeners->disposeAndClear( aEvt ); + } +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyDataSource::addEventListener( + const uno::Reference< lang::XEventListener > & Listener ) + throw( uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( !m_pDisposeEventListeners ) + m_pDisposeEventListeners + = new cppu::OInterfaceContainerHelper( m_aMutex ); + + m_pDisposeEventListeners->addInterface( Listener ); +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyDataSource::removeEventListener( + const uno::Reference< lang::XEventListener > & Listener ) + throw( uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_pDisposeEventListeners ) + m_pDisposeEventListeners->removeInterface( Listener ); +} + +//========================================================================= +// +// XMultiServiceFactory methods. +// +//========================================================================= + +// virtual +uno::Reference< uno::XInterface > SAL_CALL +HierarchyDataSource::createInstance( const rtl::OUString & aServiceSpecifier ) + throw ( uno::Exception, uno::RuntimeException ) +{ + // Create view to root node. + + beans::PropertyValue aProp; + aProp.Name = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( CFGPROPERTY_NODEPATH ) ); + aProp.Value <<= + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIG_DATA_ROOT_KEY ) ); + + uno::Sequence< uno::Any > aArguments( 1 ); + aArguments[ 0 ] <<= aProp; + + return createInstanceWithArguments( aServiceSpecifier, aArguments, false ); +} + +//========================================================================= +// virtual +uno::Reference< uno::XInterface > SAL_CALL +HierarchyDataSource::createInstanceWithArguments( + const rtl::OUString & ServiceSpecifier, + const uno::Sequence< uno::Any > & Arguments ) + throw ( uno::Exception, uno::RuntimeException ) +{ + return createInstanceWithArguments( ServiceSpecifier, Arguments, true ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL +HierarchyDataSource::getAvailableServiceNames() + throw ( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aNames( 2 ); + aNames[ 0 ] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( READ_SERVICE_NAME ) ); + aNames[ 1 ] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( READWRITE_SERVICE_NAME ) ); + return aNames; +} + +//========================================================================= +// +// Non-interface methods +// +//========================================================================= + +uno::Reference< uno::XInterface > SAL_CALL +HierarchyDataSource::createInstanceWithArguments( + const rtl::OUString & ServiceSpecifier, + const uno::Sequence< uno::Any > & Arguments, + bool bCheckArgs ) + throw ( uno::Exception, uno::RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + // Check service specifier. + bool bReadOnly = !!ServiceSpecifier.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( READ_SERVICE_NAME ) ); + bool bReadWrite = !bReadOnly && + ServiceSpecifier.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( READWRITE_SERVICE_NAME ) ); + + if ( !bReadOnly && !bReadWrite ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "Unsupported service specifier!" ); + return uno::Reference< uno::XInterface >(); + } + + uno::Sequence< uno::Any > aNewArgs( Arguments ); + + bool bHasLazyWriteProp = bReadOnly; // property must be added only if + // a writable view is requested. + if ( bCheckArgs ) + { + // Check arguments. + bool bHasNodePath = false; + sal_Int32 nCount = Arguments.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + beans::PropertyValue aProp; + if ( Arguments[ n ] >>= aProp ) + { + if ( aProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( CFGPROPERTY_NODEPATH ) ) ) + { + rtl::OUString aPath; + if ( aProp.Value >>= aPath ) + { + bHasNodePath = true; + + // Create path to data inside the configuration. + rtl::OUString aConfigPath; + if ( !createConfigPath( aPath, aConfigPath ) ) + { + OSL_ENSURE( false, + "HierarchyDataSource::" + "createInstanceWithArguments - " + "Invalid node path!" ); + return uno::Reference< uno::XInterface >(); + } + + aProp.Value <<= aConfigPath; + + // Set new path in arguments. + aNewArgs[ n ] <<= aProp; + + if ( bHasLazyWriteProp ) + break; + } + else + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "Invalid type for property 'nodepath'!" ); + return uno::Reference< uno::XInterface >(); + } + } + else if ( aProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + CFGPROPERTY_LAZYWRITE ) ) ) + { + if ( aProp.Value.getValueType() == getCppuBooleanType() ) + { + bHasLazyWriteProp = true; + + if ( bHasNodePath ) + break; + } + else + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "Invalid type for property 'lazywrite'!" ); + return uno::Reference< uno::XInterface >(); + } + } + } + } + + if ( !bHasNodePath ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "No 'nodepath' property!" ); + return uno::Reference< uno::XInterface >(); + } + } + + // Create Configuration Provider. + uno::Reference< lang::XMultiServiceFactory > xProv = getConfigProvider(); + if ( !xProv.is() ) + return uno::Reference< uno::XInterface >(); + + uno::Reference< uno::XInterface > xConfigAccess; + try + { + if ( bReadOnly ) + { + // Create configuration read-only access object. + xConfigAccess = xProv->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CONFIG_READ_SERVICE_NAME ) ), + aNewArgs ); + } + else + { + // Append 'lazywrite' property value, if not already present. + if ( !bHasLazyWriteProp ) + { + sal_Int32 nLen = aNewArgs.getLength(); + aNewArgs.realloc( nLen + 1 ); + + beans::PropertyValue aProp; + aProp.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CFGPROPERTY_LAZYWRITE ) ); + aProp.Value <<= sal_True; + aNewArgs[ nLen ] <<= aProp; + } + + // Create configuration read-write access object. + xConfigAccess = xProv->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + CONFIG_READWRITE_SERVICE_NAME ) ), + aNewArgs ); + } + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "Cannot instanciate configuration access!" ); + throw; + } + + if ( !xConfigAccess.is() ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createInstanceWithArguments - " + "Cannot instanciate configuration access!" ); + return xConfigAccess; + } + + return uno::Reference< uno::XInterface >( + static_cast< cppu::OWeakObject * >( + new HierarchyDataAccess( xConfigAccess, bReadOnly ) ) ); +} + +//========================================================================= +uno::Reference< lang::XMultiServiceFactory > +HierarchyDataSource::getConfigProvider() +{ + if ( !m_xConfigProvider.is() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + if ( !m_xConfigProvider.is() ) + { + try + { + m_xConfigProvider + = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + CONFIG_PROVIDER_SERVICE_NAME ) ) ), + uno::UNO_QUERY ); + + OSL_ENSURE( m_xConfigProvider.is(), + "HierarchyDataSource::getConfigProvider - " + "No configuration provider!" ); + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( false, + "HierarchyDataSource::getConfigProvider - " + "caught exception!" ); + } + } + } + + return m_xConfigProvider; +} + +//========================================================================= +bool HierarchyDataSource::createConfigPath( + const rtl::OUString & rInPath, rtl::OUString & rOutPath ) +{ + if ( rInPath.getLength() ) + { + if ( rInPath.indexOf( '/' ) == 0 ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createConfigPath - " + "Leading slash in node path!" ); + return false; + } + + if ( rInPath.lastIndexOf( '/' ) == rInPath.getLength() - 1 ) + { + OSL_ENSURE( false, + "HierarchyDataSource::createConfigPath - " + "Trailing slash in node path!" ); + return false; + } + + rtl::OUString aOutPath( + RTL_CONSTASCII_USTRINGPARAM( CONFIG_DATA_ROOT_KEY "/" ) ); + aOutPath += rInPath; + rOutPath = aOutPath; + } + else + { + rOutPath = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( CONFIG_DATA_ROOT_KEY ) ); + } + + return true; +} + +//========================================================================= +//========================================================================= +// +// HierarchyDataAccess Implementation. +// +//========================================================================= +//========================================================================= + +#define ENSURE_ORIG_INTERFACE( interface_name, member_name ) \ + m_xCfg##member_name; \ + if ( !m_xCfg##member_name.is() ) \ + { \ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); \ + if ( !m_xCfg##member_name.is() ) \ + m_xCfg##member_name \ + = uno::Reference< interface_name >( \ + m_xConfigAccess, uno::UNO_QUERY ); \ + xOrig = m_xCfg##member_name; \ + } + +//========================================================================= +HierarchyDataAccess::HierarchyDataAccess( const uno::Reference< + uno::XInterface > & xConfigAccess, + bool bReadOnly ) +: m_xConfigAccess( xConfigAccess ), + m_bReadOnly( bReadOnly ) +{ +} + +//========================================================================= +// virtual +HierarchyDataAccess::~HierarchyDataAccess() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_COMMON_IMPL( HierarchyDataAccess ); + +//========================================================================= +// virtual +uno::Any SAL_CALL HierarchyDataAccess::queryInterface( const uno::Type & aType ) + throw ( uno::RuntimeException ) +{ + // Interfaces supported in read-only and read-write mode. + uno::Any aRet = cppu::queryInterface( aType, + static_cast< lang::XTypeProvider * >( this ), + static_cast< lang::XServiceInfo * >( this ), + static_cast< lang::XComponent * >( this ), + static_cast< container::XHierarchicalNameAccess * >( this ), + static_cast< container::XNameAccess * >( this ), + static_cast< container::XElementAccess * >( this ), + static_cast< util::XChangesNotifier * >( this ) ); + + // Interfaces supported only in read-write mode. + if ( !aRet.hasValue() && !m_bReadOnly ) + { + aRet = cppu::queryInterface( aType, + static_cast< lang::XSingleServiceFactory * >( this ), + static_cast< container::XNameContainer * >( this ), + static_cast< container::XNameReplace * >( this ), + static_cast< util::XChangesBatch * >( this ) ); + } + + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( aType ); +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_COMMON_IMPL( HierarchyDataAccess ); + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL HierarchyDataAccess::getTypes() + throw( uno::RuntimeException ) +{ + cppu::OTypeCollection * pCollection = 0; + + if ( m_bReadOnly ) + { + static cppu::OTypeCollection* pReadOnlyTypes = 0; + + pCollection = pReadOnlyTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pReadOnlyTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( container::XHierarchicalNameAccess ), + CPPU_TYPE_REF( container::XNameAccess ), + CPPU_TYPE_REF( util::XChangesNotifier ) ); + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pReadOnlyTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + else + { + static cppu::OTypeCollection* pReadWriteTypes = 0; + + pCollection = pReadWriteTypes; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + + pCollection = pReadWriteTypes; + if ( !pCollection ) + { + static cppu::OTypeCollection aCollection( + CPPU_TYPE_REF( lang::XTypeProvider ), + CPPU_TYPE_REF( lang::XServiceInfo ), + CPPU_TYPE_REF( lang::XComponent ), + CPPU_TYPE_REF( lang::XSingleServiceFactory ), + CPPU_TYPE_REF( container::XHierarchicalNameAccess ), + CPPU_TYPE_REF( container::XNameContainer ), + CPPU_TYPE_REF( util::XChangesBatch ), + CPPU_TYPE_REF( util::XChangesNotifier ) ); + pCollection = &aCollection; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pReadWriteTypes = pCollection; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + } + + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_NOFACTORY_IMPL_0( + HierarchyDataAccess, + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.ucb.HierarchyDataAccess" ) ) ) +{ + uno::Sequence< rtl::OUString > aSNS( 2 ); + aSNS[ 0 ] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( READ_SERVICE_NAME ) ); + aSNS[ 1 ] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( READWRITE_SERVICE_NAME ) ); + return aSNS; +} + +//========================================================================= +// +// XComponent methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyDataAccess::dispose() + throw ( uno::RuntimeException ) +{ + uno::Reference< lang::XComponent > xOrig + = ENSURE_ORIG_INTERFACE( lang::XComponent, C ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XComponent!" ); + xOrig->dispose(); +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyDataAccess::addEventListener( + const uno::Reference< lang::XEventListener > & xListener ) + throw ( uno::RuntimeException ) +{ + uno::Reference< lang::XComponent > xOrig + = ENSURE_ORIG_INTERFACE( lang::XComponent, C ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XComponent!" ); + xOrig->addEventListener( xListener ); +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyDataAccess::removeEventListener( + const uno::Reference< lang::XEventListener > & aListener ) + throw ( uno::RuntimeException ) +{ + uno::Reference< lang::XComponent > xOrig + = ENSURE_ORIG_INTERFACE( lang::XComponent, C ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XComponent!" ); + xOrig->removeEventListener( aListener ); +} + +//========================================================================= +// +// XHierarchicalNameAccess methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL HierarchyDataAccess::getByHierarchicalName( + const rtl::OUString & aName ) + throw ( container::NoSuchElementException, uno::RuntimeException ) +{ + uno::Reference< container::XHierarchicalNameAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XHierarchicalNameAccess, HNA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : " + "Data source is not an XHierarchicalNameAccess!" ); + return xOrig->getByHierarchicalName( aName ); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL HierarchyDataAccess::hasByHierarchicalName( + const rtl::OUString & aName ) + throw ( uno::RuntimeException ) +{ + uno::Reference< container::XHierarchicalNameAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XHierarchicalNameAccess, HNA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : " + "Data source is not an XHierarchicalNameAccess!" ); + return xOrig->hasByHierarchicalName( aName ); +} + +//========================================================================= +// +// XNameAccess methods. +// +//========================================================================= + +// virtual +uno::Any SAL_CALL HierarchyDataAccess::getByName( const rtl::OUString & aName ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< container::XNameAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameAccess!" ); + return xOrig->getByName( aName ); +} + +//========================================================================= +// virtual +uno::Sequence< rtl::OUString > SAL_CALL HierarchyDataAccess::getElementNames() + throw ( uno::RuntimeException ) +{ + uno::Reference< container::XNameAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameAccess!" ); + return xOrig->getElementNames(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL HierarchyDataAccess::hasByName( const rtl::OUString & aName ) + throw ( uno::RuntimeException ) +{ + uno::Reference< container::XNameAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameAccess!" ); + return xOrig->hasByName( aName ); +} + +//========================================================================= +// +// XElementAccess methods. +// +//========================================================================= + +// virtual +uno::Type SAL_CALL HierarchyDataAccess::getElementType() + throw ( uno::RuntimeException ) +{ + uno::Reference< container::XElementAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XElementAccess, EA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XElementAccess!" ); + return xOrig->getElementType(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL HierarchyDataAccess::hasElements() + throw ( uno::RuntimeException ) +{ + uno::Reference< container::XElementAccess > xOrig + = ENSURE_ORIG_INTERFACE( container::XElementAccess, EA ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XElementAccess!" ); + return xOrig->hasElements(); +} + +//========================================================================= +// +// XChangesNotifier methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyDataAccess::addChangesListener( + const uno::Reference< util::XChangesListener > & aListener ) + throw ( uno::RuntimeException ) +{ + uno::Reference< util::XChangesNotifier > xOrig + = ENSURE_ORIG_INTERFACE( util::XChangesNotifier, CN ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XChangesNotifier!" ); + xOrig->addChangesListener( aListener ); +} + +//========================================================================= +// virtual +void SAL_CALL HierarchyDataAccess::removeChangesListener( + const uno::Reference< util::XChangesListener > & aListener ) + throw ( uno::RuntimeException ) +{ + uno::Reference< util::XChangesNotifier > xOrig + = ENSURE_ORIG_INTERFACE( util::XChangesNotifier, CN ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XChangesNotifier!" ); + xOrig->removeChangesListener( aListener ); +} + +//========================================================================= +// +// XSingleServiceFactory methods. +// +//========================================================================= + +// virtual +uno::Reference< uno::XInterface > SAL_CALL HierarchyDataAccess::createInstance() + throw ( uno::Exception, uno::RuntimeException ) +{ + uno::Reference< lang::XSingleServiceFactory > xOrig + = ENSURE_ORIG_INTERFACE( lang::XSingleServiceFactory, SSF ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XSingleServiceFactory!" ); + return xOrig->createInstance(); +} + +//========================================================================= +// virtual +uno::Reference< uno::XInterface > SAL_CALL +HierarchyDataAccess::createInstanceWithArguments( + const uno::Sequence< uno::Any > & aArguments ) + throw ( uno::Exception, uno::RuntimeException ) +{ + uno::Reference< lang::XSingleServiceFactory > xOrig + = ENSURE_ORIG_INTERFACE( lang::XSingleServiceFactory, SSF ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XSingleServiceFactory!" ); + return xOrig->createInstanceWithArguments( aArguments ); +} + +//========================================================================= +// +// XNameContainer methods. +// +//========================================================================= + +// virtual +void SAL_CALL +HierarchyDataAccess::insertByName( const rtl::OUString & aName, + const uno::Any & aElement ) + throw ( lang::IllegalArgumentException, + container::ElementExistException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< container::XNameContainer > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameContainer, NC ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameContainer!" ); + xOrig->insertByName( aName, aElement ); +} + +//========================================================================= +// virtual +void SAL_CALL +HierarchyDataAccess::removeByName( const rtl::OUString & Name ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< container::XNameContainer > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameContainer, NC ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameContainer!" ); + xOrig->removeByName( Name ); +} + +//========================================================================= +// +// XNameReplace methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyDataAccess::replaceByName( const rtl::OUString & aName, + const uno::Any & aElement ) + throw ( lang::IllegalArgumentException, + container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< container::XNameReplace > xOrig + = ENSURE_ORIG_INTERFACE( container::XNameReplace, NR ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XNameReplace!" ); + xOrig->replaceByName( aName, aElement ); +} + +//========================================================================= +// +// XChangesBatch methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyDataAccess::commitChanges() + throw ( lang::WrappedTargetException, uno::RuntimeException ) +{ + uno::Reference< util::XChangesBatch > xOrig + = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XChangesBatch!" ); + xOrig->commitChanges(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL HierarchyDataAccess::hasPendingChanges() + throw ( uno::RuntimeException ) +{ + uno::Reference< util::XChangesBatch > xOrig + = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XChangesBatch!" ); + return xOrig->hasPendingChanges(); +} + +//========================================================================= +// virtual +uno::Sequence< util::ElementChange > SAL_CALL +HierarchyDataAccess::getPendingChanges() + throw ( uno::RuntimeException ) +{ + uno::Reference< util::XChangesBatch > xOrig + = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB ); + + OSL_ENSURE( xOrig.is(), + "HierarchyDataAccess : Data source is not an XChangesBatch!" ); + return xOrig->getPendingChanges(); +} + diff --git a/ucb/source/ucp/hierarchy/hierarchydatasource.hxx b/ucb/source/ucp/hierarchy/hierarchydatasource.hxx new file mode 100644 index 000000000000..329011e142db --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydatasource.hxx @@ -0,0 +1,125 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _HIERARCHYDATASOURCE_HXX +#define _HIERARCHYDATASOURCE_HXX + +#include <osl/mutex.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <cppuhelper/weak.hxx> +#include <ucbhelper/macros.hxx> + +namespace cppu { class OInterfaceContainerHelper; } + +namespace hierarchy_ucp { + +//========================================================================= + +class HierarchyDataSource : public cppu::OWeakObject, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XComponent, + public com::sun::star::lang::XMultiServiceFactory +{ + osl::Mutex m_aMutex; + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xConfigProvider; + cppu::OInterfaceContainerHelper * m_pDisposeEventListeners; + +public: + HierarchyDataSource( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & + rxServiceMgr ); + virtual ~HierarchyDataSource(); + + // XInterface + XINTERFACE_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XComponent + virtual void SAL_CALL + dispose() + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener > & xListener ) + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener > & aListener ) + throw ( com::sun::star::uno::RuntimeException ); + + // XMultiServiceFactory + virtual com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > SAL_CALL + createInstance( const rtl::OUString & aServiceSpecifier ) + throw ( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > SAL_CALL + createInstanceWithArguments( const rtl::OUString & ServiceSpecifier, + const com::sun::star::uno::Sequence< + com::sun::star::uno::Any > & Arguments ) + throw ( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getAvailableServiceNames() + throw ( com::sun::star::uno::RuntimeException ); + + // Non-Interface methods + +private: + com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > SAL_CALL + createInstanceWithArguments( const rtl::OUString & ServiceSpecifier, + const com::sun::star::uno::Sequence< + com::sun::star::uno::Any > & Arguments, + bool bCheckArgs ) + throw ( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > + getConfigProvider(); + + bool + createConfigPath( const rtl::OUString & rInPath, rtl::OUString & rOutPath ); +}; + +} // namespace hierarchy_ucp + +#endif /* !_HIERARCHYDATASOURCE_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchydatasupplier.cxx b/ucb/source/ucp/hierarchy/hierarchydatasupplier.cxx new file mode 100644 index 000000000000..8cd53a4a6201 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydatasupplier.cxx @@ -0,0 +1,446 @@ +/************************************************************************* + * + * 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 + ************************************************************************** + + *************************************************************************/ + +#include <vector> +#include <ucbhelper/contentidentifier.hxx> +#include "hierarchydatasupplier.hxx" +#include "hierarchyprovider.hxx" +#include "hierarchycontent.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +namespace hierarchy_ucp +{ + +//========================================================================= +// +// struct ResultListEntry. +// +//========================================================================= + +struct ResultListEntry +{ + rtl::OUString aId; + uno::Reference< ucb::XContentIdentifier > xId; + uno::Reference< ucb::XContent > xContent; + uno::Reference< sdbc::XRow > xRow; + HierarchyEntryData aData; + + ResultListEntry( const HierarchyEntryData& rEntry ) : aData( rEntry ) {} +}; + +//========================================================================= +// +// ResultList. +// +//========================================================================= + +typedef std::vector< ResultListEntry* > ResultList; + +//========================================================================= +// +// struct DataSupplier_Impl. +// +//========================================================================= + +struct DataSupplier_Impl +{ + osl::Mutex m_aMutex; + ResultList m_aResults; + rtl::Reference< HierarchyContent > m_xContent; + uno::Reference< lang::XMultiServiceFactory > m_xSMgr; + HierarchyEntry m_aFolder; + HierarchyEntry::iterator m_aIterator; + sal_Int32 m_nOpenMode; + sal_Bool m_bCountFinal; + + DataSupplier_Impl( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< HierarchyContent >& rContent, + sal_Int32 nOpenMode ) + : m_xContent( rContent ), m_xSMgr( rxSMgr ), + m_aFolder( rxSMgr, + static_cast< HierarchyContentProvider * >( + rContent->getProvider().get() ), + rContent->getIdentifier()->getContentIdentifier() ), + m_nOpenMode( nOpenMode ), m_bCountFinal( sal_False ) {} + ~DataSupplier_Impl(); +}; + +//========================================================================= +DataSupplier_Impl::~DataSupplier_Impl() +{ + ResultList::const_iterator it = m_aResults.begin(); + ResultList::const_iterator end = m_aResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } +} + +} + +//========================================================================= +//========================================================================= +// +// HierarchyResultSetDataSupplier Implementation. +// +//========================================================================= +//========================================================================= + +HierarchyResultSetDataSupplier::HierarchyResultSetDataSupplier( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< HierarchyContent >& rContent, + sal_Int32 nOpenMode ) +: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) +{ +} + +//========================================================================= +// virtual +HierarchyResultSetDataSupplier::~HierarchyResultSetDataSupplier() +{ + delete m_pImpl; +} + +//========================================================================= +// virtual +rtl::OUString HierarchyResultSetDataSupplier::queryContentIdentifierString( + sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId; + if ( aId.getLength() ) + { + // Already cached. + return aId; + } + } + + if ( getResult( nIndex ) ) + { + rtl::OUString aId + = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(); + + if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() ) + aId += rtl::OUString::createFromAscii( "/" ); + + aId += m_pImpl->m_aResults[ nIndex ]->aData.getName(); + + m_pImpl->m_aResults[ nIndex ]->aId = aId; + return aId; + } + return rtl::OUString(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContentIdentifier > +HierarchyResultSetDataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = m_pImpl->m_aResults[ nIndex ]->xId; + if ( xId.is() ) + { + // Already cached. + return xId; + } + } + + rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( aId ); + m_pImpl->m_aResults[ nIndex ]->xId = xId; + return xId; + } + return uno::Reference< ucb::XContentIdentifier >(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > +HierarchyResultSetDataSupplier::queryContent( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_aResults[ nIndex ]->xContent; + if ( xContent.is() ) + { + // Already cached. + return xContent; + } + } + + uno::Reference< ucb::XContentIdentifier > xId + = queryContentIdentifier( nIndex ); + if ( xId.is() ) + { + try + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_xContent->getProvider()->queryContent( xId ); + m_pImpl->m_aResults[ nIndex ]->xContent = xContent; + return xContent; + + } + catch ( ucb::IllegalIdentifierException const & ) + { + } + } + return uno::Reference< ucb::XContent >(); +} + +//========================================================================= +// virtual +sal_Bool HierarchyResultSetDataSupplier::getResult( sal_uInt32 nIndex ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aResults.size() > nIndex ) + { + // Result already present. + return sal_True; + } + + // Result not (yet) present. + + if ( m_pImpl->m_bCountFinal ) + return sal_False; + + // Try to obtain result... + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + sal_Bool bFound = sal_False; + sal_uInt32 nPos = nOldCount; + + while ( m_pImpl->m_aFolder.next( m_pImpl->m_aIterator ) ) + { + const HierarchyEntryData& rResult = *m_pImpl->m_aIterator; + if ( checkResult( rResult ) ) + { + m_pImpl->m_aResults.push_back( new ResultListEntry( rResult ) ); + + if ( nPos == nIndex ) + { + // Result obtained. + bFound = sal_True; + break; + } + } + nPos++; + } + + if ( !bFound ) + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + if ( m_pImpl->m_bCountFinal ) + xResultSet->rowCountFinal(); + } + + return bFound; +} + +//========================================================================= +// virtual +sal_uInt32 HierarchyResultSetDataSupplier::totalCount() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_bCountFinal ) + return m_pImpl->m_aResults.size(); + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + + while ( m_pImpl->m_aFolder.next( m_pImpl->m_aIterator ) ) + { + const HierarchyEntryData& rResult = *m_pImpl->m_aIterator; + if ( checkResult( rResult ) ) + m_pImpl->m_aResults.push_back( new ResultListEntry( rResult ) ); + } + + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + xResultSet->rowCountFinal(); + } + + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_uInt32 HierarchyResultSetDataSupplier::currentCount() +{ + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_Bool HierarchyResultSetDataSupplier::isCountFinal() +{ + return m_pImpl->m_bCountFinal; +} + +//========================================================================= +// virtual +uno::Reference< sdbc::XRow > +HierarchyResultSetDataSupplier::queryPropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< sdbc::XRow > xRow + = m_pImpl->m_aResults[ nIndex ]->xRow; + if ( xRow.is() ) + { + // Already cached. + return xRow; + } + } + + if ( getResult( nIndex ) ) + { + static rtl::OUString aFolderType( + rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) ); + static rtl::OUString aLinkType( + rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ) ); + + HierarchyContentProperties aData( + m_pImpl->m_aResults[ nIndex ]->aData ); + + uno::Reference< sdbc::XRow > xRow + = HierarchyContent::getPropertyValues( + m_pImpl->m_xSMgr, + getResultSet()->getProperties(), + aData, + static_cast< HierarchyContentProvider * >( + m_pImpl->m_xContent->getProvider().get() ), + queryContentIdentifierString( nIndex ) ); + m_pImpl->m_aResults[ nIndex ]->xRow = xRow; + return xRow; + } + + return uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void HierarchyResultSetDataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void HierarchyResultSetDataSupplier::close() +{ +} + +//========================================================================= +// virtual +void HierarchyResultSetDataSupplier::validate() + throw( ucb::ResultSetException ) +{ +} + +//========================================================================= +sal_Bool HierarchyResultSetDataSupplier::checkResult( + const HierarchyEntryData& rResult ) +{ + switch ( m_pImpl->m_nOpenMode ) + { + case ucb::OpenMode::FOLDERS: + if ( rResult.getType() == HierarchyEntryData::LINK ) + { + // Entry is a link. + return sal_False; + } + break; + + case ucb::OpenMode::DOCUMENTS: + if ( rResult.getType() == HierarchyEntryData::FOLDER ) + { + // Entry is a folder. + return sal_False; + } + break; + + case ucb::OpenMode::ALL: + default: + break; + } + + return sal_True; +} + diff --git a/ucb/source/ucp/hierarchy/hierarchydatasupplier.hxx b/ucb/source/ucp/hierarchy/hierarchydatasupplier.hxx new file mode 100644 index 000000000000..87218e0729d0 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchydatasupplier.hxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _HIERARCHYDATASUPPLIER_HXX +#define _HIERARCHYDATASUPPLIER_HXX + +#include <rtl/ref.hxx> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <ucbhelper/resultset.hxx> + +namespace hierarchy_ucp { + +class HierarchyEntryData; +struct DataSupplier_Impl; +class HierarchyContent; + +class HierarchyResultSetDataSupplier : + public ::ucbhelper::ResultSetDataSupplier +{ + DataSupplier_Impl* m_pImpl; + +private: + sal_Bool checkResult( const HierarchyEntryData& rResult ); + +public: + HierarchyResultSetDataSupplier( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< HierarchyContent >& rContent, + sal_Int32 nOpenMode = com::sun::star::ucb::OpenMode::ALL ); + virtual ~HierarchyResultSetDataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); +}; + +} // namespace hierarchy_ucp + +#endif /* !_HIERARCHYDATASUPPLIER_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchyprovider.cxx b/ucb/source/ucp/hierarchy/hierarchyprovider.cxx new file mode 100644 index 000000000000..5ce8ea891f51 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchyprovider.cxx @@ -0,0 +1,338 @@ +/************************************************************************* + * + * 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 + ************************************************************************** + + - XInitialization::initialize does not work any longer! + + *************************************************************************/ +#include <osl/diagnose.h> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/util/XOfficeInstallationDirectories.hpp> +#include <ucbhelper/contentidentifier.hxx> +#include "hierarchyprovider.hxx" +#include "hierarchycontent.hxx" +#include "hierarchyuri.hxx" + +#include "../inc/urihelper.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= +//========================================================================= +// +// HierarchyContentProvider Implementation. +// +//========================================================================= +//========================================================================= + +HierarchyContentProvider::HierarchyContentProvider( + const uno::Reference< lang::XMultiServiceFactory >& rXSMgr ) +: ::ucbhelper::ContentProviderImplHelper( rXSMgr ) +{ +} + +//========================================================================= +// virtual +HierarchyContentProvider::~HierarchyContentProvider() +{ +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_4( HierarchyContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider, + lang::XInitialization ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_4( HierarchyContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider, + lang::XInitialization ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( HierarchyContentProvider, + rtl::OUString::createFromAscii( + "com.sun.star.comp.ucb.HierarchyContentProvider" ), + rtl::OUString::createFromAscii( + HIERARCHY_CONTENT_PROVIDER_SERVICE_NAME ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( HierarchyContentProvider ); + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL +HierarchyContentProvider::queryContent( + const uno::Reference< ucb::XContentIdentifier >& Identifier ) + throw( ucb::IllegalIdentifierException, uno::RuntimeException ) +{ + HierarchyUri aUri( Identifier->getContentIdentifier() ); + if ( !aUri.isValid() ) + throw ucb::IllegalIdentifierException(); + + // Encode URL and create new Id. This may "correct" user-typed-in URL's. + uno::Reference< ucb::XContentIdentifier > xCanonicId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, + ::ucb_impl::urihelper::encodeURI( + aUri.getUri() ) ); + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent + = queryExistingContent( xCanonicId ).get(); + if ( xContent.is() ) + return xContent; + + // Create a new content. + xContent = HierarchyContent::create( m_xSMgr, this, xCanonicId ); + registerNewContent( xContent ); + + if ( xContent.is() && !xContent->getIdentifier().is() ) + throw ucb::IllegalIdentifierException(); + + return xContent; +} + +//========================================================================= +// +// XInitialization methods. +// +//========================================================================= + +// virtual +void SAL_CALL HierarchyContentProvider::initialize( + const uno::Sequence< uno::Any >& aArguments ) + throw( uno::Exception, uno::RuntimeException ) +{ +#if 0 + if ( aArguments.getLength() > 0 ) + { + // Extract config provider from service init args. + aArguments[ 0 ] >>= m_xConfigProvider; + + OSL_ENSURE( m_xConfigProvider.is(), + "HierarchyContentProvider::initialize - " + "No config provider!" ); + } +#else + if ( aArguments.getLength() > 0 ) + OSL_ENSURE( false, + "HierarchyContentProvider::initialize : not supported!" ); +#endif +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +uno::Reference< lang::XMultiServiceFactory > +HierarchyContentProvider::getConfigProvider( + const rtl::OUString & rServiceSpecifier ) +{ + osl::MutexGuard aGuard( m_aMutex ); + ConfigProviderMap::iterator it = m_aConfigProviderMap.find( + rServiceSpecifier ); + if ( it == m_aConfigProviderMap.end() ) + { + try + { + ConfigProviderMapEntry aEntry; + aEntry.xConfigProvider + = uno::Reference< lang::XMultiServiceFactory >( + m_xSMgr->createInstance( rServiceSpecifier ), + uno::UNO_QUERY ); + + if ( aEntry.xConfigProvider.is() ) + { + m_aConfigProviderMap[ rServiceSpecifier ] = aEntry; + return aEntry.xConfigProvider; + } + } + catch ( uno::Exception const & ) + { +// OSL_ENSURE( sal_False, +// "HierarchyContentProvider::getConfigProvider - " +// "caught exception!" ); + } + + OSL_ENSURE( sal_False, + "HierarchyContentProvider::getConfigProvider - " + "No config provider!" ); + + return uno::Reference< lang::XMultiServiceFactory >(); + } + + return (*it).second.xConfigProvider; +} + +//========================================================================= +uno::Reference< container::XHierarchicalNameAccess > +HierarchyContentProvider::getRootConfigReadNameAccess( + const rtl::OUString & rServiceSpecifier ) +{ + osl::MutexGuard aGuard( m_aMutex ); + ConfigProviderMap::iterator it = m_aConfigProviderMap.find( + rServiceSpecifier ); + if ( it != m_aConfigProviderMap.end() ) + { + if ( !( (*it).second.xRootReadAccess.is() ) ) + { + if ( (*it).second.bTriedToGetRootReadAccess ) // #82494# + { + OSL_ENSURE( sal_False, + "HierarchyContentProvider::getRootConfigReadNameAccess - " + "Unable to read any config data! -> #82494#" ); + return uno::Reference< container::XHierarchicalNameAccess >(); + } + + try + { + uno::Reference< lang::XMultiServiceFactory > xConfigProv + = getConfigProvider( rServiceSpecifier ); + + if ( xConfigProv.is() ) + { + uno::Sequence< uno::Any > aArguments( 1 ); + beans::PropertyValue aProperty; + aProperty.Name + = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ); + aProperty.Value <<= rtl::OUString(); // root path + aArguments[ 0 ] <<= aProperty; + + (*it).second.bTriedToGetRootReadAccess = true; + + (*it).second.xRootReadAccess + = uno::Reference< container::XHierarchicalNameAccess >( + xConfigProv->createInstanceWithArguments( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.ucb." + "HierarchyDataReadAccess" ) ), + aArguments ), + uno::UNO_QUERY ); + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + // createInstance, createInstanceWithArguments + + OSL_ENSURE( sal_False, + "HierarchyContentProvider::getRootConfigReadNameAccess - " + "caught Exception!" ); + } + } + } + + return (*it).second.xRootReadAccess; +} + +//========================================================================= +uno::Reference< util::XOfficeInstallationDirectories > +HierarchyContentProvider::getOfficeInstallationDirectories() +{ + if ( !m_xOfficeInstDirs.is() ) + { + osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xOfficeInstDirs.is() ) + { + OSL_ENSURE( m_xSMgr.is(), "No service manager!" ); + + uno::Reference< uno::XComponentContext > xCtx; + uno::Reference< beans::XPropertySet > xPropSet( + m_xSMgr, uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + xPropSet->getPropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ) + >>= xCtx; + } + + OSL_ENSURE( xCtx.is(), + "Unable to obtain component context from " + "service manager!" ); + + if ( xCtx.is() ) + { + xCtx->getValueByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "/singletons/" + "com.sun.star.util.theOfficeInstallationDirectories" ) ) ) + >>= m_xOfficeInstDirs; + +// Be silent. singleton only available in an Office environment. +// OSL_ENSURE( m_xOfficeInstDirs.is(), +// "Unable to obtain office directories singleton!" ); + } + } + } + return m_xOfficeInstDirs; +} + diff --git a/ucb/source/ucp/hierarchy/hierarchyprovider.hxx b/ucb/source/ucp/hierarchy/hierarchyprovider.hxx new file mode 100644 index 000000000000..9212aadf417e --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchyprovider.hxx @@ -0,0 +1,155 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _HIERARCHYPROVIDER_HXX +#define _HIERARCHYPROVIDER_HXX + +#include <hash_map> +#include <ucbhelper/providerhelper.hxx> +#include <com/sun/star/lang/XInitialization.hpp> + +namespace com { namespace sun { namespace star { + namespace container { + class XHierarchicalNameAccess; + } + namespace util { + class XOfficeInstallationDirectories; + } +} } } + +namespace hierarchy_ucp { + +//========================================================================= + +#define HIERARCHY_CONTENT_PROVIDER_SERVICE_NAME \ + "com.sun.star.ucb.HierarchyContentProvider" +#define HIERARCHY_CONTENT_PROVIDER_SERVICE_NAME_LENGTH 41 + +#define HIERARCHY_URL_SCHEME \ + "vnd.sun.star.hier" +#define HIERARCHY_URL_SCHEME_LENGTH 17 + +#define HIERARCHY_FOLDER_CONTENT_TYPE \ + "application/" HIERARCHY_URL_SCHEME "-folder" +#define HIERARCHY_LINK_CONTENT_TYPE \ + "application/" HIERARCHY_URL_SCHEME "-link" + +//========================================================================= + +struct ConfigProviderMapEntry +{ + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > xConfigProvider; + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > xRootReadAccess; + bool bTriedToGetRootReadAccess; // #82494# + + ConfigProviderMapEntry() : bTriedToGetRootReadAccess( false ) {} +}; + +struct equalString +{ + bool operator()( + const rtl::OUString& rKey1, const rtl::OUString& rKey2 ) const + { + return !!( rKey1 == rKey2 ); + } +}; + +struct hashString +{ + size_t operator()( const rtl::OUString & rName ) const + { + return rName.hashCode(); + } +}; + +typedef std::hash_map +< + rtl::OUString, // servcie specifier + ConfigProviderMapEntry, + hashString, + equalString +> +ConfigProviderMap; + +//========================================================================= + +class HierarchyContentProvider : public ::ucbhelper::ContentProviderImplHelper, + public com::sun::star::lang::XInitialization +{ + ConfigProviderMap m_aConfigProviderMap; + com::sun::star::uno::Reference< + com::sun::star::util::XOfficeInstallationDirectories > m_xOfficeInstDirs; + +public: + HierarchyContentProvider( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + virtual ~HierarchyContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + queryContent( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( com::sun::star::ucb::IllegalIdentifierException, + com::sun::star::uno::RuntimeException ); + + // XInitialization + virtual void SAL_CALL + initialize( const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Any >& aArguments ) + throw( ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException ); + + // Non-Interface methods + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > + getConfigProvider( const rtl::OUString & rServiceSpecifier ); + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > + getRootConfigReadNameAccess( const rtl::OUString & rServiceSpecifier ); + + // Note: may retrun an empty reference. + com::sun::star::uno::Reference< + com::sun::star::util::XOfficeInstallationDirectories > + getOfficeInstallationDirectories(); +}; + +} // namespace hierarchy_ucp + +#endif /* !_HIERARCHYPROVIDER_HXX */ diff --git a/ucb/source/ucp/hierarchy/hierarchyservices.cxx b/ucb/source/ucp/hierarchy/hierarchyservices.cxx new file mode 100644 index 000000000000..1830ecc35625 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchyservices.cxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * 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" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include "hierarchyprovider.hxx" +#include "hierarchydatasource.hxx" + +using namespace com::sun::star; +using namespace hierarchy_ucp; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + uno::Reference< lang::XMultiServiceFactory > xSMgr( + reinterpret_cast< lang::XMultiServiceFactory * >( + pServiceManager ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // Hierarchy Content Provider. + ////////////////////////////////////////////////////////////////////// + + if ( HierarchyContentProvider::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = HierarchyContentProvider::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // Hierarchy Data Source. + ////////////////////////////////////////////////////////////////////// + + else if ( HierarchyDataSource::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = HierarchyDataSource::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/ucp/hierarchy/hierarchyuri.cxx b/ucb/source/ucp/hierarchy/hierarchyuri.cxx new file mode 100644 index 000000000000..0621db72d5bb --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchyuri.cxx @@ -0,0 +1,209 @@ +/************************************************************************* + * + * 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 + ************************************************************************** + + *************************************************************************/ + +#include "rtl/ustrbuf.hxx" +#include "osl/diagnose.h" + +#include "hierarchyuri.hxx" + +using namespace hierarchy_ucp; + +//========================================================================= + +#define DEFAULT_DATA_SOURCE_SERVICE \ + "com.sun.star.ucb.DefaultHierarchyDataSource" + +//========================================================================= +//========================================================================= +// +// HierarchyUri Implementation. +// +//========================================================================= +//========================================================================= + +void HierarchyUri::init() const +{ + // Already inited? + if ( m_aUri.getLength() && !m_aPath.getLength() ) + { + // Note: Maybe it's a re-init, setUri only resets m_aPath! + m_aService = m_aParentUri = m_aName = rtl::OUString(); + + // URI must match at least: <sheme>: + if ( ( m_aUri.getLength() < HIERARCHY_URL_SCHEME_LENGTH + 1 ) ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString::createFromAscii( "/" ); + return; + } + + // Scheme is case insensitive. + rtl::OUString aScheme + = m_aUri.copy( 0, HIERARCHY_URL_SCHEME_LENGTH ).toAsciiLowerCase(); + if ( aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( HIERARCHY_URL_SCHEME ) ) ) + { + m_aUri = m_aUri.replaceAt( 0, aScheme.getLength(), aScheme ); + + sal_Int32 nPos = 0; + + // If the URI has no service specifier, insert default service. + // This is for backward compatibility and for convenience. + + if ( m_aUri.getLength() == HIERARCHY_URL_SCHEME_LENGTH + 1 ) + { + // root folder URI without path and service specifier. + m_aUri += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "//" DEFAULT_DATA_SOURCE_SERVICE "/" ) ); + m_aService + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + DEFAULT_DATA_SOURCE_SERVICE ) ); + + nPos = m_aUri.getLength() - 1; + } + else if ( ( m_aUri.getLength() == HIERARCHY_URL_SCHEME_LENGTH + 2 ) + && + ( m_aUri.getStr()[ HIERARCHY_URL_SCHEME_LENGTH + 1 ] + == sal_Unicode( '/' ) ) ) + { + // root folder URI without service specifier. + m_aUri += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "/" DEFAULT_DATA_SOURCE_SERVICE "/" ) ); + m_aService + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + DEFAULT_DATA_SOURCE_SERVICE ) ); + + nPos = m_aUri.getLength() - 1; + } + else if ( ( m_aUri.getLength() > HIERARCHY_URL_SCHEME_LENGTH + 2 ) + && + ( m_aUri.getStr()[ HIERARCHY_URL_SCHEME_LENGTH + 2 ] + != sal_Unicode( '/' ) ) ) + { + // other (no root folder) URI without service specifier. + m_aUri = m_aUri.replaceAt( + HIERARCHY_URL_SCHEME_LENGTH + 2, + 0, + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "/" DEFAULT_DATA_SOURCE_SERVICE "/" ) ) ); + m_aService + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + DEFAULT_DATA_SOURCE_SERVICE ) ); + + nPos + = HIERARCHY_URL_SCHEME_LENGTH + 3 + m_aService.getLength(); + } + else + { + // URI with service specifier. + sal_Int32 nStart = HIERARCHY_URL_SCHEME_LENGTH + 3; + + // Here: - m_aUri has at least the form "<scheme>://" + // - nStart points to char after <scheme>:// + + // Only <scheme>:// ? + if ( nStart == m_aUri.getLength() ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString::createFromAscii( "/" ); + return; + } + + // Empty path segments? + if ( m_aUri.indexOf( + rtl::OUString::createFromAscii( "//" ), + nStart ) != -1 ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString::createFromAscii( "/" ); + return; + } + + sal_Int32 nEnd = m_aUri.indexOf( '/', nStart ); + + // Only <scheme>:/// ? + if ( nEnd == nStart ) + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString::createFromAscii( "/" ); + return; + } + + if ( nEnd == -1 ) + { + // Trailing slash missing. + nEnd = m_aUri.getLength(); + m_aUri += rtl::OUString::createFromAscii( "/" ); + } + + m_aService = m_aUri.copy( nStart, nEnd - nStart ); + + nPos = nEnd; + } + + // Here: - m_aUri has at least the form "<scheme>://<service>/" + // - m_aService was set + // - m_aPath, m_aParentPath, m_aName not yet set + // - nPos points to slash after service specifier + + // Remove trailing slash, if not a root folder URI. + sal_Int32 nEnd = m_aUri.lastIndexOf( '/' ); + if ( ( nEnd > nPos ) && ( nEnd == ( m_aUri.getLength() - 1 ) ) ) + m_aUri = m_aUri.copy( 0, nEnd ); + + // Path (includes leading slash) + m_aPath = m_aUri.copy( nPos ); + + // parent URI + name + sal_Int32 nLastSlash = m_aUri.lastIndexOf( '/' ); + if ( ( nLastSlash != -1 ) && + ( nLastSlash != m_aUri.getLength() - 1 ) ) // root + { + m_aParentUri = m_aUri.copy( 0, nLastSlash ); + m_aName = m_aUri.copy( nLastSlash + 1 ); + } + + // success + m_bValid = true; + } + else + { + // error, but remember that we did a init(). + m_aPath = rtl::OUString::createFromAscii( "/" ); + } + } +} + diff --git a/ucb/source/ucp/hierarchy/hierarchyuri.hxx b/ucb/source/ucp/hierarchy/hierarchyuri.hxx new file mode 100644 index 000000000000..012d59bb4cf2 --- /dev/null +++ b/ucb/source/ucp/hierarchy/hierarchyuri.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _HIERARCHYURI_HXX +#define _HIERARCHYURI_HXX + +#include <rtl/ustring.hxx> + +namespace hierarchy_ucp { + +//========================================================================= + +#define HIERARCHY_URL_SCHEME "vnd.sun.star.hier" +#define HIERARCHY_URL_SCHEME_LENGTH 17 + +//========================================================================= + +class HierarchyUri +{ + mutable ::rtl::OUString m_aUri; + mutable ::rtl::OUString m_aParentUri; + mutable ::rtl::OUString m_aService; + mutable ::rtl::OUString m_aPath; + mutable ::rtl::OUString m_aName; + mutable bool m_bValid; + +private: + void init() const; + +public: + HierarchyUri() : m_bValid( false ) {} + HierarchyUri( const ::rtl::OUString & rUri ) + : m_aUri( rUri ), m_bValid( false ) {} + + sal_Bool isValid() const + { init(); return m_bValid; } + + const ::rtl::OUString & getUri() const + { init(); return m_aUri; } + + void setUri( const ::rtl::OUString & rUri ) + { m_aPath = ::rtl::OUString(); m_aUri = rUri; m_bValid = false; } + + const ::rtl::OUString & getParentUri() const + { init(); return m_aParentUri; } + + const ::rtl::OUString & getService() const + { init(); return m_aService; } + + const ::rtl::OUString & getPath() const + { init(); return m_aPath; } + + const ::rtl::OUString & getName() const + { init(); return m_aName; } + + inline sal_Bool isRootFolder() const; +}; + +inline sal_Bool HierarchyUri::isRootFolder() const +{ + init(); + return ( ( m_aPath.getLength() == 1 ) && + ( m_aPath.getStr()[ 0 ] == sal_Unicode( '/' ) ) ); +} +} + +#endif diff --git a/ucb/source/ucp/hierarchy/makefile.mk b/ucb/source/ucp/hierarchy/makefile.mk new file mode 100644 index 000000000000..9263faa24b08 --- /dev/null +++ b/ucb/source/ucp/hierarchy/makefile.mk @@ -0,0 +1,92 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJNAME=ucb +TARGET=ucphier +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE +NO_BSYMBOLIC=TRUE + +# Version +UCPHIER_MAJOR=1 + +# --- Settings --------------------------------------------------------- + +.INCLUDE: settings.mk + +# --- General ----------------------------------------------------- +.IF "$(L10N_framework)"=="" + +SLOFILES=\ + $(SLO)$/hierarchyservices.obj \ + $(SLO)$/hierarchydata.obj \ + $(SLO)$/hierarchyprovider.obj \ + $(SLO)$/hierarchycontent.obj \ + $(SLO)$/hierarchycontentcaps.obj \ + $(SLO)$/hierarchydatasupplier.obj \ + $(SLO)$/dynamicresultset.obj \ + $(SLO)$/hierarchydatasource.obj \ + $(SLO)$/hierarchyuri.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +# --- Shared-Library --------------------------------------------------- + +SHL1TARGET=$(TARGET)$(UCPHIER_MAJOR) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(LIB1TARGET) + +# --- Def-File --------------------------------------------------------- + +DEF1NAME=$(SHL1TARGET) + +# --- Targets ---------------------------------------------------------- + +.ENDIF # L10N_framework +.INCLUDE: target.mk + + +ALLTAR : $(MISC)/ucphier1.component + +$(MISC)/ucphier1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + ucphier1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt ucphier1.component diff --git a/ucb/source/ucp/hierarchy/ucphier.xml b/ucb/source/ucp/hierarchy/ucphier.xml new file mode 100644 index 000000000000..1c63cbcbd7ee --- /dev/null +++ b/ucb/source/ucp/hierarchy/ucphier.xml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucphier + </module-name> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.HierarchyContentProvider + </name> + <description> + This component implements a Content Provider for the Universal + Content Broker. It provides access to a persistent hierarchy of + folders and links. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.HierarchyContentProvider + </supported-service> + + <service-dependency> + com.sun.star.ucb.DefaultHierarchyDataSource + </service-dependency> + <service-dependency> + com.sun.star.util.OfficeeInstallationDirectories + </service-dependency> + </component-description> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.HierarchyDataSource + </name> + <description> + This component implements a default data source for the Hierarchy + Content Provider. The data are accessed using the service + com.sun.star.configuration.ConfigurationProvider. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.DefaultHierarchyDataSource + </supported-service> + + <service-dependency> + com.sun.star.configuration.ConfigurationProvider + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.XPropertiesChangeNotifier </type> + <type> com.sun.star.beans.XPropertyAccess </type> + <type> com.sun.star.beans.XPropertyContainer </type> + <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type> + <type> com.sun.star.container.XChild </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.container.XNameContainer </type> + <type> com.sun.star.lang.IllegalAccessException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XColumnLocate </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.InteractiveBadTransferURLException </type> + <type> com.sun.star.ucb.MissingPropertiesException </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.ResultSetException </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.UnsuppertedNameClashException </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XCommandInfoChangeNotifier </type> + <type> com.sun.star.ucb.XCommandProcessor </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XContentProvider </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XPersistentPropertySet </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.util.XChangesBatch </type> + <type> com.sun.star.util.XChangesNotifier </type> + <type> com.sun.star.util.XOfficeInstallationDirectories </type> +</module-description> diff --git a/ucb/source/ucp/hierarchy/ucphier1.component b/ucb/source/ucp/hierarchy/ucphier1.component new file mode 100644 index 000000000000..5483187d8674 --- /dev/null +++ b/ucb/source/ucp/hierarchy/ucphier1.component @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.HierarchyContentProvider"> + <service name="com.sun.star.ucb.HierarchyContentProvider"/> + </implementation> + <implementation name="com.sun.star.comp.ucb.HierarchyDataSource"> + <service name="com.sun.star.ucb.DefaultHierarchyDataSource"/> + <service name="com.sun.star.ucb.HierarchyDataSource"/> + </implementation> +</component> |