| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_ucb.hxx" |
| |
| /************************************************************************** |
| TODO |
| ************************************************************************** |
| |
| - 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 ); |
| } |
| } |