| /************************************************************** |
| * |
| * 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 |
| ************************************************************************** |
| |
| *************************************************************************/ |
| |
| #include "osl/diagnose.h" |
| #include "osl/doublecheckedlocking.h" |
| #include "rtl/ustrbuf.hxx" |
| |
| #include "com/sun/star/beans/PropertyAttribute.hpp" |
| #include "com/sun/star/beans/PropertyValue.hpp" |
| #include "com/sun/star/beans/XPropertySet.hpp" |
| #include "com/sun/star/embed/ElementModes.hpp" |
| #include "com/sun/star/embed/XStorage.hpp" |
| #include "com/sun/star/embed/XTransactedObject.hpp" |
| #include "com/sun/star/io/XActiveDataSink.hpp" |
| #include "com/sun/star/io/XActiveDataStreamer.hpp" |
| #include "com/sun/star/lang/IllegalAccessException.hpp" |
| #include "com/sun/star/sdbc/XRow.hpp" |
| #include "com/sun/star/ucb/ContentAction.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/MissingInputStreamException.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/OpenMode.hpp" |
| #include "com/sun/star/ucb/TransferInfo.hpp" |
| #include "com/sun/star/ucb/UnsupportedCommandException.hpp" |
| #include "com/sun/star/ucb/UnsupportedDataSinkException.hpp" |
| #include "com/sun/star/ucb/UnsupportedNameClashException.hpp" |
| #include "com/sun/star/ucb/UnsupportedOpenModeException.hpp" |
| #include "com/sun/star/ucb/XCommandInfo.hpp" |
| #include "com/sun/star/ucb/XPersistentPropertySet.hpp" |
| |
| #include "ucbhelper/cancelcommandexecution.hxx" |
| #include "ucbhelper/contentidentifier.hxx" |
| #include "ucbhelper/propertyvalueset.hxx" |
| |
| #include "tdoc_content.hxx" |
| #include "tdoc_resultset.hxx" |
| #include "tdoc_passwordrequest.hxx" |
| |
| #include "../inc/urihelper.hxx" |
| |
| using namespace com::sun::star; |
| using namespace tdoc_ucp; |
| |
| //========================================================================= |
| static ContentType lcl_getContentType( const rtl::OUString & rType ) |
| { |
| if ( rType.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( TDOC_ROOT_CONTENT_TYPE ) ) ) |
| return ROOT; |
| else if ( rType.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( TDOC_DOCUMENT_CONTENT_TYPE ) ) ) |
| return DOCUMENT; |
| else if ( rType.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ) ) |
| return FOLDER; |
| else if ( rType.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) ) |
| return STREAM; |
| else |
| { |
| OSL_ENSURE( sal_False, |
| "Content::Content - unsupported content type string" ); |
| return STREAM; |
| } |
| } |
| |
| //========================================================================= |
| //========================================================================= |
| // |
| // Content Implementation. |
| // |
| //========================================================================= |
| //========================================================================= |
| |
| // static ( "virtual" ctor ) |
| Content* Content::create( |
| const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, |
| ContentProvider* pProvider, |
| const uno::Reference< ucb::XContentIdentifier >& Identifier ) |
| { |
| // Fail, if resource does not exist. |
| ContentProperties aProps; |
| if ( !Content::loadData( pProvider, |
| Uri( Identifier->getContentIdentifier() ), |
| aProps ) ) |
| return 0; |
| |
| return new Content( rxSMgr, pProvider, Identifier, aProps ); |
| } |
| |
| //========================================================================= |
| // static ( "virtual" ctor ) |
| Content* Content::create( |
| const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, |
| ContentProvider* pProvider, |
| const uno::Reference< ucb::XContentIdentifier >& Identifier, |
| const ucb::ContentInfo& Info ) |
| { |
| if ( !Info.Type.getLength() ) |
| return 0; |
| |
| if ( !Info.Type.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ) && |
| !Info.Type.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) ) |
| { |
| OSL_ENSURE( sal_False, "Content::create - unsupported content type!" ); |
| return 0; |
| } |
| |
| #if 0 |
| // Fail, if content does exist. |
| if ( Content::hasData( pProvider, |
| Uri( Identifier->getContentIdentifier() ) ) ) |
| return 0; |
| #endif |
| |
| return new Content( rxSMgr, pProvider, Identifier, Info ); |
| } |
| |
| //========================================================================= |
| Content::Content( |
| const uno::Reference< lang::XMultiServiceFactory > & rxSMgr, |
| ContentProvider * pProvider, |
| const uno::Reference< ucb::XContentIdentifier > & Identifier, |
| const ContentProperties & rProps ) |
| : ContentImplHelper( rxSMgr, pProvider, Identifier ), |
| m_aProps( rProps ), |
| m_eState( PERSISTENT ), |
| m_pProvider( pProvider ) |
| { |
| } |
| |
| //========================================================================= |
| // ctor for a content just created via XContentCreator::createNewContent() |
| Content::Content( |
| const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, |
| ContentProvider* pProvider, |
| const uno::Reference< ucb::XContentIdentifier >& Identifier, |
| const ucb::ContentInfo& Info ) |
| : ContentImplHelper( rxSMgr, pProvider, Identifier ), |
| m_aProps( lcl_getContentType( Info.Type ), rtl::OUString() ), // no Title (yet) |
| m_eState( TRANSIENT ), |
| m_pProvider( pProvider ) |
| { |
| } |
| |
| //========================================================================= |
| // virtual |
| Content::~Content() |
| { |
| } |
| |
| //========================================================================= |
| // |
| // XInterface methods. |
| // |
| //========================================================================= |
| |
| // virtual |
| void SAL_CALL Content::acquire() |
| throw( ) |
| { |
| ContentImplHelper::acquire(); |
| } |
| |
| //========================================================================= |
| // virtual |
| void SAL_CALL Content::release() |
| throw( ) |
| { |
| ContentImplHelper::release(); |
| } |
| |
| //========================================================================= |
| // virtual |
| uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) |
| throw ( uno::RuntimeException ) |
| { |
| uno::Any aRet = ContentImplHelper::queryInterface( rType ); |
| |
| if ( !aRet.hasValue() ) |
| { |
| aRet = cppu::queryInterface( |
| rType, static_cast< ucb::XContentCreator * >( this ) ); |
| if ( aRet.hasValue() ) |
| { |
| if ( !m_aProps.isContentCreator() ) |
| return uno::Any(); |
| } |
| } |
| |
| return aRet; |
| } |
| |
| //========================================================================= |
| // |
| // XTypeProvider methods. |
| // |
| //========================================================================= |
| |
| XTYPEPROVIDER_COMMON_IMPL( Content ); |
| |
| //========================================================================= |
| // virtual |
| uno::Sequence< uno::Type > SAL_CALL Content::getTypes() |
| throw( uno::RuntimeException ) |
| { |
| cppu::OTypeCollection * pCollection = 0; |
| |
| if ( m_aProps.isContentCreator() ) |
| { |
| 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 Content::getImplementationName() |
| throw( uno::RuntimeException ) |
| { |
| return rtl::OUString::createFromAscii( |
| "com.sun.star.comp.ucb.TransientDocumentsContent" ); |
| } |
| |
| //========================================================================= |
| // virtual |
| uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() |
| throw( uno::RuntimeException ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| uno::Sequence< rtl::OUString > aSNS( 1 ); |
| |
| if ( m_aProps.getType() == STREAM ) |
| aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( |
| TDOC_STREAM_CONTENT_SERVICE_NAME ); |
| else if ( m_aProps.getType() == FOLDER ) |
| aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( |
| TDOC_FOLDER_CONTENT_SERVICE_NAME ); |
| else if ( m_aProps.getType() == DOCUMENT ) |
| aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( |
| TDOC_DOCUMENT_CONTENT_SERVICE_NAME ); |
| else |
| aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( |
| TDOC_ROOT_CONTENT_SERVICE_NAME ); |
| |
| return aSNS; |
| } |
| |
| //========================================================================= |
| // |
| // XContent methods. |
| // |
| //========================================================================= |
| |
| // virtual |
| rtl::OUString SAL_CALL Content::getContentType() |
| throw( uno::RuntimeException ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| return m_aProps.getContentType(); |
| } |
| |
| //========================================================================= |
| // virtual |
| uno::Reference< ucb::XContentIdentifier > SAL_CALL |
| Content::getIdentifier() |
| throw( uno::RuntimeException ) |
| { |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| // 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 Content::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" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // open |
| ////////////////////////////////////////////////////////////////// |
| |
| 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 |
| } |
| |
| aRet = open( aOpenCommand, Environment ); |
| } |
| else if ( aCommand.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // insert ( Supported by folders and streams only ) |
| ////////////////////////////////////////////////////////////////// |
| |
| ContentType eType = m_aProps.getType(); |
| if ( ( eType != FOLDER ) && ( eType != STREAM ) ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::UnsupportedCommandException( |
| rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM( |
| "insert command only supported by " |
| "folders and streams!" ) ), |
| static_cast< cppu::OWeakObject * >( this ) ) ), |
| Environment ); |
| // Unreachable |
| } |
| |
| #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT |
| if ( eType == STREAM ) |
| { |
| Uri aUri( m_xIdentifier->getContentIdentifier() ); |
| Uri aParentUri( aUri.getParentUri() ); |
| if ( aParentUri.isDocument() ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::UnsupportedCommandException( |
| rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM( |
| "insert command not supported by " |
| "streams that are direct children " |
| "of document root!" ) ), |
| static_cast< cppu::OWeakObject * >( |
| this ) ) ), |
| Environment ); |
| // Unreachable |
| } |
| } |
| #endif |
| 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( aArg.Data, nNameClash, Environment ); |
| } |
| else if ( aCommand.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // delete ( Supported by folders and streams only ) |
| ////////////////////////////////////////////////////////////////// |
| |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| ContentType eType = m_aProps.getType(); |
| if ( ( eType != FOLDER ) && ( eType != STREAM ) ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::UnsupportedCommandException( |
| rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM( |
| "delete command only supported by " |
| "folders and streams!" ) ), |
| static_cast< cppu::OWeakObject * >( |
| this ) ) ), |
| Environment ); |
| // Unreachable |
| } |
| } |
| |
| 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" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // transfer ( Supported by document and folders only ) |
| ////////////////////////////////////////////////////////////////// |
| |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| ContentType eType = m_aProps.getType(); |
| if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::UnsupportedCommandException( |
| rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM( |
| "transfer command only supported " |
| "by folders and documents!" ) ), |
| static_cast< cppu::OWeakObject * >( |
| this ) ) ), |
| Environment ); |
| // Unreachable |
| } |
| } |
| |
| 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" ) ) ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // createNewContent ( Supported by document and folders only ) |
| ////////////////////////////////////////////////////////////////// |
| |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| ContentType eType = m_aProps.getType(); |
| if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::UnsupportedCommandException( |
| rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM( |
| "createNewContent command only " |
| "supported by folders and " |
| "documents!" ) ), |
| static_cast< cppu::OWeakObject * >( |
| this ) ) ), |
| Environment ); |
| // Unreachable |
| } |
| } |
| |
| 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 Content::abort( sal_Int32 /*CommandId*/ ) |
| throw( uno::RuntimeException ) |
| { |
| } |
| |
| //========================================================================= |
| // |
| // XContentCreator methods. |
| // |
| //========================================================================= |
| |
| // virtual |
| uno::Sequence< ucb::ContentInfo > SAL_CALL |
| Content::queryCreatableContentsInfo() |
| throw( uno::RuntimeException ) |
| { |
| return m_aProps.getCreatableContentsInfo(); |
| } |
| |
| //========================================================================= |
| // virtual |
| uno::Reference< ucb::XContent > SAL_CALL |
| Content::createNewContent( const ucb::ContentInfo& Info ) |
| throw( uno::RuntimeException ) |
| { |
| if ( m_aProps.isContentCreator() ) |
| { |
| 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( TDOC_FOLDER_CONTENT_TYPE ) ); |
| |
| #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT |
| // streams cannot be created as direct children of document root |
| if ( !bCreateFolder && ( m_aProps.getType() == DOCUMENT ) ) |
| { |
| OSL_ENSURE( sal_False, |
| "Content::createNewContent - streams cannot be " |
| "created as direct children of document root!" ); |
| return uno::Reference< ucb::XContent >(); |
| } |
| #endif |
| if ( !bCreateFolder && |
| !Info.Type.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) ) |
| { |
| OSL_ENSURE( sal_False, |
| "Content::createNewContent - unsupported type!" ); |
| return uno::Reference< ucb::XContent >(); |
| } |
| |
| rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); |
| |
| OSL_ENSURE( aURL.getLength() > 0, |
| "Content::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_Stream" ); |
| |
| 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-contentcreator object!" ); |
| return uno::Reference< ucb::XContent >(); |
| } |
| } |
| |
| //========================================================================= |
| // virtual |
| rtl::OUString Content::getParentURL() |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| Uri aUri( m_xIdentifier->getContentIdentifier() ); |
| return aUri.getParentUri(); |
| } |
| |
| //========================================================================= |
| uno::Reference< ucb::XContentIdentifier > |
| Content::makeNewIdentifier( const rtl::OUString& rTitle ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| // Assemble new content identifier... |
| Uri aUri( m_xIdentifier->getContentIdentifier() ); |
| rtl::OUStringBuffer aNewURL = aUri.getParentUri(); |
| aNewURL.append( ::ucb_impl::urihelper::encodeSegment( rTitle ) ); |
| |
| return |
| uno::Reference< ucb::XContentIdentifier >( |
| new ::ucbhelper::ContentIdentifier( |
| m_xSMgr, aNewURL.makeStringAndClear() ) ); |
| } |
| |
| //========================================================================= |
| void Content::queryChildren( ContentRefList& rChildren ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| // Only folders (root, documents, folders) have children. |
| if ( !m_aProps.getIsFolder() ) |
| 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( |
| ContentRef( |
| static_cast< Content * >( xChild.get() ) ) ); |
| } |
| } |
| ++it; |
| } |
| } |
| |
| //========================================================================= |
| sal_Bool Content::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, |
| "Content::exchangeIdentity - Not persistent!" ); |
| return sal_False; |
| } |
| |
| // Only folders and streams can be renamed -> exchange identity. |
| ContentType eType = m_aProps.getType(); |
| if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) |
| { |
| OSL_ENSURE( sal_False, "Content::exchangeIdentity - " |
| "Not supported by root or document!" ); |
| return sal_False; |
| } |
| |
| // Exchange own identitity. |
| |
| // Fail, if a content with given id already exists. |
| if ( !hasData( Uri( xNewId->getContentIdentifier() ) ) ) |
| { |
| rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); |
| |
| aGuard.clear(); |
| if ( exchange( xNewId ) ) |
| { |
| if ( eType == FOLDER ) |
| { |
| // Process instanciated children... |
| |
| ContentRefList aChildren; |
| queryChildren( aChildren ); |
| |
| ContentRefList::const_iterator it = aChildren.begin(); |
| ContentRefList::const_iterator end = aChildren.end(); |
| |
| while ( it != end ) |
| { |
| ContentRef 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, |
| "Content::exchangeIdentity - " |
| "Panic! Cannot exchange identity!" ); |
| return sal_False; |
| } |
| |
| //========================================================================= |
| // static |
| uno::Reference< sdbc::XRow > Content::getPropertyValues( |
| const uno::Reference< lang::XMultiServiceFactory >& rSMgr, |
| const uno::Sequence< beans::Property >& rProperties, |
| ContentProvider* pProvider, |
| const rtl::OUString& rContentId ) |
| { |
| ContentProperties aData; |
| if ( loadData( pProvider, rContentId, aData ) ) |
| { |
| return getPropertyValues( |
| rSMgr, rProperties, aData, pProvider, rContentId ); |
| } |
| else |
| { |
| rtl::Reference< ::ucbhelper::PropertyValueSet > xRow |
| = new ::ucbhelper::PropertyValueSet( rSMgr ); |
| |
| sal_Int32 nCount = rProperties.getLength(); |
| if ( nCount ) |
| { |
| const beans::Property* pProps = rProperties.getConstArray(); |
| for ( sal_Int32 n = 0; n < nCount; ++n ) |
| xRow->appendVoid( pProps[ n ] ); |
| } |
| |
| return uno::Reference< sdbc::XRow >( xRow.get() ); |
| } |
| } |
| |
| //========================================================================= |
| // static |
| uno::Reference< sdbc::XRow > Content::getPropertyValues( |
| const uno::Reference< lang::XMultiServiceFactory >& rSMgr, |
| const uno::Sequence< beans::Property >& rProperties, |
| const ContentProperties& rData, |
| ContentProvider* 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( "Storage" ) ) ) |
| { |
| // Storage is only supported by folders. |
| ContentType eType = rData.getType(); |
| if ( eType == FOLDER ) |
| xRow->appendObject( |
| rProp, |
| uno::makeAny( |
| pProvider->queryStorageClone( rContentId ) ) ); |
| else |
| xRow->appendVoid( rProp ); |
| } |
| else if ( rProp.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "DocumentModel" ) ) ) |
| { |
| // DocumentModel is only supported by documents. |
| ContentType eType = rData.getType(); |
| if ( eType == DOCUMENT ) |
| xRow->appendObject( |
| rProp, |
| uno::makeAny( |
| pProvider->queryDocumentModel( rContentId ) ) ); |
| 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() ); |
| |
| ContentType eType = rData.getType(); |
| |
| xRow->appendString ( |
| beans::Property( rtl::OUString::createFromAscii( "Title" ), |
| -1, |
| getCppuType( static_cast< const rtl::OUString * >( 0 ) ), |
| // Title is read-only for root and documents. |
| beans::PropertyAttribute::BOUND || |
| ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) |
| ? beans::PropertyAttribute::READONLY |
| : 0 ), |
| 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() ); |
| 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() ) ); |
| |
| // Storage is only supported by folders. |
| if ( eType == FOLDER ) |
| xRow->appendObject( |
| beans::Property( rtl::OUString::createFromAscii( "Storage" ), |
| -1, |
| getCppuType( |
| static_cast< |
| const uno::Reference< embed::XStorage > * >( 0 ) ), |
| beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ), |
| uno::makeAny( pProvider->queryStorageClone( rContentId ) ) ); |
| |
| // DocumentModel is only supported by documents. |
| if ( eType == DOCUMENT ) |
| xRow->appendObject( |
| beans::Property( rtl::OUString::createFromAscii( "DocumentModel" ), |
| -1, |
| getCppuType( |
| static_cast< |
| const uno::Reference< frame::XModel > * >( 0 ) ), |
| beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ), |
| uno::makeAny( |
| pProvider->queryDocumentModel( rContentId ) ) ); |
| |
| // 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 > Content::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 > Content::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; |
| 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" ) ) ) |
| { |
| // Title is read-only for root and documents. |
| ContentType eType = m_aProps.getType(); |
| if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) |
| { |
| 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(); |
| m_aProps.setTitle( aNewValue ); |
| |
| // property change event will be sent 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( |
| "Title Property value has wrong type!" ), |
| static_cast< cppu::OWeakObject * >( this ) ); |
| } |
| } |
| } |
| else if ( rValue.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "Storage" ) ) ) |
| { |
| ContentType eType = m_aProps.getType(); |
| if ( eType == FOLDER ) |
| { |
| aRet[ n ] <<= lang::IllegalAccessException( |
| rtl::OUString::createFromAscii( |
| "Property is read-only!" ), |
| static_cast< cppu::OWeakObject * >( this ) ); |
| } |
| else |
| { |
| // Storage is only supported by folders. |
| aRet[ n ] <<= beans::UnknownPropertyException( |
| rtl::OUString::createFromAscii( |
| "Storage property only supported by folders" ), |
| static_cast< cppu::OWeakObject * >( this ) ); |
| } |
| } |
| else if ( rValue.Name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( "DocumentModel" ) ) ) |
| { |
| ContentType eType = m_aProps.getType(); |
| if ( eType == DOCUMENT ) |
| { |
| aRet[ n ] <<= lang::IllegalAccessException( |
| rtl::OUString::createFromAscii( |
| "Property is read-only!" ), |
| static_cast< cppu::OWeakObject * >( this ) ); |
| } |
| else |
| { |
| // Storage is only supported by folders. |
| aRet[ n ] <<= beans::UnknownPropertyException( |
| rtl::OUString::createFromAscii( |
| "DocumentModel property only supported by " |
| "documents" ), |
| 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 ); |
| aOldTitle = 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::Reference< io::XInputStream >(), xEnv ) ) |
| { |
| 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; |
| } |
| |
| //========================================================================= |
| uno::Any Content::open( |
| const ucb::OpenCommandArgument2& rArg, |
| const uno::Reference< ucb::XCommandEnvironment >& xEnv ) |
| throw( uno::Exception ) |
| { |
| if ( rArg.Mode == ucb::OpenMode::ALL || |
| rArg.Mode == ucb::OpenMode::FOLDERS || |
| rArg.Mode == ucb::OpenMode::DOCUMENTS ) |
| { |
| ////////////////////////////////////////////////////////////////// |
| // open command for a folder content |
| ////////////////////////////////////////////////////////////////// |
| |
| uno::Reference< ucb::XDynamicResultSet > xSet |
| = new DynamicResultSet( m_xSMgr, this, rArg ); |
| return uno::makeAny( xSet ); |
| } |
| else |
| { |
| ////////////////////////////////////////////////////////////////// |
| // open command for a document content |
| ////////////////////////////////////////////////////////////////// |
| |
| if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || |
| ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) |
| { |
| // Currently(?) unsupported. |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::UnsupportedOpenModeException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| sal_Int16( rArg.Mode ) ) ), |
| xEnv ); |
| // Unreachable |
| } |
| |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); |
| |
| uno::Reference< io::XActiveDataStreamer > xDataStreamer( |
| rArg.Sink, uno::UNO_QUERY ); |
| if ( xDataStreamer.is() ) |
| { |
| // May throw CommandFailedException, DocumentPasswordRequest! |
| uno::Reference< io::XStream > xStream = getStream( xEnv ); |
| if ( !xStream.is() ) |
| { |
| // No interaction if we are not persistent! |
| 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_READ, |
| uno::Sequence< uno::Any >(&aProps, 1), |
| m_eState == PERSISTENT |
| ? xEnv |
| : uno::Reference< ucb::XCommandEnvironment >(), |
| rtl::OUString::createFromAscii( |
| "Got no data stream!" ), |
| this ); |
| // Unreachable |
| } |
| |
| // Done. |
| xDataStreamer->setStream( xStream ); |
| } |
| else |
| { |
| uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY ); |
| if ( xOut.is() ) |
| { |
| // PUSH: write data into xOut |
| |
| // May throw CommandFailedException, DocumentPasswordRequest! |
| uno::Reference< io::XInputStream > xIn = getInputStream( xEnv ); |
| if ( !xIn.is() ) |
| { |
| // No interaction if we are not persistent! |
| 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_READ, |
| uno::Sequence< uno::Any >(&aProps, 1), |
| m_eState == PERSISTENT |
| ? xEnv |
| : uno::Reference< ucb::XCommandEnvironment >(), |
| rtl::OUString::createFromAscii( "Got no data stream!" ), |
| this ); |
| // Unreachable |
| } |
| |
| try |
| { |
| uno::Sequence< sal_Int8 > aBuffer; |
| sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 ); |
| |
| while ( nRead > 0 ) |
| { |
| aBuffer.realloc( nRead ); |
| xOut->writeBytes( aBuffer ); |
| aBuffer.realloc( 0 ); |
| nRead = xIn->readSomeBytes( aBuffer, 65536 ); |
| } |
| |
| xOut->closeOutput(); |
| } |
| catch ( io::NotConnectedException const & ) |
| { |
| // closeOutput, readSomeBytes, writeBytes |
| } |
| catch ( io::BufferSizeExceededException const & ) |
| { |
| // closeOutput, readSomeBytes, writeBytes |
| } |
| catch ( io::IOException const & ) |
| { |
| // closeOutput, readSomeBytes, writeBytes |
| } |
| } |
| else |
| { |
| uno::Reference< io::XActiveDataSink > xDataSink( |
| rArg.Sink, uno::UNO_QUERY ); |
| if ( xDataSink.is() ) |
| { |
| // PULL: wait for client read |
| |
| // May throw CommandFailedException, DocumentPasswordRequest! |
| uno::Reference< io::XInputStream > xIn = getInputStream( xEnv ); |
| if ( !xIn.is() ) |
| { |
| // No interaction if we are not persistent! |
| 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_READ, |
| uno::Sequence< uno::Any >(&aProps, 1), |
| m_eState == PERSISTENT |
| ? xEnv |
| : uno::Reference< |
| ucb::XCommandEnvironment >(), |
| rtl::OUString::createFromAscii( |
| "Got no data stream!" ), |
| this ); |
| // Unreachable |
| } |
| |
| // Done. |
| xDataSink->setInputStream( xIn ); |
| } |
| else |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( |
| ucb::UnsupportedDataSinkException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| rArg.Sink ) ), |
| xEnv ); |
| // Unreachable |
| } |
| } |
| } |
| } |
| |
| return uno::Any(); |
| } |
| |
| //========================================================================= |
| void Content::insert( const uno::Reference< io::XInputStream >& xData, |
| sal_Int32 nNameClashResolve, |
| const uno::Reference< |
| ucb::XCommandEnvironment > & xEnv ) |
| throw( uno::Exception ) |
| { |
| osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); |
| |
| ContentType eType = m_aProps.getType(); |
| |
| OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ), |
| "insert command only supported by streams and folders!" ); |
| |
| Uri aUri( m_xIdentifier->getContentIdentifier() ); |
| |
| #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT |
| #if OSL_DEBUG_LEVEL > 0 |
| if ( eType == STREAM ) |
| { |
| Uri aParentUri( aUri.getParentUri() ); |
| OSL_ENSURE( !aParentUri.isDocument(), |
| "insert command not supported by streams that are direct " |
| "children of document root!" ); |
| } |
| #endif |
| #endif |
| |
| // Check, if all required properties were set. |
| if ( eType == FOLDER ) |
| { |
| // Required: Title |
| |
| if ( m_aProps.getTitle().getLength() == 0 ) |
| m_aProps.setTitle( aUri.getDecodedName() ); |
| } |
| else // stream |
| { |
| // Required: data |
| |
| if ( !xData.is() ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::MissingInputStreamException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ) ) ), |
| xEnv ); |
| // Unreachable |
| } |
| |
| // Required: Title |
| |
| if ( m_aProps.getTitle().getLength() == 0 ) |
| m_aProps.setTitle( aUri.getDecodedName() ); |
| } |
| |
| rtl::OUStringBuffer aNewURL = aUri.getParentUri(); |
| aNewURL.append( m_aProps.getTitle() ); |
| Uri aNewUri( aNewURL.makeStringAndClear() ); |
| |
| // Handle possible name clash... |
| switch ( nNameClashResolve ) |
| { |
| // fail. |
| case ucb::NameClash::ERROR: |
| if ( hasData( aNewUri ) ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::NameClashException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| task::InteractionClassification_ERROR, |
| m_aProps.getTitle() ) ), |
| xEnv ); |
| // Unreachable |
| } |
| break; |
| |
| // replace (possibly) existing object. |
| case ucb::NameClash::OVERWRITE: |
| break; |
| |
| // "invent" a new valid title. |
| case ucb::NameClash::RENAME: |
| if ( hasData( aNewUri ) ) |
| { |
| sal_Int32 nTry = 0; |
| |
| do |
| { |
| rtl::OUStringBuffer aNew = aNewUri.getUri(); |
| aNew.appendAscii( "_" ); |
| aNew.append( rtl::OUString::valueOf( ++nTry ) ); |
| aNewUri.setUri( aNew.makeStringAndClear() ); |
| } |
| while ( hasData( aNewUri ) && ( 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::OUStringBuffer aNewTitle = m_aProps.getTitle(); |
| aNewTitle.appendAscii( "_" ); |
| aNewTitle.append( rtl::OUString::valueOf( ++nTry ) ); |
| m_aProps.setTitle( aNewTitle.makeStringAndClear() ); |
| } |
| } |
| break; |
| |
| case ucb::NameClash::KEEP: // deprecated |
| case ucb::NameClash::ASK: |
| default: |
| if ( hasData( aNewUri ) ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( |
| ucb::UnsupportedNameClashException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ), |
| nNameClashResolve ) ), |
| xEnv ); |
| // Unreachable |
| } |
| break; |
| } |
| |
| // Identifier changed? |
| sal_Bool bNewId = ( aUri != aNewUri ); |
| |
| if ( bNewId ) |
| { |
| m_xIdentifier |
| = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewUri.getUri() ); |
| } |
| |
| if ( !storeData( xData, xEnv ) ) |
| { |
| 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 ) |
| { |
| //loadData( m_pProvider, m_aUri, m_aProps ); |
| |
| aGuard.clear(); |
| inserted(); |
| } |
| } |
| |
| //========================================================================= |
| void Content::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 ); |
| |
| ContentType eType = m_aProps.getType(); |
| |
| OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ), |
| "delete command only supported by streams and folders!" ); |
| |
| 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 |
| } |
| |
| m_eState = DEAD; |
| |
| aGuard.clear(); |
| deleted(); |
| |
| if ( eType == FOLDER ) |
| { |
| // Process instanciated children... |
| |
| ContentRefList aChildren; |
| queryChildren( aChildren ); |
| |
| ContentRefList::const_iterator it = aChildren.begin(); |
| ContentRefList::const_iterator end = aChildren.end(); |
| |
| while ( it != end ) |
| { |
| (*it)->destroy( bDeletePhysical, xEnv ); |
| ++it; |
| } |
| } |
| } |
| |
| //========================================================================= |
| void Content::notifyDocumentClosed() |
| { |
| osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); |
| |
| m_eState = DEAD; |
| |
| // @@@ anything else to reset or such? |
| |
| // callback follows! |
| aGuard.clear(); |
| |
| // Propagate destruction to content event listeners |
| // Remove this from provider's content list. |
| deleted(); |
| } |
| |
| //========================================================================= |
| uno::Reference< ucb::XContent > |
| Content::queryChildContent( const rtl::OUString & rRelativeChildUri ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| const rtl::OUString aMyId = getIdentifier()->getContentIdentifier(); |
| rtl::OUStringBuffer aBuf( aMyId ); |
| if ( aMyId.getStr()[ aMyId.getLength() - 1 ] != sal_Unicode( '/' ) ) |
| aBuf.appendAscii( "/" ); |
| if ( rRelativeChildUri.getStr()[ 0 ] != sal_Unicode( '/' ) ) |
| aBuf.append( rRelativeChildUri ); |
| else |
| aBuf.append( rRelativeChildUri.copy( 1 ) ); |
| |
| uno::Reference< ucb::XContentIdentifier > xChildId |
| = new ::ucbhelper::ContentIdentifier( |
| m_xSMgr, aBuf.makeStringAndClear() ); |
| |
| uno::Reference< ucb::XContent > xChild; |
| try |
| { |
| xChild = m_pProvider->queryContent( xChildId ); |
| } |
| catch ( ucb::IllegalIdentifierException const & ) |
| { |
| // handled below. |
| } |
| |
| OSL_ENSURE( xChild.is(), |
| "Content::queryChildContent - unable to create child content!" ); |
| return xChild; |
| } |
| |
| //========================================================================= |
| void Content::notifyChildRemoved( const rtl::OUString & rRelativeChildUri ) |
| { |
| osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); |
| |
| // Ugly! Need to create child content object, just to fill event properly. |
| uno::Reference< ucb::XContent > xChild |
| = queryChildContent( rRelativeChildUri ); |
| |
| if ( xChild.is() ) |
| { |
| // callback follows! |
| aGuard.clear(); |
| |
| // Notify "REMOVED" event. |
| ucb::ContentEvent aEvt( |
| static_cast< cppu::OWeakObject * >( this ), |
| ucb::ContentAction::REMOVED, |
| xChild, |
| getIdentifier() ); |
| notifyContentEvent( aEvt ); |
| } |
| } |
| |
| //========================================================================= |
| void Content::notifyChildInserted( const rtl::OUString & rRelativeChildUri ) |
| { |
| osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); |
| |
| // Ugly! Need to create child content object, just to fill event properly. |
| uno::Reference< ucb::XContent > xChild |
| = queryChildContent( rRelativeChildUri ); |
| |
| if ( xChild.is() ) |
| { |
| // callback follows! |
| aGuard.clear(); |
| |
| // Notify "INSERTED" event. |
| ucb::ContentEvent aEvt( |
| static_cast< cppu::OWeakObject * >( this ), |
| ucb::ContentAction::INSERTED, |
| xChild, |
| getIdentifier() ); |
| notifyContentEvent( aEvt ); |
| } |
| } |
| |
| //========================================================================= |
| void Content::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 |
| } |
| |
| // Does source URI scheme match? Only vnd.sun.star.tdoc is supported. |
| |
| if ( ( rInfo.SourceURL.getLength() < TDOC_URL_SCHEME_LENGTH + 2 ) ) |
| { |
| // Invaild length (to short). |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::InteractiveBadTransferURLException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ) ) ), |
| xEnv ); |
| // Unreachable |
| } |
| |
| rtl::OUString aScheme |
| = rInfo.SourceURL.copy( 0, TDOC_URL_SCHEME_LENGTH + 2 ) |
| .toAsciiLowerCase(); |
| if ( !aScheme.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM( TDOC_URL_SCHEME ":/" ) ) ) |
| { |
| // Invalid scheme. |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( ucb::InteractiveBadTransferURLException( |
| rtl::OUString(), |
| static_cast< cppu::OWeakObject * >( this ) ) ), |
| xEnv ); |
| // Unreachable |
| } |
| |
| // Does source URI describe a tdoc folder or stream? |
| Uri aSourceUri( rInfo.SourceURL ); |
| if ( !aSourceUri.isValid() ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString::createFromAscii( |
| "Invalid source URI! Syntax!" ), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| xEnv ); |
| // Unreachable |
| } |
| |
| if ( aSourceUri.isRoot() || aSourceUri.isDocument() ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString::createFromAscii( |
| "Invalid source URI! " |
| "Must describe a folder or stream!" ), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| 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 |
| } |
| } |
| |
| #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT |
| if ( m_aProps.getType() == DOCUMENT ) |
| { |
| bool bOK = false; |
| |
| uno::Reference< embed::XStorage > xStorage |
| = m_pProvider->queryStorage( |
| aSourceUri.getParentUri(), READ_WRITE_NOCREATE ); |
| if ( xStorage.is() ) |
| { |
| try |
| { |
| if ( xStorage->isStreamElement( aSourceUri.getDecodedName() ) ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString::createFromAscii( |
| "Invalid source URI! " |
| "Streams cannot be created as " |
| "children of document root!" ), |
| static_cast< cppu::OWeakObject * >( |
| this ), |
| -1 ) ), |
| xEnv ); |
| // Unreachable |
| } |
| bOK = true; |
| } |
| catch ( container::NoSuchElementException const & ) |
| { |
| // handled below. |
| } |
| catch ( lang::IllegalArgumentException const & ) |
| { |
| // handled below. |
| } |
| catch ( embed::InvalidStorageException const & ) |
| { |
| // handled below. |
| } |
| } |
| |
| if ( !bOK ) |
| { |
| ucbhelper::cancelCommandExecution( |
| uno::makeAny( lang::IllegalArgumentException( |
| rtl::OUString::createFromAscii( |
| "Invalid source URI! " |
| "Unabale to determine source type!" ), |
| static_cast< cppu::OWeakObject * >( this ), |
| -1 ) ), |
| xEnv ); |
| // Unreachable |
| } |
| } |
| #endif |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // Copy data. |
| ///////////////////////////////////////////////////////////////////////// |
| |
| rtl::OUString aNewName( rInfo.NewTitle.getLength() > 0 |
| ? rInfo.NewTitle |
| : aSourceUri.getDecodedName() ); |
| |
| if ( !copyData( aSourceUri, aNewName ) ) |
| { |
| 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_CANT_WRITE, |
| uno::Sequence< uno::Any >(&aProps, 1), |
| xEnv, |
| rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM( "Cannot copy data!" ) ), |
| this ); |
| // Unreachable |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // Copy own and all children's Additional Core Properties. |
| ///////////////////////////////////////////////////////////////////////// |
| |
| rtl::OUString aTargetUri = m_xIdentifier->getContentIdentifier(); |
| if ( ( aTargetUri.lastIndexOf( '/' ) + 1 ) != aTargetUri.getLength() ) |
| aTargetUri += rtl::OUString::createFromAscii( "/" ); |
| |
| if ( rInfo.NewTitle.getLength() > 0 ) |
| aTargetUri += ::ucb_impl::urihelper::encodeSegment( rInfo.NewTitle ); |
| else |
| aTargetUri += aSourceUri.getName(); |
| |
| if ( !copyAdditionalPropertySet( |
| aSourceUri.getUri(), aTargetUri, sal_True ) ) |
| { |
| 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_CANT_WRITE, |
| uno::Sequence< uno::Any >(&aProps, 1), |
| xEnv, |
| rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM( |
| "Cannot copy additional properties!" ) ), |
| this ); |
| // Unreachable |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // Propagate new content. |
| ///////////////////////////////////////////////////////////////////////// |
| |
| rtl::Reference< Content > xTarget; |
| try |
| { |
| uno::Reference< ucb::XContentIdentifier > xTargetId |
| = new ::ucbhelper::ContentIdentifier( m_xSMgr, aTargetUri ); |
| |
| // Note: The static cast is okay here, because its sure that |
| // m_xProvider is always the WebDAVContentProvider. |
| xTarget = static_cast< Content * >( |
| m_pProvider->queryContent( xTargetId ).get() ); |
| |
| } |
| catch ( ucb::IllegalIdentifierException const & ) |
| { |
| // queryContent |
| } |
| |
| if ( !xTarget.is() ) |
| { |
| uno::Any aProps |
| = uno::makeAny(beans::PropertyValue( |
| rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( |
| "Uri")), |
| -1, |
| uno::makeAny( aTargetUri ), |
| beans::PropertyState_DIRECT_VALUE)); |
| ucbhelper::cancelCommandExecution( |
| ucb::IOErrorCode_CANT_READ, |
| uno::Sequence< uno::Any >(&aProps, 1), |
| xEnv, |
| rtl::OUString::createFromAscii( |
| "Cannot instanciate target object!" ), |
| this ); |
| // Unreachable |
| } |
| |
| // Announce transfered content in its new folder. |
| xTarget->inserted(); |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // Remove source, if requested |
| ///////////////////////////////////////////////////////////////////////// |
| |
| if ( rInfo.MoveData ) |
| { |
| rtl::Reference< Content > xSource; |
| try |
| { |
| uno::Reference< ucb::XContentIdentifier > |
| xSourceId = new ::ucbhelper::ContentIdentifier( |
| m_xSMgr, rInfo.SourceURL ); |
| |
| // Note: The static cast is okay here, because its sure |
| // that m_xProvider is always the ContentProvider. |
| xSource = static_cast< Content * >( |
| m_xProvider->queryContent( xSourceId ).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( rInfo.SourceURL ), |
| beans::PropertyState_DIRECT_VALUE)); |
| ucbhelper::cancelCommandExecution( |
| ucb::IOErrorCode_CANT_READ, |
| uno::Sequence< uno::Any >(&aProps, 1), |
| xEnv, |
| rtl::OUString::createFromAscii( |
| "Cannot instanciate target object!" ), |
| this ); |
| // Unreachable |
| } |
| |
| // Propagate destruction (recursively). |
| 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( rInfo.SourceURL ), |
| 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. |
| if ( !xSource->removeAdditionalPropertySet( sal_True ) ) |
| { |
| 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_CANT_WRITE, |
| uno::Sequence< uno::Any >(&aProps, 1), |
| xEnv, |
| rtl::OUString::createFromAscii( |
| "Cannot remove additional properties of source object!" ), |
| this ); |
| // Unreachable |
| } |
| |
| } // rInfo.MoveData |
| } |
| |
| //========================================================================= |
| //static |
| bool Content::hasData( ContentProvider* pProvider, const Uri & rUri ) |
| { |
| if ( rUri.isRoot() ) |
| { |
| return true; // root has no storage |
| } |
| else if ( rUri.isDocument() ) |
| { |
| uno::Reference< embed::XStorage > xStorage |
| = pProvider->queryStorage( rUri.getUri(), READ ); |
| return xStorage.is(); |
| } |
| else |
| { |
| // folder or stream |
| |
| // Ask parent storage. In case that rUri describes a stream, |
| // ContentProvider::queryStorage( rUri ) would return null. |
| |
| uno::Reference< embed::XStorage > xStorage |
| = pProvider->queryStorage( rUri.getParentUri(), READ ); |
| |
| if ( !xStorage.is() ) |
| return false; |
| |
| uno::Reference< container::XNameAccess > xParentNA( |
| xStorage, uno::UNO_QUERY ); |
| |
| OSL_ENSURE( xParentNA.is(), "Got no css.container.XNameAccess!" ); |
| |
| return xParentNA->hasByName( rUri.getDecodedName() ); |
| } |
| } |
| |
| //========================================================================= |
| //static |
| bool Content::loadData( ContentProvider* pProvider, |
| const Uri & rUri, |
| ContentProperties& rProps ) |
| { |
| if ( rUri.isRoot() ) // root has no storage, but can always be created |
| { |
| rProps |
| = ContentProperties( |
| ROOT, pProvider->queryStorageTitle( rUri.getUri() ) ); |
| } |
| else if ( rUri.isDocument() ) // document must have storage |
| { |
| uno::Reference< embed::XStorage > xStorage |
| = pProvider->queryStorage( rUri.getUri(), READ ); |
| |
| if ( !xStorage.is() ) |
| return false; |
| |
| rProps |
| = ContentProperties( |
| DOCUMENT, pProvider->queryStorageTitle( rUri.getUri() ) ); |
| } |
| else // stream or folder; stream has no storage; folder has storage |
| { |
| uno::Reference< embed::XStorage > xStorage |
| = pProvider->queryStorage( rUri.getParentUri(), READ ); |
| |
| if ( !xStorage.is() ) |
| return false; |
| |
| // Check whether exists at all, is stream or folder |
| try |
| { |
| // return: true -> folder |
| // return: false -> stream |
| // NoSuchElementException -> neither folder nor stream |
| bool bIsFolder |
| = xStorage->isStorageElement( rUri.getDecodedName() ); |
| |
| rProps |
| = ContentProperties( |
| bIsFolder ? FOLDER : STREAM, |
| pProvider->queryStorageTitle( rUri.getUri() ) ); |
| } |
| catch ( container::NoSuchElementException const & ) |
| { |
| // there is no element with such name |
| //OSL_ENSURE( false, "Caught NoSuchElementException!" ); |
| return false; |
| } |
| catch ( lang::IllegalArgumentException const & ) |
| { |
| // an illegal argument is provided |
| OSL_ENSURE( false, "Caught IllegalArgumentException!" ); |
| return false; |
| } |
| catch ( embed::InvalidStorageException const & ) |
| { |
| // this storage is in invalid state for any reason |
| OSL_ENSURE( false, "Caught InvalidStorageException!" ); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| //========================================================================= |
| bool Content::storeData( const uno::Reference< io::XInputStream >& xData, |
| const uno::Reference< |
| ucb::XCommandEnvironment >& xEnv ) |
| throw ( ucb::CommandFailedException, |
| task::DocumentPasswordRequest ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| ContentType eType = m_aProps.getType(); |
| if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) |
| { |
| OSL_ENSURE( false, "storeData not supported by root and documents!" ); |
| return false; |
| } |
| |
| Uri aUri( m_xIdentifier->getContentIdentifier() ); |
| |
| if ( eType == FOLDER ) |
| { |
| uno::Reference< embed::XStorage > xStorage |
| = m_pProvider->queryStorage( aUri.getUri(), READ_WRITE_CREATE ); |
| |
| if ( !xStorage.is() ) |
| return false; |
| |
| uno::Reference< beans::XPropertySet > xPropSet( |
| xStorage, uno::UNO_QUERY ); |
| OSL_ENSURE( xPropSet.is(), |
| "Content::storeData - Got no XPropertySet interface!" ); |
| if ( !xPropSet.is() ) |
| return false; |
| |
| try |
| { |
| // According to MBA, if no mediatype is set, folder and all |
| // its contents will be lost on save of the document!!! |
| xPropSet->setPropertyValue( |
| rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), |
| uno::makeAny( |
| rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( |
| // @@@ better mediatype |
| "application/binary" ) ) ) ); |
| } |
| catch ( beans::UnknownPropertyException const & ) |
| { |
| OSL_ENSURE( false, "Property MediaType not supported!" ); |
| return false; |
| } |
| catch ( beans::PropertyVetoException const & ) |
| { |
| OSL_ENSURE( false, "Caught PropertyVetoException!" ); |
| return false; |
| } |
| catch ( lang::IllegalArgumentException const & ) |
| { |
| OSL_ENSURE( false, "Caught IllegalArgumentException!" ); |
| return false; |
| } |
| catch ( lang::WrappedTargetException const & ) |
| { |
| OSL_ENSURE( false, "Caught WrappedTargetException!" ); |
| return false; |
| } |
| |
| if ( !commitStorage( xStorage ) ) |
| return false; |
| } |
| else if ( eType == STREAM ) |
| { |
| // stream |
| |
| // Important: Parent storage and output stream must be kept alive until |
| // changes have been committed! |
| uno::Reference< embed::XStorage > xStorage |
| = m_pProvider->queryStorage( |
| aUri.getParentUri(), READ_WRITE_CREATE ); |
| uno::Reference< io::XOutputStream > xOut; |
| |
| if ( !xStorage.is() ) |
| return false; |
| |
| if ( xData.is() ) |
| { |
| // May throw CommandFailedException, DocumentPasswordRequest! |
| xOut = getTruncatedOutputStream( xEnv ); |
| |
| OSL_ENSURE( xOut.is(), "No target data stream!" ); |
| |
| try |
| { |
| uno::Sequence< sal_Int8 > aBuffer; |
| sal_Int32 nRead = xData->readSomeBytes( aBuffer, 65536 ); |
| |
| while ( nRead > 0 ) |
| { |
| aBuffer.realloc( nRead ); |
| xOut->writeBytes( aBuffer ); |
| aBuffer.realloc( 0 ); |
| nRead = xData->readSomeBytes( aBuffer, 65536 ); |
| } |
| |
| closeOutputStream( xOut ); |
| } |
| catch ( io::NotConnectedException const & ) |
| { |
| // readSomeBytes, writeBytes |
| OSL_ENSURE( false, "Caught NotConnectedException!" ); |
| closeOutputStream( xOut ); |
| return false; |
| } |
| catch ( io::BufferSizeExceededException const & ) |
| { |
| // readSomeBytes, writeBytes |
| OSL_ENSURE( false, "Caught BufferSizeExceededException!" ); |
| closeOutputStream( xOut ); |
| return false; |
| } |
| catch ( io::IOException const & ) |
| { |
| // readSomeBytes, writeBytes |
| OSL_ENSURE( false, "Caught IOException!" ); |
| closeOutputStream( xOut ); |
| return false; |
| } |
| catch ( ... ) |
| { |
| closeOutputStream( xOut ); |
| throw; |
| } |
| } |
| |
| // Commit changes. |
| if ( !commitStorage( xStorage ) ) |
| return false; |
| } |
| else |
| { |
| OSL_ENSURE( false, "Unknown content type!" ); |
| return false; |
| } |
| return true; |
| } |
| |
| //========================================================================= |
| bool Content::renameData( |
| const uno::Reference< ucb::XContentIdentifier >& xOldId, |
| const uno::Reference< ucb::XContentIdentifier >& xNewId ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| ContentType eType = m_aProps.getType(); |
| if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) |
| { |
| OSL_ENSURE( false, "renameData not supported by root and documents!" ); |
| return false; |
| } |
| |
| Uri aOldUri( xOldId->getContentIdentifier() ); |
| uno::Reference< embed::XStorage > xStorage |
| = m_pProvider->queryStorage( |
| aOldUri.getParentUri(), READ_WRITE_NOCREATE ); |
| |
| if ( !xStorage.is() ) |
| return false; |
| |
| try |
| { |
| Uri aNewUri( xNewId->getContentIdentifier() ); |
| xStorage->renameElement( |
| aOldUri.getDecodedName(), aNewUri.getDecodedName() ); |
| } |
| catch ( embed::InvalidStorageException const & ) |
| { |
| // this storage is in invalid state for eny reason |
| OSL_ENSURE( false, "Caught InvalidStorageException!" ); |
| return false; |
| } |
| catch ( lang::IllegalArgumentException const & ) |
| { |
| // an illegal argument is provided |
| OSL_ENSURE( false, "Caught IllegalArgumentException!" ); |
| return false; |
| } |
| catch ( container::NoSuchElementException const & ) |
| { |
| // there is no element with old name in this storage |
| OSL_ENSURE( false, "Caught NoSuchElementException!" ); |
| return false; |
| } |
| catch ( container::ElementExistException const & ) |
| { |
| // an element with new name already exists in this storage |
| OSL_ENSURE( false, "Caught ElementExistException!" ); |
| return false; |
| } |
| catch ( io::IOException const & ) |
| { |
| // in case of io errors during renaming |
| OSL_ENSURE( false, "Caught IOException!" ); |
| return false; |
| } |
| catch ( embed::StorageWrappedTargetException const & ) |
| { |
| // wraps other exceptions |
| OSL_ENSURE( false, "Caught StorageWrappedTargetException!" ); |
| return false; |
| } |
| |
| return commitStorage( xStorage ); |
| } |
| |
| //========================================================================= |
| bool Content::removeData() |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| ContentType eType = m_aProps.getType(); |
| if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) |
| { |
| OSL_ENSURE( false, "removeData not supported by root and documents!" ); |
| return false; |
| } |
| |
| Uri aUri( m_xIdentifier->getContentIdentifier() ); |
| uno::Reference< embed::XStorage > xStorage |
| = m_pProvider->queryStorage( |
| aUri.getParentUri(), READ_WRITE_NOCREATE ); |
| |
| if ( !xStorage.is() ) |
| return false; |
| |
| try |
| { |
| xStorage->removeElement( aUri.getDecodedName() ); |
| } |
| catch ( embed::InvalidStorageException const & ) |
| { |
| // this storage is in invalid state for eny reason |
| OSL_ENSURE( false, "Caught InvalidStorageException!" ); |
| return false; |
| } |
| catch ( lang::IllegalArgumentException const & ) |
| { |
| // an illegal argument is provided |
| OSL_ENSURE( false, "Caught IllegalArgumentException!" ); |
| return false; |
| } |
| catch ( container::NoSuchElementException const & ) |
| { |
| // there is no element with this name in this storage |
| OSL_ENSURE( false, "Caught NoSuchElementException!" ); |
| return false; |
| } |
| catch ( io::IOException const & ) |
| { |
| // in case of io errors during renaming |
| OSL_ENSURE( false, "Caught IOException!" ); |
| return false; |
| } |
| catch ( embed::StorageWrappedTargetException const & ) |
| { |
| // wraps other exceptions |
| OSL_ENSURE( false, "Caught StorageWrappedTargetException!" ); |
| return false; |
| } |
| |
| return commitStorage( xStorage ); |
| } |
| |
| //========================================================================= |
| bool Content::copyData( const Uri & rSourceUri, const rtl::OUString & rNewName ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| ContentType eType = m_aProps.getType(); |
| if ( ( eType == ROOT ) || ( eType == STREAM ) ) |
| { |
| OSL_ENSURE( false, "copyData not supported by root and streams!" ); |
| return false; |
| } |
| |
| Uri aDestUri( m_xIdentifier->getContentIdentifier() ); |
| uno::Reference< embed::XStorage > xDestStorage |
| = m_pProvider->queryStorage( aDestUri.getUri(), READ_WRITE_NOCREATE ); |
| |
| if ( !xDestStorage.is() ) |
| return false; |
| |
| uno::Reference< embed::XStorage > xSourceStorage |
| = m_pProvider->queryStorage( rSourceUri.getParentUri(), READ ); |
| |
| if ( !xSourceStorage.is() ) |
| return false; |
| |
| try |
| { |
| xSourceStorage->copyElementTo( rSourceUri.getDecodedName(), |
| xDestStorage, |
| rNewName ); |
| } |
| catch ( embed::InvalidStorageException const & ) |
| { |
| // this storage is in invalid state for eny reason |
| OSL_ENSURE( false, "Caught InvalidStorageException!" ); |
| return false; |
| } |
| catch ( lang::IllegalArgumentException const & ) |
| { |
| // an illegal argument is provided |
| OSL_ENSURE( false, "Caught IllegalArgumentException!" ); |
| return false; |
| } |
| catch ( container::NoSuchElementException const & ) |
| { |
| // there is no element with this name in this storage |
| OSL_ENSURE( false, "Caught NoSuchElementException!" ); |
| return false; |
| } |
| catch ( container::ElementExistException const & ) |
| { |
| // there is no element with this name in this storage |
| OSL_ENSURE( false, "Caught ElementExistException!" ); |
| return false; |
| } |
| catch ( io::IOException const & ) |
| { |
| // in case of io errors during renaming |
| OSL_ENSURE( false, "Caught IOException!" ); |
| return false; |
| } |
| catch ( embed::StorageWrappedTargetException const & ) |
| { |
| // wraps other exceptions |
| OSL_ENSURE( false, "Caught StorageWrappedTargetException!" ); |
| return false; |
| } |
| |
| return commitStorage( xDestStorage ); |
| } |
| |
| //========================================================================= |
| // static |
| bool Content::commitStorage( const uno::Reference< embed::XStorage > & xStorage ) |
| { |
| // Commit changes |
| uno::Reference< embed::XTransactedObject > xTO( xStorage, uno::UNO_QUERY ); |
| |
| OSL_ENSURE( xTO.is(), |
| "Required interface css.embed.XTransactedObject missing!" ); |
| try |
| { |
| xTO->commit(); |
| } |
| catch ( io::IOException const & ) |
| { |
| OSL_ENSURE( false, "Caught IOException!" ); |
| return false; |
| } |
| catch ( lang::WrappedTargetException const & ) |
| { |
| OSL_ENSURE( false, "Caught WrappedTargetException!" ); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| //========================================================================= |
| // static |
| bool Content::closeOutputStream( |
| const uno::Reference< io::XOutputStream > & xOut ) |
| { |
| if ( xOut.is() ) |
| { |
| try |
| { |
| xOut->closeOutput(); |
| return true; |
| } |
| catch ( io::NotConnectedException const & ) |
| { |
| OSL_ENSURE( false, "Caught NotConnectedException!" ); |
| } |
| catch ( io::BufferSizeExceededException const & ) |
| { |
| OSL_ENSURE( false, "Caught BufferSizeExceededException!" ); |
| } |
| catch ( io::IOException const & ) |
| { |
| OSL_ENSURE( false, "Caught IOException!" ); |
| } |
| } |
| return false; |
| } |
| |
| //========================================================================= |
| static rtl::OUString obtainPassword( |
| const rtl::OUString & rName, |
| task::PasswordRequestMode eMode, |
| const uno::Reference< ucb::XCommandEnvironment > & xEnv ) |
| throw ( ucb::CommandFailedException, |
| task::DocumentPasswordRequest ) |
| { |
| rtl::Reference< DocumentPasswordRequest > xRequest |
| = new DocumentPasswordRequest( eMode, rName ); |
| |
| if ( xEnv.is() ) |
| { |
| uno::Reference< task::XInteractionHandler > xIH |
| = xEnv->getInteractionHandler(); |
| if ( xIH.is() ) |
| { |
| xIH->handle( xRequest.get() ); |
| |
| rtl::Reference< ucbhelper::InteractionContinuation > xSelection |
| = xRequest->getSelection(); |
| |
| if ( xSelection.is() ) |
| { |
| // Handler handled the request. |
| uno::Reference< task::XInteractionAbort > xAbort( |
| xSelection.get(), uno::UNO_QUERY ); |
| if ( xAbort.is() ) |
| { |
| throw ucb::CommandFailedException( |
| rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "Abort requested by Interaction Handler." ) ), |
| uno::Reference< uno::XInterface >(), |
| xRequest->getRequest() ); |
| } |
| |
| uno::Reference< task::XInteractionPassword > xPassword( |
| xSelection.get(), uno::UNO_QUERY ); |
| if ( xPassword.is() ) |
| { |
| return xPassword->getPassword(); |
| } |
| |
| // Unknown selection. Should never happen. |
| throw ucb::CommandFailedException( |
| rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "Interaction Handler selected unknown continuation!" ) ), |
| uno::Reference< uno::XInterface >(), |
| xRequest->getRequest() ); |
| } |
| } |
| } |
| |
| // No IH or IH did not handle exception. |
| task::DocumentPasswordRequest aRequest; |
| xRequest->getRequest() >>= aRequest; |
| throw aRequest; |
| } |
| |
| //========================================================================= |
| uno::Reference< io::XInputStream > Content::getInputStream( |
| const uno::Reference< ucb::XCommandEnvironment > & xEnv ) |
| throw ( ucb::CommandFailedException, |
| task::DocumentPasswordRequest ) |
| { |
| rtl::OUString aUri; |
| rtl::OUString aPassword; |
| bool bPasswordRequested = false; |
| |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| OSL_ENSURE( m_aProps.getType() == STREAM, |
| "Content::getInputStream - content is no stream!" ); |
| |
| aUri = Uri( m_xIdentifier->getContentIdentifier() ).getUri(); |
| } |
| |
| for ( ;; ) |
| { |
| try |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| return uno::Reference< io::XInputStream >( |
| m_pProvider->queryInputStream( aUri, aPassword ) ); |
| } |
| catch ( packages::WrongPasswordException const & ) |
| { |
| // Obtain (new) password. |
| aPassword |
| = obtainPassword( aUri, /* @@@ find better title */ |
| bPasswordRequested |
| ? task::PasswordRequestMode_PASSWORD_REENTER |
| : task::PasswordRequestMode_PASSWORD_ENTER, |
| xEnv ); |
| bPasswordRequested = true; |
| } |
| } |
| } |
| |
| //========================================================================= |
| static uno::Reference< io::XOutputStream > lcl_getTruncatedOutputStream( |
| const rtl::OUString & rUri, |
| ContentProvider * pProvider, |
| const uno::Reference< ucb::XCommandEnvironment > & xEnv ) |
| throw ( ucb::CommandFailedException, |
| task::DocumentPasswordRequest ) |
| { |
| rtl::OUString aPassword; |
| bool bPasswordRequested = false; |
| for ( ;; ) |
| { |
| try |
| { |
| return uno::Reference< io::XOutputStream >( |
| pProvider->queryOutputStream( |
| rUri, aPassword, true /* truncate */ ) ); |
| } |
| catch ( packages::WrongPasswordException const & ) |
| { |
| // Obtain (new) password. |
| aPassword |
| = obtainPassword( rUri, /* @@@ find better title */ |
| bPasswordRequested |
| ? task::PasswordRequestMode_PASSWORD_REENTER |
| : task::PasswordRequestMode_PASSWORD_ENTER, |
| xEnv ); |
| bPasswordRequested = true; |
| } |
| } |
| } |
| |
| //========================================================================= |
| uno::Reference< io::XOutputStream > Content::getTruncatedOutputStream( |
| const uno::Reference< ucb::XCommandEnvironment > & xEnv ) |
| throw ( ucb::CommandFailedException, |
| task::DocumentPasswordRequest ) |
| { |
| OSL_ENSURE( m_aProps.getType() == STREAM, |
| "Content::getTruncatedOutputStream - content is no stream!" ); |
| |
| return lcl_getTruncatedOutputStream( |
| Uri( m_xIdentifier->getContentIdentifier() ).getUri(), |
| m_pProvider, |
| xEnv ); |
| } |
| |
| //========================================================================= |
| uno::Reference< io::XStream > Content::getStream( |
| const uno::Reference< ucb::XCommandEnvironment > & xEnv ) |
| throw ( ucb::CommandFailedException, |
| task::DocumentPasswordRequest ) |
| { |
| osl::Guard< osl::Mutex > aGuard( m_aMutex ); |
| |
| OSL_ENSURE( m_aProps.getType() == STREAM, |
| "Content::getStream - content is no stream!" ); |
| |
| rtl::OUString aUri( Uri( m_xIdentifier->getContentIdentifier() ).getUri() ); |
| rtl::OUString aPassword; |
| bool bPasswordRequested = false; |
| for ( ;; ) |
| { |
| try |
| { |
| return uno::Reference< io::XStream >( |
| m_pProvider->queryStream( |
| aUri, aPassword, false /* no truncate */ ) ); |
| } |
| catch ( packages::WrongPasswordException const & ) |
| { |
| // Obtain (new) password. |
| aPassword |
| = obtainPassword( aUri, /* @@@ find better title */ |
| bPasswordRequested |
| ? task::PasswordRequestMode_PASSWORD_REENTER |
| : task::PasswordRequestMode_PASSWORD_ENTER, |
| xEnv ); |
| bPasswordRequested = true; |
| } |
| } |
| } |
| |
| //========================================================================= |
| //========================================================================= |
| // |
| // ContentProperties Implementation. |
| // |
| //========================================================================= |
| //========================================================================= |
| |
| uno::Sequence< ucb::ContentInfo > |
| ContentProperties::getCreatableContentsInfo() const |
| { |
| if ( isContentCreator() ) |
| { |
| uno::Sequence< beans::Property > aProps( 1 ); |
| aProps.getArray()[ 0 ] = beans::Property( |
| rtl::OUString::createFromAscii( "Title" ), |
| -1, |
| getCppuType( static_cast< const rtl::OUString * >( 0 ) ), |
| beans::PropertyAttribute::BOUND ); |
| |
| #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT |
| if ( getType() == DOCUMENT ) |
| { |
| // streams cannot be created as direct children of document root |
| uno::Sequence< ucb::ContentInfo > aSeq( 1 ); |
| |
| // Folder. |
| aSeq.getArray()[ 0 ].Type |
| = rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE ); |
| aSeq.getArray()[ 0 ].Attributes |
| = ucb::ContentInfoAttribute::KIND_FOLDER; |
| aSeq.getArray()[ 0 ].Properties = aProps; |
| |
| return aSeq; |
| } |
| else |
| { |
| #endif |
| uno::Sequence< ucb::ContentInfo > aSeq( 2 ); |
| |
| // Folder. |
| aSeq.getArray()[ 0 ].Type |
| = rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE ); |
| aSeq.getArray()[ 0 ].Attributes |
| = ucb::ContentInfoAttribute::KIND_FOLDER; |
| aSeq.getArray()[ 0 ].Properties = aProps; |
| |
| // Stream. |
| aSeq.getArray()[ 1 ].Type |
| = rtl::OUString::createFromAscii( TDOC_STREAM_CONTENT_TYPE ); |
| aSeq.getArray()[ 1 ].Attributes |
| = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM |
| | ucb::ContentInfoAttribute::KIND_DOCUMENT; |
| aSeq.getArray()[ 1 ].Properties = aProps; |
| |
| return aSeq; |
| #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT |
| } |
| #endif |
| } |
| else |
| { |
| OSL_ENSURE( sal_False, |
| "getCreatableContentsInfo called on non-contentcreator " |
| "object!" ); |
| |
| return uno::Sequence< ucb::ContentInfo >( 0 ); |
| } |
| } |
| |
| //========================================================================= |
| bool ContentProperties::isContentCreator() const |
| { |
| return ( getType() == FOLDER ) || ( getType() == DOCUMENT ); |
| } |