diff options
Diffstat (limited to 'ucb/source/ucp/tdoc')
25 files changed, 10259 insertions, 0 deletions
diff --git a/ucb/source/ucp/tdoc/exports.map b/ucb/source/ucp/tdoc/exports.map new file mode 100644 index 000000000000..5ec50ad779c1 --- /dev/null +++ b/ucb/source/ucp/tdoc/exports.map @@ -0,0 +1,8 @@ +UDK_3_1_0 { + global: + component_getImplementationEnvironment; + component_writeInfo; + component_getFactory; + local: + *; +}; diff --git a/ucb/source/ucp/tdoc/makefile.mk b/ucb/source/ucp/tdoc/makefile.mk new file mode 100644 index 000000000000..1c2c44b124de --- /dev/null +++ b/ucb/source/ucp/tdoc/makefile.mk @@ -0,0 +1,98 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.10 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJNAME=ucb +# Version +UCPTDOC_MAJOR=1 +TARGET=ucptdoc$(UCPTDOC_MAJOR).uno +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings --------------------------------------------------------- + +.INCLUDE: settings.mk + +# --- General ----------------------------------------------------- +.IF "$(L10N_framework)"=="" + +# no "lib" prefix +DLLPRE = + +SLOFILES=\ + $(SLO)$/tdoc_provider.obj \ + $(SLO)$/tdoc_services.obj \ + $(SLO)$/tdoc_uri.obj \ + $(SLO)$/tdoc_content.obj \ + $(SLO)$/tdoc_contentcaps.obj \ + $(SLO)$/tdoc_storage.obj \ + $(SLO)$/tdoc_docmgr.obj \ + $(SLO)$/tdoc_datasupplier.obj \ + $(SLO)$/tdoc_resultset.obj \ + $(SLO)$/tdoc_documentcontentfactory.obj \ + $(SLO)$/tdoc_passwordrequest.obj \ + $(SLO)$/tdoc_stgelems.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +# --- Shared-Library --------------------------------------------------- + +SHL1TARGET=$(TARGET) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP= exports.map + +SHL1STDLIBS=\ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1LIBS=$(LIB1TARGET) + +# Make symbol renaming match library name for Mac OS X +.IF "$(OS)"=="MACOSX" +SYMBOLPREFIX=$(TARGET) +.ENDIF + +DEF1NAME=$(SHL1TARGET) + +.ENDIF # L10N_framework + +# --- Targets ---------------------------------------------------------- + +.INCLUDE: target.mk + diff --git a/ucb/source/ucp/tdoc/tdoc_content.cxx b/ucb/source/ucp/tdoc/tdoc_content.cxx new file mode 100644 index 000000000000..908d7310889b --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_content.cxx @@ -0,0 +1,3061 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_content.cxx,v $ + * $Revision: 1.16 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "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 ( !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 ( 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 + { + ////////////////////////////////////////////////////////////////// + // 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 ) +{ + if ( isContentCreator() ) + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + 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 ( m_aProps.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, + "queryCreatableContentsInfo called on non-contentcreator " + "object!" ); + + return uno::Sequence< ucb::ContentInfo >( 0 ); + } +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > SAL_CALL +Content::createNewContent( const ucb::ContentInfo& Info ) + throw( uno::RuntimeException ) +{ + if ( 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( "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() ); + + // 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( "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 +} + +//========================================================================= +bool Content::isContentCreator() +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + return + ( m_aProps.getType() == FOLDER ) || ( m_aProps.getType() == DOCUMENT ); +} + +//========================================================================= +//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; + } + } +} diff --git a/ucb/source/ucp/tdoc/tdoc_content.hxx b/ucb/source/ucp/tdoc/tdoc_content.hxx new file mode 100644 index 000000000000..c1ff14928496 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_content.hxx @@ -0,0 +1,341 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_content.hxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_TDOC_CONTENT_HXX +#define INCLUDED_TDOC_CONTENT_HXX + +#include <ucbhelper/contenthelper.hxx> +#include <com/sun/star/task/DocumentPasswordRequest.hpp> +#include <com/sun/star/ucb/XContentCreator.hpp> +#include <com/sun/star/ucb/CommandFailedException.hpp> +#include "tdoc_provider.hxx" + +#define NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT 1 + +namespace com { namespace sun { namespace star { + namespace sdbc { class XRow; } + namespace io { class XInputStream; class XOutputStream; } + namespace beans { struct PropertyValue; } + namespace ucb { struct OpenCommandArgument2; struct TransferInfo; } +} } } + +namespace tdoc_ucp +{ + +//========================================================================= + +#define TDOC_ROOT_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.TransientDocumentsRootContent" +#define TDOC_DOCUMENT_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.TransientDocumentsDocumentContent" +#define TDOC_FOLDER_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.TransientDocumentsFolderContent" +#define TDOC_STREAM_CONTENT_SERVICE_NAME \ + "com.sun.star.ucb.TransientDocumentsStreamContent" + +//========================================================================= + +enum ContentType { STREAM, FOLDER, DOCUMENT, ROOT }; + +class ContentProperties +{ +public: + ContentProperties() + {} + + ContentProperties( const ContentType & rType, const rtl::OUString & rTitle ) + : m_eType( rType ), + m_aContentType( rType == STREAM + ? rtl::OUString::createFromAscii( TDOC_STREAM_CONTENT_TYPE ) + : rType == FOLDER + ? rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE ) + : rType == DOCUMENT + ? rtl::OUString::createFromAscii( TDOC_DOCUMENT_CONTENT_TYPE ) + : rtl::OUString::createFromAscii( TDOC_ROOT_CONTENT_TYPE ) ), + m_aTitle( rTitle ) + {} + + ContentType getType() const { return m_eType; } + + // Properties + + const rtl::OUString & getContentType() const { return m_aContentType; } + + bool getIsFolder() const { return m_eType > STREAM; } + bool getIsDocument() const { return !getIsFolder(); } + + const rtl::OUString & getTitle() const { return m_aTitle; } + void setTitle( const rtl::OUString & rTitle ) { m_aTitle = rTitle; } + +private: + ContentType m_eType; + rtl::OUString m_aContentType; + rtl::OUString m_aTitle; +}; + +//========================================================================= + +class Content : public ::ucbhelper::ContentImplHelper, + public com::sun::star::ucb::XContentCreator +{ + enum ContentState { TRANSIENT, // created via createNewContent, + // but did not process "insert" yet + PERSISTENT, // processed "insert" + DEAD // processed "delete" / document was closed + }; + + ContentProperties m_aProps; + ContentState m_eState; + ContentProvider* m_pProvider; + +private: + Content( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const ContentProperties & rProps ); + Content( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > + getCommands( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual ::rtl::OUString getParentURL(); + + bool isContentCreator(); + + static bool hasData( ContentProvider* pProvider, const Uri & rUri ); + bool hasData( const Uri & rUri ) { return hasData( m_pProvider, rUri ); } + + static bool loadData( ContentProvider* pProvider, + const Uri & rUri, + ContentProperties& rProps ); + bool storeData( const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream >& xData, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( ::com::sun::star::ucb::CommandFailedException, + ::com::sun::star::task::DocumentPasswordRequest ); + bool renameData( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xOldId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& xNewId ); + bool removeData(); + + bool copyData( const Uri & rSourceUri, const rtl::OUString & rNewName ); + + ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier > + makeNewIdentifier( const rtl::OUString& rTitle ); + + typedef rtl::Reference< Content > ContentRef; + typedef std::list< ContentRef > ContentRefList; + void queryChildren( ContentRefList& rChildren ); + + sal_Bool exchangeIdentity( + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& xNewId ); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties ); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + com::sun::star::uno::Any + open( const ::com::sun::star::ucb::OpenCommandArgument2& rArg, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void insert( const ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream >& xData, + sal_Int32 nNameClashResolve, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void destroy( sal_Bool bDeletePhysical, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + void transfer( const ::com::sun::star::ucb::TransferInfo& rInfo, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( ::com::sun::star::uno::Exception ); + + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + const ContentProperties& rData, + ContentProvider* pProvider, + const ::rtl::OUString& rContentId ); + + + static bool commitStorage( + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xStorage ); + + static bool closeOutputStream( + const com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & xOut ); + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > + getInputStream( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & + xEnv ) + throw ( ::com::sun::star::ucb::CommandFailedException, + ::com::sun::star::task::DocumentPasswordRequest ); + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > + getTruncatedOutputStream( + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( ::com::sun::star::ucb::CommandFailedException, + ::com::sun::star::task::DocumentPasswordRequest ); + + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > + queryChildContent( const rtl::OUString & rRelativeChildUri ); + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > + getStream( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( ::com::sun::star::ucb::CommandFailedException, + ::com::sun::star::task::DocumentPasswordRequest ); + +public: + // Create existing content. Fail, if not already exists. + static Content* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ); + + // Create new content. Fail, if already exists. + static Content* create( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier, + const com::sun::star::ucb::ContentInfo& Info ); + + virtual ~Content(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL + getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw( ::com::sun::star::uno::RuntimeException ); + + // XContent + virtual rtl::OUString SAL_CALL + getContentType() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > SAL_CALL + getIdentifier() + throw( com::sun::star::uno::RuntimeException ); + + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( com::sun::star::uno::Exception, + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// + + // XContentCreator + virtual com::sun::star::uno::Sequence< + com::sun::star::ucb::ContentInfo > SAL_CALL + queryCreatableContentsInfo() + throw( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + throw( com::sun::star::uno::RuntimeException ); + + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// + + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties, + ContentProvider* pProvider, + const ::rtl::OUString& rContentId ); + + void notifyDocumentClosed(); + void notifyChildRemoved( const rtl::OUString & rRelativeChildUri ); + void notifyChildInserted( const rtl::OUString & rRelativeChildUri ); + + rtl::Reference< ContentProvider > getContentProvider() const + { return rtl::Reference< ContentProvider >( m_pProvider ); } +}; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_CONTENT_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_contentcaps.cxx b/ucb/source/ucp/tdoc/tdoc_contentcaps.cxx new file mode 100644 index 000000000000..792d693ab194 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_contentcaps.cxx @@ -0,0 +1,657 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_contentcaps.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + ************************************************************************** + + Props/Commands: + + root document folder folder stream stream + (new) (new) + ---------------------------------------------------------------- + ContentType r r r r r r + IsDocument r r r r r r + IsFolder r r r r r r + Title r r w w w w + Storage - - r r - - + DocumentModel - r - - - - + + getCommandInfo x x x x x x + getPropertySetInfo x x x x x x + getPropertyValues x x x x x x + setPropertyValues x x x x x x + insert - - x x x(*) x(*) + delete - - x - x - + open x x x - x - + transfer - x x - - - + +#ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT + (*) not supported by streams that are direct children of document +#endif + + *************************************************************************/ + +#include "com/sun/star/beans/Property.hpp" +#include "com/sun/star/beans/PropertyAttribute.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/embed/XStorage.hpp" +#include "com/sun/star/frame/XModel.hpp" +#include "com/sun/star/ucb/CommandInfo.hpp" +#include "com/sun/star/ucb/OpenCommandArgument2.hpp" +#include "com/sun/star/ucb/TransferInfo.hpp" + +#include "tdoc_content.hxx" + +namespace com { namespace sun { namespace star { namespace embed { + class XStorage; +} } } } + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +// +// Content implementation. +// +//========================================================================= + +//========================================================================= +// +// IMPORTENT: If any property data ( name / type / ... ) are changed, then +// Content::getPropertyValues(...) must be adapted too! +// +//========================================================================= + +// virtual +uno::Sequence< beans::Property > Content::getProperties( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_aProps.getType() == STREAM ) + { + //================================================================= + // + // Stream: Supported properties + // + //================================================================= + + static const beans::Property aStreamPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ) + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + }; + return uno::Sequence< beans::Property >( aStreamPropertyInfoTable, 4 ); + } + else if ( m_aProps.getType() == FOLDER ) + { + //================================================================= + // + // Folder: Supported properties + // + //================================================================= + + static const beans::Property aFolderPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Storage" ) ), + -1, + getCppuType( static_cast< + const uno::Reference< embed::XStorage > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + }; + return uno::Sequence< beans::Property >( aFolderPropertyInfoTable, 5 ); + } + else if ( m_aProps.getType() == DOCUMENT ) + { + //================================================================= + // + // Document: Supported properties + // + //================================================================= + + static const beans::Property aDocPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + /////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentModel" ) ), + -1, + getCppuType( static_cast< + const uno::Reference< frame::XModel > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + }; + return uno::Sequence< beans::Property >( aDocPropertyInfoTable, 5 ); + } + else + { + //================================================================= + // + // Root: Supported properties + // + //================================================================= + + OSL_ENSURE( m_aProps.getType() == ROOT, "Wrong content type!" ); + + static const beans::Property aRootPropertyInfoTable[] = + { + /////////////////////////////////////////////////////////////// + // Mandatory properties + /////////////////////////////////////////////////////////////// + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + -1, + getCppuBooleanType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ), + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY + ) + /////////////////////////////////////////////////////////////// + // Optional standard properties + /////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// + // New properties + /////////////////////////////////////////////////////////////// + }; + return uno::Sequence< beans::Property >( aRootPropertyInfoTable, 4 ); + } +} + +//========================================================================= +// virtual +uno::Sequence< ucb::CommandInfo > Content::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + + if ( m_aProps.getType() == STREAM ) + { +#ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT + Uri aUri( m_xIdentifier->getContentIdentifier() ); + Uri aParentUri( aUri.getParentUri() ); + + if ( aParentUri.isDocument() ) + { + //================================================================= + // + // Stream, that is a child of a document: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aStreamCommandInfoTable1[] = + { + /////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return uno::Sequence< + ucb::CommandInfo >( aStreamCommandInfoTable1, 6 ); + } +#endif + //================================================================= + // + // Stream: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aStreamCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return uno::Sequence< + ucb::CommandInfo >( aStreamCommandInfoTable, 7 ); + } + else if ( m_aProps.getType() == FOLDER ) + { + //================================================================= + // + // Folder: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aFolderCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), + -1, + getCppuBooleanType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return uno::Sequence< + ucb::CommandInfo >( aFolderCommandInfoTable, 8 ); + } + else if ( m_aProps.getType() == DOCUMENT ) + { + //================================================================= + // + // Document: Supported commands + // + //================================================================= + + static const ucb::CommandInfo aDocCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), + -1, + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return uno::Sequence< + ucb::CommandInfo >( aDocCommandInfoTable, 6 ); + } + else + { + //================================================================= + // + // Root: Supported commands + // + //================================================================= + + OSL_ENSURE( m_aProps.getType() == ROOT, "Wrong content type!" ); + + static const ucb::CommandInfo aRootCommandInfoTable[] = + { + /////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), + -1, + getCppuVoidType() + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), + -1, + getCppuType( + static_cast< uno::Sequence< beans::Property > * >( 0 ) ) + ), + ucb::CommandInfo( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), + -1, + getCppuType( + static_cast< + uno::Sequence< beans::PropertyValue > * >( 0 ) ) + ), + /////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////// + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + -1, + getCppuType( + static_cast< ucb::OpenCommandArgument2 * >( 0 ) ) + ) + /////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////// + }; + return uno::Sequence< + ucb::CommandInfo >( aRootCommandInfoTable, 5 ); + } +} diff --git a/ucb/source/ucp/tdoc/tdoc_datasupplier.cxx b/ucb/source/ucp/tdoc/tdoc_datasupplier.cxx new file mode 100644 index 000000000000..e96e00d6bc6e --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_datasupplier.cxx @@ -0,0 +1,471 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_datasupplier.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <vector> + +#include "osl/diagnose.h" +#include "ucbhelper/contentidentifier.hxx" + +#include "tdoc_datasupplier.hxx" +#include "tdoc_content.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +namespace tdoc_ucp +{ + +//========================================================================= +// +// struct ResultListEntry. +// +//========================================================================= + +struct ResultListEntry +{ + rtl::OUString aURL; + uno::Reference< ucb::XContentIdentifier > xId; + uno::Reference< ucb::XContent > xContent; + uno::Reference< sdbc::XRow > xRow; + + ResultListEntry( const rtl::OUString& rURL ) : aURL( rURL ) {} +}; + +//========================================================================= +// +// ResultList. +// +//========================================================================= + +typedef std::vector< ResultListEntry* > ResultList; + +//========================================================================= +// +// struct DataSupplier_Impl. +// +//========================================================================= + +struct DataSupplier_Impl +{ + osl::Mutex m_aMutex; + ResultList m_aResults; + rtl::Reference< Content > m_xContent; + uno::Reference< lang::XMultiServiceFactory > m_xSMgr; + uno::Sequence< rtl::OUString > * m_pNamesOfChildren; + sal_Int32 m_nOpenMode; + bool m_bCountFinal; + bool m_bThrowException; + + DataSupplier_Impl( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) + : m_xContent( rContent ), m_xSMgr( rxSMgr ), + m_pNamesOfChildren( 0 ), m_nOpenMode( nOpenMode ), + m_bCountFinal( false ), m_bThrowException( false ) + {} + ~DataSupplier_Impl(); +}; + +//========================================================================= +DataSupplier_Impl::~DataSupplier_Impl() +{ + ResultList::const_iterator it = m_aResults.begin(); + ResultList::const_iterator end = m_aResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } + + delete m_pNamesOfChildren; +} + +} + +//========================================================================= +//========================================================================= +// +// DataSupplier Implementation. +// +//========================================================================= +//========================================================================= + +ResultSetDataSupplier::ResultSetDataSupplier( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode ) +: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) +{ +} + +//========================================================================= +// virtual +ResultSetDataSupplier::~ResultSetDataSupplier() +{ + delete m_pImpl; +} + +//========================================================================= +// virtual +rtl::OUString +ResultSetDataSupplier::queryContentIdentifierString( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aURL; + if ( aId.getLength() ) + { + // Already cached. + return aId; + } + } + + if ( getResult( nIndex ) ) + { + // Note: getResult fills m_pImpl->m_aResults[ nIndex ]->aURL. + return m_pImpl->m_aResults[ nIndex ]->aURL; + } + return rtl::OUString(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContentIdentifier > +ResultSetDataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = m_pImpl->m_aResults[ nIndex ]->xId; + if ( xId.is() ) + { + // Already cached. + return xId; + } + } + + rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) + { + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( aId ); + m_pImpl->m_aResults[ nIndex ]->xId = xId; + return xId; + } + return uno::Reference< ucb::XContentIdentifier >(); +} + +//========================================================================= +// virtual +uno::Reference< ucb::XContent > +ResultSetDataSupplier::queryContent( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_aResults[ nIndex ]->xContent; + if ( xContent.is() ) + { + // Already cached. + return xContent; + } + } + + uno::Reference< ucb::XContentIdentifier > xId + = queryContentIdentifier( nIndex ); + if ( xId.is() ) + { + try + { + uno::Reference< ucb::XContent > xContent + = m_pImpl->m_xContent->getProvider()->queryContent( xId ); + m_pImpl->m_aResults[ nIndex ]->xContent = xContent; + return xContent; + + } + catch ( ucb::IllegalIdentifierException const & ) + { + } + } + return uno::Reference< ucb::XContent >(); +} + +//========================================================================= +// virtual +sal_Bool ResultSetDataSupplier::getResult( sal_uInt32 nIndex ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aResults.size() > nIndex ) + { + // Result already present. + return sal_True; + } + + // Result not (yet) present. + + if ( m_pImpl->m_bCountFinal ) + return sal_False; + + // Try to obtain result... + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + bool bFound = false; + + if ( queryNamesOfChildren() ) + { + for ( sal_uInt32 n = nOldCount; + n < sal::static_int_cast<sal_uInt32>( + m_pImpl->m_pNamesOfChildren->getLength()); + ++n ) + { + const rtl::OUString & rName + = m_pImpl->m_pNamesOfChildren->getConstArray()[ n ]; + + if ( !rName.getLength() ) + { + OSL_ENSURE( sal_False, + "ResultDataSupplier::getResult - Empty name!" ); + break; + } + + // Assemble URL for child. + rtl::OUString aURL = assembleChildURL( rName ); + + m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) ); + + if ( n == nIndex ) + { + // Result obtained. + bFound = true; + break; + } + } + } + + if ( !bFound ) + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( nOldCount, m_pImpl->m_aResults.size() ); + + if ( m_pImpl->m_bCountFinal ) + xResultSet->rowCountFinal(); + } + + return bFound; +} + +//========================================================================= +// virtual +sal_uInt32 ResultSetDataSupplier::totalCount() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_bCountFinal ) + return m_pImpl->m_aResults.size(); + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + + if ( queryNamesOfChildren() ) + { + for ( sal_uInt32 n = nOldCount; + n < sal::static_int_cast<sal_uInt32>( + m_pImpl->m_pNamesOfChildren->getLength()); + ++n ) + { + const rtl::OUString & rName + = m_pImpl->m_pNamesOfChildren->getConstArray()[ n ]; + + if ( !rName.getLength() ) + { + OSL_ENSURE( sal_False, + "ResultDataSupplier::getResult - Empty name!" ); + break; + } + + // Assemble URL for child. + rtl::OUString aURL = assembleChildURL( rName ); + + m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) ); + } + } + + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( nOldCount, m_pImpl->m_aResults.size() ); + + xResultSet->rowCountFinal(); + } + + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_uInt32 ResultSetDataSupplier::currentCount() +{ + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_Bool ResultSetDataSupplier::isCountFinal() +{ + return m_pImpl->m_bCountFinal; +} + +//========================================================================= +// virtual +uno::Reference< sdbc::XRow > +ResultSetDataSupplier::queryPropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + { + uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow; + if ( xRow.is() ) + { + // Already cached. + return xRow; + } + } + + if ( getResult( nIndex ) ) + { + uno::Reference< sdbc::XRow > xRow = Content::getPropertyValues( + m_pImpl->m_xSMgr, + getResultSet()->getProperties(), + m_pImpl->m_xContent->getContentProvider().get(), + queryContentIdentifierString( nIndex ) ); + m_pImpl->m_aResults[ nIndex ]->xRow = xRow; + return xRow; + } + + return uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void ResultSetDataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); +} + +//========================================================================= +// virtual +void ResultSetDataSupplier::close() +{ +} + +//========================================================================= +// virtual +void ResultSetDataSupplier::validate() + throw( ucb::ResultSetException ) +{ + if ( m_pImpl->m_bThrowException ) + throw ucb::ResultSetException(); +} + +//========================================================================= +bool ResultSetDataSupplier::queryNamesOfChildren() +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_pNamesOfChildren == 0 ) + { + uno::Sequence< rtl::OUString > * pNamesOfChildren + = new uno::Sequence< rtl::OUString >(); + + if ( !m_pImpl->m_xContent->getContentProvider()->queryNamesOfChildren( + m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(), + *pNamesOfChildren ) ) + { + OSL_ENSURE( false, "Got no list of children!" ); + m_pImpl->m_bThrowException = sal_True; + return false; + } + else + { + m_pImpl->m_pNamesOfChildren = pNamesOfChildren; + } + } + return true; +} + +//========================================================================= +::rtl::OUString +ResultSetDataSupplier::assembleChildURL( const ::rtl::OUString& aName ) +{ + rtl::OUString aContURL + = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(); + rtl::OUString aURL( aContURL ); + + sal_Int32 nUrlEnd = aURL.lastIndexOf( '/' ); + if ( nUrlEnd != aURL.getLength() - 1 ) + aURL += rtl::OUString::createFromAscii( "/" ); + + aURL += aName; + return aURL; +} diff --git a/ucb/source/ucp/tdoc/tdoc_datasupplier.hxx b/ucb/source/ucp/tdoc/tdoc_datasupplier.hxx new file mode 100644 index 000000000000..5119ac706629 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_datasupplier.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_datasupplier.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_TDOC_DATASUPPLIER_HXX +#define INCLUDED_TDOC_DATASUPPLIER_HXX + +#include <rtl/ref.hxx> +#include <com/sun/star/ucb/OpenMode.hpp> +#include <ucbhelper/resultset.hxx> + +namespace tdoc_ucp { + +struct DataSupplier_Impl; +class Content; + +class ResultSetDataSupplier : public ::ucbhelper::ResultSetDataSupplier +{ + DataSupplier_Impl* m_pImpl; + +private: + bool queryNamesOfChildren(); + ::rtl::OUString assembleChildURL( const ::rtl::OUString& aName ); + +public: + ResultSetDataSupplier( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rContent, + sal_Int32 nOpenMode = com::sun::star::ucb::OpenMode::ALL ); + virtual ~ResultSetDataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); +}; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_DATASUPPLIER_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_docmgr.cxx b/ucb/source/ucp/tdoc/tdoc_docmgr.cxx new file mode 100644 index 000000000000..51bc2ba2cb94 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_docmgr.cxx @@ -0,0 +1,694 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_docmgr.cxx,v $ + * $Revision: 1.19.24.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +/************************************************************************** + TODO + ************************************************************************** + + - filter unwanted models notified by global document event broadcaster + - help documents + - others, which I don't know yet + + *************************************************************************/ + +#include "osl/diagnose.h" +#include "rtl/ref.hxx" +#include "cppuhelper/weak.hxx" + +#include "comphelper/namedvaluecollection.hxx" +#include "comphelper/documentinfo.hxx" + +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/container/XEnumerationAccess.hpp" +#include "com/sun/star/frame/XStorable.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/document/XStorageBasedDocument.hpp" +#include "com/sun/star/awt/XTopWindow.hpp" + +#include "tdoc_docmgr.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; +using ::comphelper::DocumentInfo; + +//========================================================================= +//========================================================================= +// +// OfficeDocumentsManager Implementation. +// +//========================================================================= +//========================================================================= + +OfficeDocumentsManager::OfficeDocumentsManager( + const uno::Reference< lang::XMultiServiceFactory > & xSMgr, + OfficeDocumentsEventListener * pDocEventListener ) +: m_xSMgr( xSMgr ), + m_xDocEvtNotifier( createDocumentEventNotifier( xSMgr ) ), + m_pDocEventListener( pDocEventListener ) +{ + if ( m_xDocEvtNotifier.is() ) + { + // Order is important (multithreaded environment) + m_xDocEvtNotifier->addEventListener( this ); + buildDocumentsList(); + } +} + +//========================================================================= +// virtual +OfficeDocumentsManager::~OfficeDocumentsManager() +{ + OSL_ENSURE( m_aDocs.empty(), "document list not empty!" ); +} + +//========================================================================= +void OfficeDocumentsManager::destroy() +{ + if ( m_xDocEvtNotifier.is() ) + m_xDocEvtNotifier->removeEventListener( this ); +} + +//========================================================================= +static rtl::OUString +getDocumentId( const uno::Reference< uno::XInterface > & xDoc ) +{ + rtl::OUString aId; + + // Try to get the UID directly from the document. + uno::Reference< beans::XPropertySet > xPropSet( xDoc, uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + try + { + uno::Any aValue = xPropSet->getPropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "RuntimeUID" ) ) ); + aValue >>= aId; + } + catch ( beans::UnknownPropertyException const & ) + { + // Not actually an error. Property is optional. + } + catch ( lang::WrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught WrappedTargetException!" ); + } + } + + if ( aId.getLength() == 0 ) + { + // fallback: generate UID from document's this pointer. + // normalize the interface pointer first. Else, calls with different + // interfaces to the same object (say, XFoo and XBar) will produce + // different IDs + uno::Reference< uno::XInterface > xNormalizedIFace( xDoc, uno::UNO_QUERY ); + sal_Int64 nId = reinterpret_cast< sal_Int64 >( xNormalizedIFace.get() ); + aId = rtl::OUString::valueOf( nId ); + } + + OSL_ENSURE( aId.getLength() > 0, "getDocumentId - Empty id!" ); + return aId; +} + +//========================================================================= +// +// document::XEventListener +// +//========================================================================= + +// virtual +void SAL_CALL OfficeDocumentsManager::notifyEvent( + const document::EventObject & Event ) + throw ( uno::RuntimeException ) +{ +/* + Events documentation: OOo Developer's Guide / Writing UNO Components / Jobs +*/ + + if ( Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnLoadFinished" ) ) // document loaded + || Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnCreate" ) ) ) // document created + { + if ( isOfficeDocument( Event.Source ) ) + { + osl::MutexGuard aGuard( m_aMtx ); + + uno::Reference< frame::XModel > + xModel( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); + + DocumentList::const_iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // already known. + break; + } + ++it; + } + + if ( it == m_aDocs.end() ) + { + // new document + + uno::Reference< document::XStorageBasedDocument > + xDoc( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" ); + + uno::Reference< embed::XStorage > xStorage + = xDoc->getDocumentStorage(); + OSL_ENSURE( xStorage.is(), "Got no document storage!" ); + + rtl:: OUString aDocId = getDocumentId( Event.Source ); + rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) ); + + m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel ); + + // Propagate document closure. + OSL_ENSURE( m_pDocEventListener, + "OnLoadFinished/OnCreate event: no owner for insert event propagation!" ); + + if ( m_pDocEventListener ) + m_pDocEventListener->notifyDocumentOpened( aDocId ); + } + } + } + else if ( Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnUnload" ) ) ) + { + if ( isOfficeDocument( Event.Source ) ) + { + // Document has been closed (unloaded) + + osl::MutexGuard aGuard( m_aMtx ); + + uno::Reference< frame::XModel > + xModel( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); + + DocumentList::iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // Propagate document closure. + OSL_ENSURE( m_pDocEventListener, + "OnUnload event: no owner for close event propagation!" ); + + if ( m_pDocEventListener ) + { + rtl::OUString aDocId( (*it).first ); + m_pDocEventListener->notifyDocumentClosed( aDocId ); + } + + + break; + } + ++it; + } + + OSL_ENSURE( it != m_aDocs.end(), + "OnUnload event notified for unknown document!" ); + + if( it != m_aDocs.end() ) + m_aDocs.erase( it ); + } + } + else if ( Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnSaveDone" ) ) ) + { + if ( isOfficeDocument( Event.Source ) ) + { + osl::MutexGuard aGuard( m_aMtx ); + + uno::Reference< frame::XModel > + xModel( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); + + DocumentList::iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // Storage gets exchanged while saving. + uno::Reference< document::XStorageBasedDocument > + xDoc( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xDoc.is(), + "Got no document::XStorageBasedDocument!" ); + + uno::Reference< embed::XStorage > xStorage + = xDoc->getDocumentStorage(); + OSL_ENSURE( xStorage.is(), "Got no document storage!" ); + + (*it).second.xStorage = xStorage; + break; + } + ++it; + } + + OSL_ENSURE( it != m_aDocs.end(), + "OnSaveDone event notified for unknown document!" ); + } + } + else if ( Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnSaveAsDone" ) ) ) + { + if ( isOfficeDocument( Event.Source ) ) + { + osl::MutexGuard aGuard( m_aMtx ); + + uno::Reference< frame::XModel > + xModel( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); + + DocumentList::iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // Storage gets exchanged while saving. + uno::Reference< document::XStorageBasedDocument > + xDoc( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xDoc.is(), + "Got no document::XStorageBasedDocument!" ); + + uno::Reference< embed::XStorage > xStorage + = xDoc->getDocumentStorage(); + OSL_ENSURE( xStorage.is(), "Got no document storage!" ); + + (*it).second.xStorage = xStorage; + + // Adjust title. + (*it).second.aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) ); + break; + } + ++it; + } + + OSL_ENSURE( it != m_aDocs.end(), + "OnSaveAsDone event notified for unknown document!" ); + } + } + else if ( Event.EventName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "OnTitleChanged" ) ) ) + { + if ( isOfficeDocument( Event.Source ) ) + { + osl::MutexGuard aGuard( m_aMtx ); + + uno::Reference< frame::XModel > + xModel( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); + + DocumentList::iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // Adjust title. + rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) ); + (*it).second.aTitle = aTitle; + + // Adjust storage. + uno::Reference< document::XStorageBasedDocument > + xDoc( Event.Source, uno::UNO_QUERY ); + OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" ); + + uno::Reference< embed::XStorage > xStorage + = xDoc->getDocumentStorage(); + OSL_ENSURE( xDoc.is(), "Got no document storage!" ); + + rtl:: OUString aDocId = getDocumentId( Event.Source ); + + m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel ); + break; + } + ++it; + } + + OSL_ENSURE( it != m_aDocs.end(), + "TitleChanged event notified for unknown document!" ); + } + } +} + +//========================================================================= +// +// lang::XEventListener (base of document::XEventListener) +// +//========================================================================= + +// virtual +void SAL_CALL OfficeDocumentsManager::disposing( + const lang::EventObject& /*Source*/ ) + throw ( uno::RuntimeException ) +{ +} + +//========================================================================= +// +// Non-interface. +// +//========================================================================= + +// static +uno::Reference< document::XEventBroadcaster > +OfficeDocumentsManager::createDocumentEventNotifier( + const uno::Reference< lang::XMultiServiceFactory >& rXSMgr ) +{ + uno::Reference< uno::XInterface > xIfc; + try + { + xIfc = rXSMgr->createInstance( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.GlobalEventBroadcaster" ) ) ); + } + catch ( uno::Exception const & ) + { + // handled below. + } + + OSL_ENSURE( + xIfc.is(), + "Could not instanciate com.sun.star.frame.GlobalEventBroadcaster" ); + + if ( xIfc.is() ) + { + uno::Reference< document::XEventBroadcaster > xBC( + xIfc, uno::UNO_QUERY ); + + OSL_ENSURE( + xBC.is(), + "com.sun.star.frame.GlobalEventBroadcaster does not implement " + "interface com.sun.star.document.XEventBroadcaster!" ); + + return xBC; + } + else + return uno::Reference< document::XEventBroadcaster >(); +} + +//========================================================================= +void OfficeDocumentsManager::buildDocumentsList() +{ + OSL_ENSURE( m_xDocEvtNotifier.is(), + "OfficeDocumentsManager::buildDocumentsList - " + "No document event notifier!" ); + + uno::Reference< container::XEnumerationAccess > xEnumAccess( + m_xDocEvtNotifier, uno::UNO_QUERY_THROW ); + + uno::Reference< container::XEnumeration > xEnum + = xEnumAccess->createEnumeration(); + + osl::MutexGuard aGuard( m_aMtx ); + + while ( xEnum->hasMoreElements() ) + { + uno::Any aValue = xEnum->nextElement(); + // container::NoSuchElementException + // lang::WrappedTargetException + + try + { + uno::Reference< frame::XModel > xModel; + aValue >>= xModel; + + if ( xModel.is() ) + { + if ( isOfficeDocument( xModel ) ) + { + DocumentList::const_iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + if ( (*it).second.xModel == xModel ) + { + // already known. + break; + } + ++it; + } + + if ( it == m_aDocs.end() ) + { + // new document + rtl::OUString aDocId = getDocumentId( xModel ); + rtl::OUString aTitle = DocumentInfo::getDocumentTitle( xModel ); + + uno::Reference< document::XStorageBasedDocument > + xDoc( xModel, uno::UNO_QUERY ); + OSL_ENSURE( xDoc.is(), + "Got no document::XStorageBasedDocument!" ); + + uno::Reference< embed::XStorage > xStorage + = xDoc->getDocumentStorage(); + OSL_ENSURE( xDoc.is(), "Got no document storage!" ); + + m_aDocs[ aDocId ] + = StorageInfo( aTitle, xStorage, xModel ); + } + } + } + } + catch ( lang::DisposedException const & ) + { + // Note: Due to race conditions the XEnumeration can + // contains docs that already have been closed + } + } +} + +//========================================================================= +uno::Reference< embed::XStorage > +OfficeDocumentsManager::queryStorage( const rtl::OUString & rDocId ) +{ + osl::MutexGuard aGuard( m_aMtx ); + + DocumentList::const_iterator it = m_aDocs.find( rDocId ); + if ( it == m_aDocs.end() ) + return uno::Reference< embed::XStorage >(); + + return (*it).second.xStorage; +} + +//========================================================================= +rtl::OUString OfficeDocumentsManager::queryDocumentId( + const uno::Reference< frame::XModel > & xModel ) +{ + return getDocumentId( xModel ); +} + +//========================================================================= +uno::Reference< frame::XModel > +OfficeDocumentsManager::queryDocumentModel( const rtl::OUString & rDocId ) +{ + osl::MutexGuard aGuard( m_aMtx ); + + DocumentList::const_iterator it = m_aDocs.find( rDocId ); + if ( it == m_aDocs.end() ) + return uno::Reference< frame::XModel >(); + + return (*it).second.xModel; +} + +//========================================================================= +uno::Sequence< rtl::OUString > OfficeDocumentsManager::queryDocuments() +{ + osl::MutexGuard aGuard( m_aMtx ); + + uno::Sequence< rtl::OUString > aRet( m_aDocs.size() ); + sal_Int32 nPos = 0; + + DocumentList::const_iterator it = m_aDocs.begin(); + while ( it != m_aDocs.end() ) + { + aRet[ nPos ] = (*it).first; + ++it; + ++nPos; + } + return aRet; +} + +//========================================================================= +rtl::OUString +OfficeDocumentsManager::queryStorageTitle( const rtl::OUString & rDocId ) +{ + osl::MutexGuard aGuard( m_aMtx ); + + DocumentList::const_iterator it = m_aDocs.find( rDocId ); + if ( it == m_aDocs.end() ) + return rtl::OUString(); + + return (*it).second.aTitle; +} + +//========================================================================= +bool OfficeDocumentsManager::isDocumentPreview( + const uno::Reference< frame::XModel > & xModel ) +{ + if ( !xModel.is() ) + return false; + + ::comphelper::NamedValueCollection aArgs( + xModel->getArgs() ); + sal_Bool bIsPreview = aArgs.getOrDefault( "Preview", sal_False ); + return bIsPreview; +} + +//========================================================================= +bool OfficeDocumentsManager::isHelpDocument( + const uno::Reference< frame::XModel > & xModel ) +{ + if ( !xModel.is() ) + return false; + + ::rtl::OUString sURL( xModel->getURL() ); + if ( sURL.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.help://" ) ) ) + return true; + + return false; +} + +//========================================================================= +bool OfficeDocumentsManager::isWithoutOrInTopLevelFrame( + const uno::Reference< frame::XModel > & xModel ) +{ + if ( !xModel.is() ) + return false; + + uno::Reference< frame::XController > xController + = xModel->getCurrentController(); + if ( xController.is() ) + { + uno::Reference< frame::XFrame > xFrame + = xController->getFrame(); + if ( xFrame.is() ) + { + // don't use XFrame::isTop here. This nowadays excludes + // "sub documents" such as forms embedded in database documents + uno::Reference< awt::XTopWindow > xFrameContainer( + xFrame->getContainerWindow(), uno::UNO_QUERY ); + if ( !xFrameContainer.is() ) + return false; + } + } + + return true; +} + +//========================================================================= +bool OfficeDocumentsManager::isBasicIDE( + const uno::Reference< frame::XModel > & xModel ) +{ + if ( !m_xModuleMgr.is() ) + { + osl::MutexGuard aGuard( m_aMtx ); + if ( !m_xModuleMgr.is() ) + { + try + { + m_xModuleMgr + = uno::Reference< + frame::XModuleManager >( + m_xSMgr->createInstance( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.ModuleManager" ) ) ), + uno::UNO_QUERY ); + } + catch ( uno::Exception const & ) + { + // handled below. + } + + OSL_ENSURE( m_xModuleMgr .is(), + "Could not instanciate ModuleManager service!" ); + } + } + + if ( m_xModuleMgr.is() ) + { + rtl::OUString aModule; + try + { + aModule = m_xModuleMgr->identify( xModel ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( frame::UnknownModuleException const & ) + { + OSL_ENSURE( false, "Caught UnknownModuleException!" ); + } + + if ( aModule.getLength() > 0 ) + { + // Filter unwanted items, that are no real documents. + if ( aModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.script.BasicIDE" ) ) ) + { + return true; + } + } + } + + return false; +} + +//========================================================================= +bool OfficeDocumentsManager::isOfficeDocument( + const uno::Reference< uno::XInterface > & xDoc ) +{ + uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY ); + uno::Reference< document::XStorageBasedDocument > + xStorageBasedDoc( xModel, uno::UNO_QUERY ); + if ( !xStorageBasedDoc.is() ) + return false; + + if ( !isWithoutOrInTopLevelFrame( xModel ) ) + return false; + + if ( isDocumentPreview( xModel ) ) + return false; + + if ( isHelpDocument( xModel ) ) + return false; + + if ( isBasicIDE( xModel ) ) + return false; + + return true; +} diff --git a/ucb/source/ucp/tdoc/tdoc_docmgr.hxx b/ucb/source/ucp/tdoc/tdoc_docmgr.hxx new file mode 100644 index 000000000000..b0d420cbe6f8 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_docmgr.hxx @@ -0,0 +1,176 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_docmgr.hxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_TDOC_DOCMGR_HXX +#define INCLUDED_TDOC_DOCMGR_HXX + +#include <map> + +#include "osl/mutex.hxx" + +#include "cppuhelper/implbase1.hxx" + +#include "com/sun/star/document/XEventBroadcaster.hpp" +#include "com/sun/star/document/XEventListener.hpp" +#include "com/sun/star/embed/XStorage.hpp" +#include "com/sun/star/frame/XModel.hpp" +#include "com/sun/star/frame/XModuleManager.hpp" + +namespace tdoc_ucp { + + class OfficeDocumentsEventListener + { + public: + virtual void notifyDocumentOpened( const rtl::OUString & rDocId ) = 0; + virtual void notifyDocumentClosed( const rtl::OUString & rDocId ) = 0; + }; + + //======================================================================= + + struct StorageInfo + { + rtl::OUString aTitle; + com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > xStorage; + com::sun::star::uno::Reference< + com::sun::star::frame::XModel > xModel; + + StorageInfo() {}; // needed for STL map only. + + StorageInfo( + const rtl::OUString & rTitle, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & rxStorage, + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & rxModel ) + : aTitle( rTitle ), xStorage( rxStorage ), xModel( rxModel ) {} + }; + + //======================================================================= + + struct ltref + { + bool operator()( + const rtl::OUString & r1, const rtl::OUString & r2 ) const + { + return r1 < r2; + } + }; + + typedef std::map< rtl::OUString, StorageInfo, ltref > DocumentList; + + //======================================================================= + + class OfficeDocumentsManager : + public cppu::WeakImplHelper1< com::sun::star::document::XEventListener > + { + public: + OfficeDocumentsManager( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr, + OfficeDocumentsEventListener * pDocEventListener ); + virtual ~OfficeDocumentsManager(); + + void destroy(); + + // document::XEventListener + virtual void SAL_CALL notifyEvent( + const com::sun::star::document::EventObject & Event ) + throw ( com::sun::star::uno::RuntimeException ); + + // lang::XEventListener (base of document::XEventListener) + virtual void SAL_CALL disposing( + const com::sun::star::lang::EventObject & Source ) + throw ( com::sun::star::uno::RuntimeException ); + + // Non-interface + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + queryStorage( const rtl::OUString & rDocId ); + + rtl::OUString + queryDocumentId( + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & xModel ); + + com::sun::star::uno::Reference< com::sun::star::frame::XModel > + queryDocumentModel( const rtl::OUString & rDocId ); + + com::sun::star::uno::Sequence< rtl::OUString > + queryDocuments(); + + rtl::OUString + queryStorageTitle( const rtl::OUString & rDocId ); + + private: + static com::sun::star::uno::Reference< + com::sun::star::document::XEventBroadcaster > + createDocumentEventNotifier( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + void buildDocumentsList(); + bool + isOfficeDocument( + const com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > & xDoc ); + + bool + isDocumentPreview( + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & xModel ); + + bool + isWithoutOrInTopLevelFrame( + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & xModel ); + + bool + isBasicIDE( + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & xModel ); + + bool + isHelpDocument( + const com::sun::star::uno::Reference< + com::sun::star::frame::XModel > & xModel ); + + osl::Mutex m_aMtx; + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + com::sun::star::uno::Reference< + com::sun::star::document::XEventBroadcaster > m_xDocEvtNotifier; + com::sun::star::uno::Reference< + com::sun::star::frame::XModuleManager > m_xModuleMgr; + DocumentList m_aDocs; + OfficeDocumentsEventListener * m_pDocEventListener; + }; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_DOCMGR_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.cxx b/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.cxx new file mode 100644 index 000000000000..b455e5834bd2 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.cxx @@ -0,0 +1,191 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_documentcontentfactory.cxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "cppuhelper/factory.hxx" + +#include "tdoc_documentcontentfactory.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +//========================================================================= +// +// DocumentContentFactory Implementation. +// +//========================================================================= +//========================================================================= + +DocumentContentFactory::DocumentContentFactory( + const uno::Reference< lang::XMultiServiceFactory >& xSMgr ) +: m_xSMgr( xSMgr ) +{ +} + +//========================================================================= +// virtual +DocumentContentFactory::~DocumentContentFactory() +{ +} + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +// virtual +::rtl::OUString SAL_CALL DocumentContentFactory::getImplementationName() + throw ( uno::RuntimeException ) +{ + return getImplementationName_Static(); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL +DocumentContentFactory::supportsService( const ::rtl::OUString& ServiceName ) + throw ( uno::RuntimeException ) +{ + uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames(); + const rtl::OUString * pArray = aSNL.getConstArray(); + for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + { + if ( pArray[ i ] == ServiceName ) + return sal_True; + } + return sal_False; +} + +//========================================================================= +// virtual +uno::Sequence< ::rtl::OUString > SAL_CALL +DocumentContentFactory::getSupportedServiceNames() + throw ( uno::RuntimeException ) +{ + return getSupportedServiceNames_Static(); +} + +//========================================================================= +// static +rtl::OUString DocumentContentFactory::getImplementationName_Static() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.ucb.TransientDocumentsDocumentContentFactory" ) ); +} + +//========================================================================= +// static +uno::Sequence< rtl::OUString > +DocumentContentFactory::getSupportedServiceNames_Static() +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + aSNS.getArray()[ 0 ] + = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.TransientDocumentsDocumentContentFactory" ) ); + return aSNS; +} + +//========================================================================= +// +// XTransientDocumentsDocumentContentFactory methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL +DocumentContentFactory::createDocumentContent( + const uno::Reference< frame::XModel >& Model ) + throw ( lang::IllegalArgumentException, uno::RuntimeException ) +{ + uno::Reference< frame::XTransientDocumentsDocumentContentFactory > xDocFac; + try + { + xDocFac + = uno::Reference< frame::XTransientDocumentsDocumentContentFactory >( + m_xSMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.ucb.TransientDocumentsContentProvider" ) ) + ), + uno::UNO_QUERY ); + } + catch ( uno::Exception const & ) + { + // handled below. + } + + if ( xDocFac.is() ) + return xDocFac->createDocumentContent( Model ); + + throw uno::RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Unable to obtain document content factory!" ) ), + static_cast< cppu::OWeakObject * >( this ) ); +} + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +static uno::Reference< uno::XInterface > SAL_CALL +DocumentContentFactory_CreateInstance( + const uno::Reference< lang::XMultiServiceFactory> & rSMgr ) + throw( uno::Exception ) +{ + lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >( + new DocumentContentFactory( rSMgr ) ); + return uno::Reference< uno::XInterface >::query( pX ); +} + +//========================================================================= +// static +uno::Reference< lang::XSingleServiceFactory > +DocumentContentFactory::createServiceFactory( + const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr ) +{ + return uno::Reference< lang::XSingleServiceFactory >( + cppu::createOneInstanceFactory( + rxServiceMgr, + DocumentContentFactory::getImplementationName_Static(), + DocumentContentFactory_CreateInstance, + DocumentContentFactory::getSupportedServiceNames_Static() ) ); +} + diff --git a/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.hxx b/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.hxx new file mode 100644 index 000000000000..44a01efde938 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_documentcontentfactory.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_documentcontentfactory.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_TDOC_DOCUMENTCONTENTFACTORY_HXX +#define INCLUDED_TDOC_DOCUMENTCONTENTFACTORY_HXX + +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/frame/XTransientDocumentsDocumentContentFactory.hpp" + +#include "cppuhelper/implbase2.hxx" + +namespace tdoc_ucp { + +class DocumentContentFactory : + public cppu::WeakImplHelper2< + com::sun::star::frame::XTransientDocumentsDocumentContentFactory, + com::sun::star::lang::XServiceInfo > +{ +public: + DocumentContentFactory( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + virtual ~DocumentContentFactory(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw ( com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL + supportsService( const ::rtl::OUString& ServiceName ) + throw ( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw ( com::sun::star::uno::RuntimeException ); + + // XTransientDocumentsDocumentContentFactory + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createDocumentContent( const ::com::sun::star::uno::Reference< + com::sun::star::frame::XModel >& Model ) + throw ( com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException ); + + // Non-UNO interfaces + static rtl::OUString + getImplementationName_Static(); + static com::sun::star::uno::Sequence< rtl::OUString > + getSupportedServiceNames_Static(); + + static com::sun::star::uno::Reference< + com::sun::star::lang::XSingleServiceFactory > + createServiceFactory( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & rxServiceMgr ); +private: + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; +}; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_DOCUMENTCONTENTFACTORY_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_passwordrequest.cxx b/ucb/source/ucp/tdoc/tdoc_passwordrequest.cxx new file mode 100644 index 000000000000..65f75f5a8a67 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_passwordrequest.cxx @@ -0,0 +1,245 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_passwordrequest.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include "osl/mutex.hxx" + +#include "com/sun/star/lang/XTypeProvider.hpp" +#include "com/sun/star/task/DocumentPasswordRequest.hpp" + +#include "cppuhelper/typeprovider.hxx" +#include "ucbhelper/interactionrequest.hxx" + +#include "tdoc_passwordrequest.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +namespace tdoc_ucp +{ + class InteractionSupplyPassword : + public ucbhelper::InteractionContinuation, + public lang::XTypeProvider, + public task::XInteractionPassword + { + public: + InteractionSupplyPassword( ucbhelper::InteractionRequest * pRequest ) + : InteractionContinuation( pRequest ) {} + + // XInterface + virtual uno::Any SAL_CALL queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ); + virtual void SAL_CALL acquire() + throw (); + virtual void SAL_CALL release() + throw (); + + // XTypeProvider + virtual uno::Sequence< uno::Type > SAL_CALL getTypes() + throw ( uno::RuntimeException ); + virtual uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() + throw ( uno::RuntimeException ); + + // XInteractionContinuation + virtual void SAL_CALL select() + throw ( uno::RuntimeException ); + + // XInteractionPassword + virtual void SAL_CALL setPassword( const rtl::OUString & aPasswd ) + throw ( uno::RuntimeException ); + virtual rtl::OUString SAL_CALL getPassword() + throw ( uno::RuntimeException ); + + private: + osl::Mutex m_aMutex; + rtl::OUString m_aPassword; + }; +} // namespace tdoc_ucp + +//========================================================================= +//========================================================================= +// +// InteractionSupplyPassword Implementation. +// +//========================================================================= +//========================================================================= + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +// virtual +void SAL_CALL InteractionSupplyPassword::acquire() + throw() +{ + OWeakObject::acquire(); +} + +//========================================================================= +// virtual +void SAL_CALL InteractionSupplyPassword::release() + throw() +{ + OWeakObject::release(); +} + +//========================================================================= +// virtual +uno::Any SAL_CALL +InteractionSupplyPassword::queryInterface( const uno::Type & rType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet = cppu::queryInterface( rType, + static_cast< lang::XTypeProvider * >( this ), + static_cast< task::XInteractionContinuation * >( this ), + static_cast< task::XInteractionPassword * >( this ) ); + + return aRet.hasValue() + ? aRet : InteractionContinuation::queryInterface( rType ); +} + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +// virtual +uno::Sequence< sal_Int8 > SAL_CALL +InteractionSupplyPassword::getImplementationId() + throw( uno::RuntimeException ) +{ + static cppu::OImplementationId * pId = 0; + if ( !pId ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if ( !pId ) + { + static cppu::OImplementationId id( sal_False ); + pId = &id; + } + } + return (*pId).getImplementationId(); +} + +//========================================================================= +// virtual +uno::Sequence< uno::Type > SAL_CALL InteractionSupplyPassword::getTypes() + throw( uno::RuntimeException ) +{ + static cppu::OTypeCollection * pCollection = 0; + if ( !pCollection ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if ( !pCollection ) + { + static cppu::OTypeCollection collection( + getCppuType( static_cast< + uno::Reference< lang::XTypeProvider > * >( 0 ) ), + getCppuType( static_cast< + uno::Reference< task::XInteractionPassword > * >( 0 ) ) ); + pCollection = &collection; + } + } + return (*pCollection).getTypes(); +} + +//========================================================================= +// +// XInteractionContinuation methods. +// +//========================================================================= + +// virtual +void SAL_CALL InteractionSupplyPassword::select() + throw( uno::RuntimeException ) +{ + recordSelection(); +} + +//========================================================================= +// +// XInteractionPassword methods. +// +//========================================================================= + +// virtual +void SAL_CALL +InteractionSupplyPassword::setPassword( const ::rtl::OUString& aPasswd ) + throw ( uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + m_aPassword = aPasswd; +} + +// virtual +rtl::OUString SAL_CALL InteractionSupplyPassword::getPassword() + throw ( uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + return m_aPassword; +} + +//========================================================================= +//========================================================================= +// +// DocumentPasswordRequest Implementation. +// +//========================================================================= +//========================================================================= + +DocumentPasswordRequest::DocumentPasswordRequest( + task::PasswordRequestMode eMode, + const rtl::OUString & rDocumentName ) +{ + // Fill request... + task::DocumentPasswordRequest aRequest; +// aRequest.Message = // OUString +// aRequest.Context = // XInterface + aRequest.Classification = task::InteractionClassification_ERROR; + aRequest.Mode = eMode; + aRequest.Name = rDocumentName; + + setRequest( uno::makeAny( aRequest ) ); + + // Fill continuations... + uno::Sequence< + uno::Reference< task::XInteractionContinuation > > aContinuations( 3 ); + aContinuations[ 0 ] = new ucbhelper::InteractionAbort( this ); + aContinuations[ 1 ] = new ucbhelper::InteractionRetry( this ); + aContinuations[ 2 ] = new InteractionSupplyPassword( this ); + + setContinuations( aContinuations ); +} + diff --git a/ucb/source/ucp/tdoc/tdoc_passwordrequest.hxx b/ucb/source/ucp/tdoc/tdoc_passwordrequest.hxx new file mode 100644 index 000000000000..441c0a3145c7 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_passwordrequest.hxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_passwordrequest.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_TDOC_PASSWORDREQUEST_HXX +#define INCLUDED_TDOC_PASSWORDREQUEST_HXX + +#include "com/sun/star/task/PasswordRequestMode.hpp" +#include "com/sun/star/task/XInteractionPassword.hpp" + +#include "ucbhelper/interactionrequest.hxx" + +namespace tdoc_ucp { + + /* + @usage: + + uno::Reference< ucb::XCommandEnvironment > Environment = ...; + + if ( Environment.is() ) + { + uno::Reference< task::XInteractionHandler > xIH + = Environment->getInteractionHandler(); + if ( xIH.is() ) + { + rtl::Reference< DocumentPasswordRequest > xRequest + = new DocumentPasswordRequest( + task::PasswordRequestMode_PASSWORD_ENTER, + m_xIdentifier->getContentIdentifier() ); + 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() ) + { + // @@@ + } + + uno::Reference< task::XInteractionRetry > xRetry( + xSelection.get(), uno::UNO_QUERY ); + if ( xRetry.is() ) + { + // @@@ + } + + uno::Reference< task::XInteractionPassword > xPassword( + xSelection.get(), uno::UNO_QUERY ); + if ( xPassword.is() ) + { + rtl::OUString aPassword = xPassword->getPassword(); + + // @@@ + } + } + } + } + + */ + + class DocumentPasswordRequest : public ucbhelper::InteractionRequest + { + public: + DocumentPasswordRequest( + com::sun::star::task::PasswordRequestMode eMode, + const rtl::OUString & rDocumentName ); + }; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_PASSWORDREQUEST_HXX */ + diff --git a/ucb/source/ucp/tdoc/tdoc_provider.cxx b/ucb/source/ucp/tdoc/tdoc_provider.cxx new file mode 100644 index 000000000000..1ee6a4ee5160 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_provider.cxx @@ -0,0 +1,632 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_provider.cxx,v $ + * $Revision: 1.11 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "rtl/ustrbuf.hxx" + +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/embed/XStorage.hpp" + +#include "ucbhelper/contentidentifier.hxx" + +#include "tdoc_provider.hxx" +#include "tdoc_content.hxx" +#include "tdoc_uri.hxx" +#include "tdoc_docmgr.hxx" +#include "tdoc_storage.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +//========================================================================= +// +// ContentProvider Implementation. +// +//========================================================================= +//========================================================================= + +ContentProvider::ContentProvider( + const uno::Reference< lang::XMultiServiceFactory >& xSMgr ) +: ::ucbhelper::ContentProviderImplHelper( xSMgr ), + m_xDocsMgr( new OfficeDocumentsManager( xSMgr, this ) ), + m_xStgElemFac( new StorageElementFactory( xSMgr, m_xDocsMgr ) ) +{ +} + +//========================================================================= +// virtual +ContentProvider::~ContentProvider() +{ + if ( m_xDocsMgr.is() ) + m_xDocsMgr->destroy(); +} + +//========================================================================= +// +// XInterface methods. +// +//========================================================================= + +XINTERFACE_IMPL_4( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider, + frame::XTransientDocumentsDocumentContentFactory ); + +//========================================================================= +// +// XTypeProvider methods. +// +//========================================================================= + +XTYPEPROVIDER_IMPL_4( ContentProvider, + lang::XTypeProvider, + lang::XServiceInfo, + ucb::XContentProvider, + frame::XTransientDocumentsDocumentContentFactory ); + +//========================================================================= +// +// XServiceInfo methods. +// +//========================================================================= + +XSERVICEINFO_IMPL_1( + ContentProvider, + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.ucb.TransientDocumentsContentProvider" ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + TDOC_CONTENT_PROVIDER_SERVICE_NAME ) ) ); + +//========================================================================= +// +// Service factory implementation. +// +//========================================================================= + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider ); + +//========================================================================= +// +// XContentProvider methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL +ContentProvider::queryContent( + const uno::Reference< ucb::XContentIdentifier >& Identifier ) + throw( ucb::IllegalIdentifierException, uno::RuntimeException ) +{ + Uri aUri( Identifier->getContentIdentifier() ); + if ( !aUri.isValid() ) + throw ucb::IllegalIdentifierException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid URL!" ) ), + Identifier ); + + // Normalize URI. + uno::Reference< ucb::XContentIdentifier > xCanonicId + = new ::ucbhelper::ContentIdentifier( m_xSMgr, aUri.getUri() ); + + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent + = queryExistingContent( xCanonicId ).get(); + + if ( !xContent.is() ) + { + // Create a new content. + xContent = Content::create( m_xSMgr, this, xCanonicId ); + registerNewContent( xContent ); + } + + return xContent; +} + +//========================================================================= +// +// XTransientDocumentsDocumentContentFactory methods. +// +//========================================================================= + +// virtual +uno::Reference< ucb::XContent > SAL_CALL +ContentProvider::createDocumentContent( + const uno::Reference< frame::XModel >& Model ) + throw ( lang::IllegalArgumentException, uno::RuntimeException ) +{ + // model -> id -> content identifier -> queryContent + if ( m_xDocsMgr.is() ) + { + rtl::OUString aDocId = m_xDocsMgr->queryDocumentId( Model ); + if ( aDocId.getLength() > 0 ) + { + rtl::OUStringBuffer aBuffer; + aBuffer.appendAscii( TDOC_URL_SCHEME ":/" ); + aBuffer.append( aDocId ); + + uno::Reference< ucb::XContentIdentifier > xId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, aBuffer.makeStringAndClear() ); + + osl::MutexGuard aGuard( m_aMutex ); + + // Check, if a content with given id already exists... + uno::Reference< ucb::XContent > xContent + = queryExistingContent( xId ).get(); + + if ( !xContent.is() ) + { + // Create a new content. + xContent = Content::create( m_xSMgr, this, xId ); + } + + if ( xContent.is() ) + return xContent; + + // no content. + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Illegal Content Identifier!" ) ), + static_cast< cppu::OWeakObject * >( this ), + 1 ); + } + else + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Unable to obtain document id from model!" ) ), + static_cast< cppu::OWeakObject * >( this ), + 1 ); + } + } + else + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "No Document Manager!" ) ), + static_cast< cppu::OWeakObject * >( this ), + 1 ); + } +} + +//========================================================================= +// +// interface OfficeDocumentsEventListener +// +//========================================================================= + +// virtual +void ContentProvider::notifyDocumentClosed( const rtl::OUString & rDocId ) +{ + osl::MutexGuard aGuard( getContentListMutex() ); + + ::ucbhelper::ContentRefList aAllContents; + queryExistingContents( aAllContents ); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + // Notify all content objects related to the closed doc. + + bool bFoundDocumentContent = false; + rtl::Reference< Content > xRoot; + + while ( it != end ) + { + Uri aUri( (*it)->getIdentifier()->getContentIdentifier() ); + OSL_ENSURE( aUri.isValid(), + "ContentProvider::notifyDocumentClosed - Invalid URI!" ); + + if ( !bFoundDocumentContent ) + { + if ( aUri.isRoot() ) + { + xRoot = static_cast< Content * >( (*it).get() ); + } + else if ( aUri.isDocument() ) + { + if ( aUri.getDocumentId() == rDocId ) + { + bFoundDocumentContent = true; + + // document content will notify removal of child itself; + // no need for the root to propagate this. + xRoot.clear(); + } + } + } + + if ( aUri.getDocumentId() == rDocId ) + { + // Inform content. + rtl::Reference< Content > xContent + = static_cast< Content * >( (*it).get() ); + + xContent->notifyDocumentClosed(); + } + + ++it; + } + + if ( xRoot.is() ) + { + // No document content found for rDocId but root content + // instanciated. Root content must announce document removal + // to content event listeners. + xRoot->notifyChildRemoved( rDocId ); + } +} + +//========================================================================= +// virtual +void ContentProvider::notifyDocumentOpened( const rtl::OUString & rDocId ) +{ + osl::MutexGuard aGuard( getContentListMutex() ); + + ::ucbhelper::ContentRefList aAllContents; + queryExistingContents( aAllContents ); + + ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); + ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); + + // Find root content. If instanciated let it propagate document insertion. + + while ( it != end ) + { + Uri aUri( (*it)->getIdentifier()->getContentIdentifier() ); + OSL_ENSURE( aUri.isValid(), + "ContentProvider::notifyDocumentOpened - Invalid URI!" ); + + if ( aUri.isRoot() ) + { + rtl::Reference< Content > xRoot + = static_cast< Content * >( (*it).get() ); + xRoot->notifyChildInserted( rDocId ); + + // Done. + break; + } + + ++it; + } +} + +//========================================================================= +// +// Non-UNO +// +//========================================================================= + +uno::Reference< embed::XStorage > +ContentProvider::queryStorage( const rtl::OUString & rUri, + StorageAccessMode eMode ) const +{ + if ( m_xStgElemFac.is() ) + { + try + { + return m_xStgElemFac->createStorage( rUri, eMode ); + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + // Okay to happen, for instance when the storage does not exist. + //OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" ); + } + } + return uno::Reference< embed::XStorage >(); +} + +//========================================================================= +uno::Reference< embed::XStorage > +ContentProvider::queryStorageClone( const rtl::OUString & rUri ) const +{ + if ( m_xStgElemFac.is() ) + { + try + { + Uri aUri( rUri ); + uno::Reference< embed::XStorage > xParentStorage + = m_xStgElemFac->createStorage( aUri.getParentUri(), READ ); + uno::Reference< embed::XStorage > xStorage + = m_xStgElemFac->createTemporaryStorage(); + + xParentStorage->copyStorageElementLastCommitTo( + aUri.getDecodedName(), xStorage ); + return xStorage; + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + // Okay to happen, for instance when the storage does not exist. + //OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" ); + } + } + + return uno::Reference< embed::XStorage >(); +} + +//========================================================================= +uno::Reference< io::XInputStream > +ContentProvider::queryInputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword ) const + throw ( packages::WrongPasswordException ) +{ + if ( m_xStgElemFac.is() ) + { + try + { + return m_xStgElemFac->createInputStream( rUri, rPassword ); + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" ); + } +// catch ( packages::WrongPasswordException const & ) +// { +// // the key provided is wrong; rethrow; to be handled by caller. +// throw; +// } + } + return uno::Reference< io::XInputStream >(); +} + +//========================================================================= +uno::Reference< io::XOutputStream > +ContentProvider::queryOutputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) const + throw ( packages::WrongPasswordException ) +{ + if ( m_xStgElemFac.is() ) + { + try + { + return + m_xStgElemFac->createOutputStream( rUri, rPassword, bTruncate ); + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + // Okay to happen, for instance when the storage does not exist. + //OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" ); + } +// catch ( packages::WrongPasswordException const & ) +// { +// // the key provided is wrong; rethrow; to be handled by caller. +// throw; +// } + } + return uno::Reference< io::XOutputStream >(); +} + +//========================================================================= +uno::Reference< io::XStream > +ContentProvider::queryStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) const + throw ( packages::WrongPasswordException ) +{ + if ( m_xStgElemFac.is() ) + { + try + { + return m_xStgElemFac->createStream( rUri, rPassword, bTruncate ); + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + // Okay to happen, for instance when the storage does not exist. + //OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, "Caught embed::StorageWrappedTargetException!" ); + } +// catch ( packages::WrongPasswordException const & ) +// { +// // the key provided is wrong; rethrow; to be handled by caller. +// throw; +// } + } + return uno::Reference< io::XStream >(); +} + +//========================================================================= +bool ContentProvider::queryNamesOfChildren( + const rtl::OUString & rUri, uno::Sequence< rtl::OUString > & rNames ) const +{ + Uri aUri( rUri ); + if ( aUri.isRoot() ) + { + // special handling for root, which has no storage, but children. + if ( m_xDocsMgr.is() ) + { + rNames = m_xDocsMgr->queryDocuments(); + return true; + } + } + else + { + if ( m_xStgElemFac.is() ) + { + try + { + uno::Reference< embed::XStorage > xStorage + = m_xStgElemFac->createStorage( rUri, READ ); + + OSL_ENSURE( xStorage.is(), "Got no Storage!" ); + + if ( xStorage.is() ) + { + uno::Reference< container::XNameAccess > xNA( + xStorage, uno::UNO_QUERY ); + + OSL_ENSURE( xNA.is(), "Got no css.container.XNameAccess!" ); + if ( xNA.is() ) + { + rNames = xNA->getElementNames(); + return true; + } + } + } + catch ( embed::InvalidStorageException const & ) + { + OSL_ENSURE( false, "Caught InvalidStorageException!" ); + } + catch ( lang::IllegalArgumentException const & ) + { + OSL_ENSURE( false, "Caught IllegalArgumentException!" ); + } + catch ( io::IOException const & ) + { + // Okay to happen, for instance if the storage does not exist. + //OSL_ENSURE( false, "Caught IOException!" ); + } + catch ( embed::StorageWrappedTargetException const & ) + { + OSL_ENSURE( false, + "Caught embed::StorageWrappedTargetException!" ); + } + } + } + return false; +} + +//========================================================================= +rtl::OUString +ContentProvider::queryStorageTitle( const rtl::OUString & rUri ) const +{ + rtl::OUString aTitle; + + Uri aUri( rUri ); + if ( aUri.isRoot() ) + { + // always empty. + aTitle = rtl::OUString(); + } + else if ( aUri.isDocument() ) + { + // for documents, title shall not be derived from URL. It shall + // be somethimg more 'speaking' than just the document UID. + if ( m_xDocsMgr.is() ) + aTitle = m_xDocsMgr->queryStorageTitle( aUri.getDocumentId() ); + } + else + { + // derive title from URL + aTitle = aUri.getDecodedName(); + } + + OSL_ENSURE( ( aTitle.getLength() > 0 ) || aUri.isRoot(), + "ContentProvider::queryStorageTitle - empty title!" ); + return aTitle; +} + +//========================================================================= +uno::Reference< frame::XModel > +ContentProvider::queryDocumentModel( const rtl::OUString & rUri ) const +{ + uno::Reference< frame::XModel > xModel; + + if ( m_xDocsMgr.is() ) + { + Uri aUri( rUri ); + xModel = m_xDocsMgr->queryDocumentModel( aUri.getDocumentId() ); + } + + OSL_ENSURE( xModel.is(), + "ContentProvider::queryDocumentModel - no model!" ); + return xModel; +} + diff --git a/ucb/source/ucp/tdoc/tdoc_provider.hxx b/ucb/source/ucp/tdoc/tdoc_provider.hxx new file mode 100644 index 000000000000..28e60757216e --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_provider.hxx @@ -0,0 +1,151 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_provider.hxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_TDOC_PROVIDER_HXX +#define INCLUDED_TDOC_PROVIDER_HXX + +#include "rtl/ref.hxx" +#include <com/sun/star/frame/XTransientDocumentsDocumentContentFactory.hpp> +#include <com/sun/star/packages/WrongPasswordException.hpp> +#include "ucbhelper/providerhelper.hxx" +#include "tdoc_uri.hxx" // for TDOC_URL_SCHEME +#include "tdoc_docmgr.hxx" +#include "tdoc_storage.hxx" // for StorageAccessMode + +namespace com { namespace sun { namespace star { namespace embed { + class XStorage; +} } } } + +namespace com { namespace sun { namespace star { namespace frame { + class XModel; +} } } } + +namespace tdoc_ucp { + +//========================================================================= + +#define TDOC_CONTENT_PROVIDER_SERVICE_NAME \ + "com.sun.star.ucb.TransientDocumentsContentProvider" +#define TDOC_CONTENT_PROVIDER_SERVICE_NAME_LENGTH 50 + +#define TDOC_ROOT_CONTENT_TYPE \ + "application/" TDOC_URL_SCHEME "-root" +#define TDOC_DOCUMENT_CONTENT_TYPE \ + "application/" TDOC_URL_SCHEME "-document" +#define TDOC_FOLDER_CONTENT_TYPE \ + "application/" TDOC_URL_SCHEME "-folder" +#define TDOC_STREAM_CONTENT_TYPE \ + "application/" TDOC_URL_SCHEME "-stream" + +//========================================================================= + +class StorageElementFactory; + +class ContentProvider : + public ::ucbhelper::ContentProviderImplHelper, + public com::sun::star::frame::XTransientDocumentsDocumentContentFactory, + public OfficeDocumentsEventListener +{ +public: + ContentProvider( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rXSMgr ); + virtual ~ContentProvider(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_DECL() + + // XContentProvider + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + queryContent( const com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier >& Identifier ) + throw( com::sun::star::ucb::IllegalIdentifierException, + com::sun::star::uno::RuntimeException ); + + // XTransientDocumentsDocumentContentFactory + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createDocumentContent( const ::com::sun::star::uno::Reference< + com::sun::star::frame::XModel >& Model ) + throw ( com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException ); + + // Non-UNO interfaces + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + queryStorage( const rtl::OUString & rUri, StorageAccessMode eMode ) const; + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + queryStorageClone( const rtl::OUString & rUri ) const; + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + queryInputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword ) const + throw ( com::sun::star::packages::WrongPasswordException ); + + com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > + queryOutputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) const + throw ( com::sun::star::packages::WrongPasswordException ); + + com::sun::star::uno::Reference< com::sun::star::io::XStream > + queryStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) const + throw ( com::sun::star::packages::WrongPasswordException ); + + bool queryNamesOfChildren( + const rtl::OUString & rUri, + com::sun::star::uno::Sequence< rtl::OUString > & rNames ) const; + + // storage properties + rtl::OUString queryStorageTitle( const rtl::OUString & rUri ) const; + + com::sun::star::uno::Reference< com::sun::star::frame::XModel > + queryDocumentModel( const rtl::OUString & rUri ) const; + + // interface OfficeDocumentsEventListener + virtual void notifyDocumentOpened( const rtl::OUString & rDocId ); + virtual void notifyDocumentClosed( const rtl::OUString & rDocId ); + +private: + rtl::Reference< OfficeDocumentsManager > m_xDocsMgr; + rtl::Reference< StorageElementFactory > m_xStgElemFac; +}; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_PROVIDER_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_resultset.cxx b/ucb/source/ucp/tdoc/tdoc_resultset.cxx new file mode 100644 index 000000000000..e2c3053514ce --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_resultset.cxx @@ -0,0 +1,98 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_resultset.cxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - This implementation is not a dynamic result set!!! It only implements + the necessary interfaces, but never recognizes/notifies changes!!! + + *************************************************************************/ + +#include "ucbhelper/resultset.hxx" + +#include "tdoc_datasupplier.hxx" +#include "tdoc_resultset.hxx" +#include "tdoc_content.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +//========================================================================= +// +// DynamicResultSet Implementation. +// +//========================================================================= +//========================================================================= + +DynamicResultSet::DynamicResultSet( + const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const ucb::OpenCommandArgument2& rCommand ) +: ResultSetImplHelper( rxSMgr, rCommand ), + m_xContent( rxContent ) +{ +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( + m_xSMgr, + m_aCommand.Properties, + new ResultSetDataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ) ); +} + +//========================================================================= +void DynamicResultSet::initDynamic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( + m_xSMgr, + m_aCommand.Properties, + new ResultSetDataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ) ); + m_xResultSet2 = m_xResultSet1; +} + diff --git a/ucb/source/ucp/tdoc/tdoc_resultset.hxx b/ucb/source/ucp/tdoc/tdoc_resultset.hxx new file mode 100644 index 000000000000..f177402cb692 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_resultset.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_resultset.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_TDOC_RESULTSET_HXX +#define INCLUDED_TDOC_RESULTSET_HXX + +#include <rtl/ref.hxx> +#include <ucbhelper/resultsethelper.hxx> + +namespace tdoc_ucp { + +class Content; + +class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper +{ + rtl::Reference< Content > m_xContent; + +private: + virtual void initStatic(); + virtual void initDynamic(); + +public: + DynamicResultSet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< Content >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand ); +}; + +} + +#endif /* !INCLUDED_TDOC_RESULTSET_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_services.cxx b/ucb/source/ucp/tdoc/tdoc_services.cxx new file mode 100644 index 000000000000..3ab332323b64 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_services.cxx @@ -0,0 +1,154 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_services.cxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" + +#include "tdoc_provider.hxx" +#include "tdoc_documentcontentfactory.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +static sal_Bool writeInfo( void * pRegistryKey, + const rtl::OUString & rImplementationName, + uno::Sequence< rtl::OUString > const & rServiceNames ) +{ + rtl::OUString aKeyName( rtl::OUString::createFromAscii( "/" ) ); + aKeyName += rImplementationName; + aKeyName += rtl::OUString::createFromAscii( "/UNO/SERVICES" ); + + uno::Reference< registry::XRegistryKey > xKey; + try + { + xKey = static_cast< registry::XRegistryKey * >( + pRegistryKey )->createKey( aKeyName ); + } + catch ( registry::InvalidRegistryException const & ) + { + } + + if ( !xKey.is() ) + return sal_False; + + sal_Bool bSuccess = sal_True; + + for ( sal_Int32 n = 0; n < rServiceNames.getLength(); ++n ) + { + try + { + xKey->createKey( rServiceNames[ n ] ); + } + catch ( registry::InvalidRegistryException const & ) + { + bSuccess = sal_False; + break; + } + } + return bSuccess; +} + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" sal_Bool SAL_CALL component_writeInfo( + void * /*pServiceManager*/, void * pRegistryKey ) +{ + return pRegistryKey && + + ////////////////////////////////////////////////////////////////////// + // Transient Documents Content Provider. + ////////////////////////////////////////////////////////////////////// + + writeInfo( pRegistryKey, + ContentProvider::getImplementationName_Static(), + ContentProvider::getSupportedServiceNames_Static() ) && + + ////////////////////////////////////////////////////////////////////// + // Transient Documents Document Content Factory. + ////////////////////////////////////////////////////////////////////// + + writeInfo( pRegistryKey, + DocumentContentFactory::getImplementationName_Static(), + DocumentContentFactory::getSupportedServiceNames_Static() ); +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + uno::Reference< lang::XMultiServiceFactory > xSMgr( + reinterpret_cast< lang::XMultiServiceFactory * >( + pServiceManager ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // Transient Documents Content Provider. + ////////////////////////////////////////////////////////////////////// + + if ( ContentProvider::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = ContentProvider::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + // Transient Documents Document Content Factory. + ////////////////////////////////////////////////////////////////////// + + else if ( DocumentContentFactory::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = DocumentContentFactory::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/ucp/tdoc/tdoc_stgelems.cxx b/ucb/source/ucp/tdoc/tdoc_stgelems.cxx new file mode 100644 index 000000000000..359736916222 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_stgelems.cxx @@ -0,0 +1,1111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_stgelems.cxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - remove root storage access workaround + + *************************************************************************/ + +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/reflection/XProxyFactory.hpp" + +#include "tdoc_uri.hxx" + +#include "tdoc_stgelems.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + +//========================================================================= +//========================================================================= +// +// ParentStorageHolder Implementation. +// +//========================================================================= +//========================================================================= + +ParentStorageHolder::ParentStorageHolder( + const uno::Reference< embed::XStorage > & xParentStorage, + const rtl::OUString & rUri ) +: m_xParentStorage( xParentStorage ), + m_bParentIsRootStorage( false ) +{ + Uri aUri( rUri ); + if ( aUri.isDocument() ) + m_bParentIsRootStorage = true; +} + +//========================================================================= +//========================================================================= +// +// Storage Implementation. +// +//========================================================================= +//========================================================================= + +Storage::Storage( const uno::Reference< lang::XMultiServiceFactory > & xSMgr, + const rtl::Reference< StorageElementFactory > & xFactory, + const rtl::OUString & rUri, + const uno::Reference< embed::XStorage > & xParentStorage, + const uno::Reference< embed::XStorage > & xStorageToWrap ) +: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ), + m_xFactory( xFactory ), + m_xWrappedStorage( xStorageToWrap ), + m_xWrappedTransObj( xStorageToWrap, uno::UNO_QUERY ), // optional interface + m_xWrappedComponent( xStorageToWrap, uno::UNO_QUERY ), + m_xWrappedTypeProv( xStorageToWrap, uno::UNO_QUERY ), + m_bIsDocumentStorage( Uri( rUri ).isDocument() ) +{ + OSL_ENSURE( m_xWrappedStorage.is(), + "Storage::Storage: No storage to wrap!" ); + + OSL_ENSURE( m_xWrappedComponent.is(), + "Storage::Storage: No component to wrap!" ); + + OSL_ENSURE( m_xWrappedTypeProv.is(), + "Storage::Storage: No Type Provider!" ); + + // Use proxy factory service to create aggregatable proxy. + try + { + uno::Reference< reflection::XProxyFactory > xProxyFac( + xSMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.reflection.ProxyFactory" ) ) ), + uno::UNO_QUERY ); + if ( xProxyFac.is() ) + { + m_xAggProxy = xProxyFac->createProxy( m_xWrappedStorage ); + } + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( false, "Storage::Storage: Caught exception!" ); + } + + OSL_ENSURE( m_xAggProxy.is(), + "Storage::Storage: Wrapped storage cannot be aggregated!" ); + + if ( m_xAggProxy.is() ) + { + osl_incrementInterlockedCount( &m_refCount ); + { + // Solaris compiler problem: + // Extra block to enforce destruction of temporary object created + // in next statement _before_ osl_decrementInterlockedCount is + // called. Otherwise 'this' will destroy itself even before ctor + // is completed (See impl. of XInterface::release())! + + m_xAggProxy->setDelegator( + static_cast< cppu::OWeakObject * >( this ) ); + } + osl_decrementInterlockedCount( &m_refCount ); + } +} + +//========================================================================= +// virtual +Storage::~Storage() +{ + if ( m_xAggProxy.is() ) + m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() ); + + // Never dispose a document storage. Not owner! + if ( !isDocumentStorage() ) + { + if ( m_xWrappedComponent.is() ) + { + // "Auto-dispose"... + try + { + m_xWrappedComponent->dispose(); + } + catch ( lang::DisposedException const & ) + { + // might happen. + } + catch ( ... ) + { + OSL_ENSURE( false, "Storage::~Storage - Caught exception!" ); + } + } + } +} + +//========================================================================= +// +// uno::XInterface +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Storage::queryInterface( const uno::Type& aType ) + throw ( uno::RuntimeException ) +{ + // First, try to use interfaces implemented by myself and base class(es) + uno::Any aRet = StorageUNOBase::queryInterface( aType ); + + if ( aRet.hasValue() ) + return aRet; + + // Try to use requested interface from aggregated storage + return m_xAggProxy->queryAggregation( aType ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::acquire() + throw () +{ + osl_incrementInterlockedCount( &m_refCount ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::release() + throw () +{ + if ( osl_decrementInterlockedCount( &m_refCount ) == 0 ) + { + m_xFactory->releaseElement( this ); + delete this; + } +} + +//========================================================================= +// +// lang::XTypeProvider +// +//========================================================================= + +// virtual +uno::Sequence< uno::Type > SAL_CALL Storage::getTypes() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getTypes(); +} + +//========================================================================= +// virtual +uno::Sequence< sal_Int8 > SAL_CALL Storage::getImplementationId() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getImplementationId(); +} + +//========================================================================= +// +// lang::XComponent (base of embed::XStorage) +// +//========================================================================= +// virtual +void SAL_CALL Storage::dispose() + throw ( uno::RuntimeException ) +{ + m_xWrappedStorage->dispose(); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + m_xWrappedStorage->addEventListener( xListener ); +} +//========================================================================= +// virtual +void SAL_CALL Storage::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) + throw (uno::RuntimeException) +{ + m_xWrappedStorage->removeEventListener( aListener ); +} + +//========================================================================= +// +// container::XElementAccess (base of container::XNameAccess) +// +//========================================================================= + +// virtual +uno::Type SAL_CALL Storage::getElementType() + throw ( uno::RuntimeException ) +{ + return m_xWrappedStorage->getElementType(); +} + +//========================================================================= +// virtual +::sal_Bool SAL_CALL Storage::hasElements() + throw ( uno::RuntimeException ) +{ + return m_xWrappedStorage->hasElements(); +} + +//========================================================================= +// +// container::XNameAccess (base of embed::XStorage) +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Storage::getByName( const ::rtl::OUString& aName ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->getByName( aName ); +} + +//========================================================================= +// virtual +uno::Sequence< ::rtl::OUString > SAL_CALL Storage::getElementNames() + throw ( uno::RuntimeException ) +{ + return m_xWrappedStorage->getElementNames(); +} + +//========================================================================= +// virtual +::sal_Bool SAL_CALL Storage::hasByName( const ::rtl::OUString& aName ) + throw ( uno::RuntimeException ) +{ + return m_xWrappedStorage->hasByName( aName ); +} + +//========================================================================= +// +// embed::XStorage +// +//========================================================================= + +// virtual +void SAL_CALL Storage::copyToStorage( + const uno::Reference< embed::XStorage >& xDest ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + m_xWrappedStorage->copyToStorage( xDest ); +} + +//========================================================================= +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::openStreamElement( + const ::rtl::OUString& aStreamName, sal_Int32 nOpenMode ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + packages::WrongPasswordException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->openStreamElement( aStreamName, nOpenMode ); +} + +//========================================================================= +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::openEncryptedStreamElement( + const ::rtl::OUString& aStreamName, + sal_Int32 nOpenMode, + const ::rtl::OUString& aPassword ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + packages::NoEncryptionException, + packages::WrongPasswordException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->openEncryptedStreamElement( + aStreamName, nOpenMode, aPassword ); +} + +//========================================================================= +// virtual +uno::Reference< embed::XStorage > SAL_CALL Storage::openStorageElement( + const ::rtl::OUString& aStorName, sal_Int32 nOpenMode ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->openStorageElement( aStorName, nOpenMode ); +} + +//========================================================================= +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::cloneStreamElement( + const ::rtl::OUString& aStreamName ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + packages::WrongPasswordException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->cloneStreamElement( aStreamName ); +} + +//========================================================================= +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::cloneEncryptedStreamElement( + const ::rtl::OUString& aStreamName, + const ::rtl::OUString& aPassword ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + packages::NoEncryptionException, + packages::WrongPasswordException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->cloneEncryptedStreamElement( aStreamName, + aPassword ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::copyLastCommitTo( + const uno::Reference< embed::XStorage >& xTargetStorage ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException) +{ + m_xWrappedStorage->copyLastCommitTo( xTargetStorage ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::copyStorageElementLastCommitTo( + const ::rtl::OUString& aStorName, + const uno::Reference< embed::XStorage >& xTargetStorage ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException) +{ + m_xWrappedStorage->copyStorageElementLastCommitTo( aStorName, xTargetStorage ); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL Storage::isStreamElement( + const ::rtl::OUString& aElementName ) + throw ( container::NoSuchElementException, + lang::IllegalArgumentException, + embed::InvalidStorageException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->isStreamElement( aElementName ); +} + +//========================================================================= +// virtual +sal_Bool SAL_CALL Storage::isStorageElement( + const ::rtl::OUString& aElementName ) + throw ( container::NoSuchElementException, + lang::IllegalArgumentException, + embed::InvalidStorageException, + uno::RuntimeException ) +{ + return m_xWrappedStorage->isStorageElement( aElementName ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::removeElement( const ::rtl::OUString& aElementName ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + container::NoSuchElementException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + m_xWrappedStorage->removeElement( aElementName ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::renameElement( const ::rtl::OUString& aEleName, + const ::rtl::OUString& aNewName ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + container::NoSuchElementException, + container::ElementExistException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + m_xWrappedStorage->renameElement( aEleName, aNewName ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::copyElementTo( + const ::rtl::OUString& aElementName, + const uno::Reference< embed::XStorage >& xDest, + const ::rtl::OUString& aNewName ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + container::NoSuchElementException, + container::ElementExistException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + m_xWrappedStorage->copyElementTo( aElementName, xDest, aNewName ); +} + +//========================================================================= +// virtual +void SAL_CALL Storage::moveElementTo( + const ::rtl::OUString& aElementName, + const uno::Reference< embed::XStorage >& xDest, + const ::rtl::OUString& rNewName ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + container::NoSuchElementException, + container::ElementExistException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + m_xWrappedStorage->moveElementTo( aElementName, xDest, rNewName ); +} + +//========================================================================= +// +// embed::XTransactedObject +// +//========================================================================= + +// virtual +void SAL_CALL Storage::commit() + throw ( io::IOException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + // Never commit a root storage (-> has no parent)! + // Would lead in writing the whole document to disk. + + uno::Reference< embed::XStorage > xParentStorage = getParentStorage(); + if ( xParentStorage.is() ) + { + OSL_ENSURE( m_xWrappedTransObj.is(), "No XTransactedObject interface!" ); + + if ( m_xWrappedTransObj.is() ) + { + m_xWrappedTransObj->commit(); + + if ( !isParentARootStorage() ) + { + uno::Reference< embed::XTransactedObject > xParentTA( + xParentStorage, uno::UNO_QUERY ); + OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" ); + + if ( xParentTA.is() ) + xParentTA->commit(); + } + } + } +} + +//========================================================================= +// virtual +void SAL_CALL Storage::revert() + throw ( io::IOException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< embed::XStorage > xParentStorage = getParentStorage(); + if ( xParentStorage.is() ) + { + OSL_ENSURE( m_xWrappedTransObj.is(), "No XTransactedObject interface!" ); + + if ( m_xWrappedTransObj.is() ) + { + m_xWrappedTransObj->revert(); + + if ( !isParentARootStorage() ) + { + uno::Reference< embed::XTransactedObject > xParentTA( + xParentStorage, uno::UNO_QUERY ); + OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" ); + + if ( xParentTA.is() ) + xParentTA->revert(); + } + } + } +} + +//========================================================================= +//========================================================================= +// +// OutputStream Implementation. +// +//========================================================================= +//========================================================================= + +OutputStream::OutputStream( + const uno::Reference< lang::XMultiServiceFactory > & xSMgr, + const rtl::OUString & rUri, + const uno::Reference< embed::XStorage > & xParentStorage, + const uno::Reference< io::XOutputStream > & xStreamToWrap ) +: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ), + m_xWrappedStream( xStreamToWrap ), + m_xWrappedComponent( xStreamToWrap, uno::UNO_QUERY ), + m_xWrappedTypeProv( xStreamToWrap, uno::UNO_QUERY ) +{ + OSL_ENSURE( m_xWrappedStream.is(), + "OutputStream::OutputStream: No stream to wrap!" ); + + OSL_ENSURE( m_xWrappedComponent.is(), + "OutputStream::OutputStream: No component to wrap!" ); + + OSL_ENSURE( m_xWrappedTypeProv.is(), + "OutputStream::OutputStream: No Type Provider!" ); + + // Use proxy factory service to create aggregatable proxy. + try + { + uno::Reference< reflection::XProxyFactory > xProxyFac( + xSMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.reflection.ProxyFactory" ) ) ), + uno::UNO_QUERY ); + if ( xProxyFac.is() ) + { + m_xAggProxy = xProxyFac->createProxy( m_xWrappedStream ); + } + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( false, "OutputStream::OutputStream: Caught exception!" ); + } + + OSL_ENSURE( m_xAggProxy.is(), + "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" ); + + if ( m_xAggProxy.is() ) + { + osl_incrementInterlockedCount( &m_refCount ); + { + // Solaris compiler problem: + // Extra block to enforce destruction of temporary object created + // in next statement _before_ osl_decrementInterlockedCount is + // called. Otherwise 'this' will destroy itself even before ctor + // is completed (See impl. of XInterface::release())! + + m_xAggProxy->setDelegator( + static_cast< cppu::OWeakObject * >( this ) ); + } + osl_decrementInterlockedCount( &m_refCount ); + } +} + +//========================================================================= +// virtual +OutputStream::~OutputStream() +{ + if ( m_xAggProxy.is() ) + m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() ); +} + +//========================================================================= +// +// uno::XInterface +// +//========================================================================= + +// virtual +uno::Any SAL_CALL OutputStream::queryInterface( const uno::Type& aType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet = OutputStreamUNOBase::queryInterface( aType ); + + if ( aRet.hasValue() ) + return aRet; + + if ( m_xAggProxy.is() ) + return m_xAggProxy->queryAggregation( aType ); + else + return uno::Any(); +} + +//========================================================================= +// +// lang::XTypeProvider +// +//========================================================================= + +// virtual +uno::Sequence< uno::Type > SAL_CALL OutputStream::getTypes() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getTypes(); +} + +//========================================================================= +// virtual +uno::Sequence< sal_Int8 > SAL_CALL OutputStream::getImplementationId() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getImplementationId(); +} + +//========================================================================= +// +// io::XOutputStream +// +//========================================================================= + +// virtual +void SAL_CALL +OutputStream::writeBytes( const uno::Sequence< sal_Int8 >& aData ) + throw ( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + m_xWrappedStream->writeBytes( aData ); +} + +//========================================================================= +// virtual +void SAL_CALL +OutputStream::flush() + throw ( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + m_xWrappedStream->flush(); +} + +//========================================================================= +// virtual +void SAL_CALL +OutputStream::closeOutput( ) + throw ( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + m_xWrappedStream->closeOutput(); + + // Release parent storage. + // Now, that the stream is closed/disposed it is not needed any longer. + setParentStorage( uno::Reference< embed::XStorage >() ); +} + +//========================================================================= +// +// lang::XComponent +// +//========================================================================= + +// virtual +void SAL_CALL +OutputStream::dispose() + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->dispose(); + + // Release parent storage. + // Now, that the stream is closed/disposed it is not needed any longer. + setParentStorage( uno::Reference< embed::XStorage >() ); +} + +//========================================================================= +// virtual +void SAL_CALL +OutputStream::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->addEventListener( xListener ); +} + +//========================================================================= +// virtual +void SAL_CALL +OutputStream::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->removeEventListener( aListener ); +} + +//========================================================================= +//========================================================================= +// +// Stream Implementation. +// +//========================================================================= +//========================================================================= + +Stream::Stream( + const uno::Reference< lang::XMultiServiceFactory > & xSMgr, + const rtl::OUString & rUri, + const uno::Reference< embed::XStorage > & xParentStorage, + const uno::Reference< io::XStream > & xStreamToWrap ) +: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ), + m_xWrappedStream( xStreamToWrap ), + m_xWrappedOutputStream( xStreamToWrap->getOutputStream() ), // might be empty + m_xWrappedTruncate( m_xWrappedOutputStream, uno::UNO_QUERY ), // might be empty + m_xWrappedInputStream( xStreamToWrap->getInputStream(), uno::UNO_QUERY ), + m_xWrappedComponent( xStreamToWrap, uno::UNO_QUERY ), + m_xWrappedTypeProv( xStreamToWrap, uno::UNO_QUERY ) +{ + OSL_ENSURE( m_xWrappedStream.is(), + "OutputStream::OutputStream: No stream to wrap!" ); + + OSL_ENSURE( m_xWrappedComponent.is(), + "OutputStream::OutputStream: No component to wrap!" ); + + OSL_ENSURE( m_xWrappedTypeProv.is(), + "OutputStream::OutputStream: No Type Provider!" ); + + // Use proxy factory service to create aggregatable proxy. + try + { + uno::Reference< reflection::XProxyFactory > xProxyFac( + xSMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.reflection.ProxyFactory" ) ) ), + uno::UNO_QUERY ); + if ( xProxyFac.is() ) + { + m_xAggProxy = xProxyFac->createProxy( m_xWrappedStream ); + } + } + catch ( uno::Exception const & ) + { + OSL_ENSURE( false, "OutputStream::OutputStream: Caught exception!" ); + } + + OSL_ENSURE( m_xAggProxy.is(), + "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" ); + + if ( m_xAggProxy.is() ) + { + osl_incrementInterlockedCount( &m_refCount ); + { + // Solaris compiler problem: + // Extra block to enforce destruction of temporary object created + // in next statement _before_ osl_decrementInterlockedCount is + // called. Otherwise 'this' will destroy itself even before ctor + // is completed (See impl. of XInterface::release())! + + m_xAggProxy->setDelegator( + static_cast< cppu::OWeakObject * >( this ) ); + } + osl_decrementInterlockedCount( &m_refCount ); + } +} + +//========================================================================= +// virtual +Stream::~Stream() +{ + if ( m_xAggProxy.is() ) + m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() ); +} + +//========================================================================= +// +// uno::XInterface +// +//========================================================================= + +// virtual +uno::Any SAL_CALL Stream::queryInterface( const uno::Type& aType ) + throw ( uno::RuntimeException ) +{ + uno::Any aRet = StreamUNOBase::queryInterface( aType ); + + if ( aRet.hasValue() ) + return aRet; + + if ( m_xAggProxy.is() ) + return m_xAggProxy->queryAggregation( aType ); + else + return uno::Any(); +} + +//========================================================================= +// +// lang::XTypeProvider +// +//========================================================================= + +// virtual +uno::Sequence< uno::Type > SAL_CALL Stream::getTypes() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getTypes(); +} + +//========================================================================= +// virtual +uno::Sequence< sal_Int8 > SAL_CALL Stream::getImplementationId() + throw ( uno::RuntimeException ) +{ + return m_xWrappedTypeProv->getImplementationId(); +} + +//========================================================================= +// +// io::XStream. +// +//========================================================================= + +// virtual +uno::Reference< io::XInputStream > SAL_CALL Stream::getInputStream() + throw( uno::RuntimeException ) +{ + return uno::Reference< io::XInputStream >( this ); +} + +//========================================================================= +// virtual +uno::Reference< io::XOutputStream > SAL_CALL Stream::getOutputStream() + throw( uno::RuntimeException ) +{ + return uno::Reference< io::XOutputStream >( this ); +} + +//========================================================================= +// +// io::XOutputStream. +// +//========================================================================= + +// virtual +void SAL_CALL Stream::writeBytes( const uno::Sequence< sal_Int8 >& aData ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + if ( m_xWrappedOutputStream.is() ) + { + m_xWrappedOutputStream->writeBytes( aData ); + commitChanges(); + } +} + +//========================================================================= +// virtual +void SAL_CALL Stream::flush() + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + if ( m_xWrappedOutputStream.is() ) + { + m_xWrappedOutputStream->flush(); + commitChanges(); + } +} + +//========================================================================= +// virtual +void SAL_CALL Stream::closeOutput() + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + if ( m_xWrappedOutputStream.is() ) + { + m_xWrappedOutputStream->closeOutput(); + commitChanges(); + } + + // Release parent storage. + // Now, that the stream is closed/disposed it is not needed any longer. + setParentStorage( uno::Reference< embed::XStorage >() ); +} + +//========================================================================= +// +// io::XTruncate. +// +//========================================================================= + +// virtual +void SAL_CALL Stream::truncate() + throw( io::IOException, + uno::RuntimeException ) +{ + if ( m_xWrappedTruncate.is() ) + { + m_xWrappedTruncate->truncate(); + commitChanges(); + } +} + +//========================================================================= +// +// io::XInputStream. +// +//========================================================================= + +// virtual +sal_Int32 SAL_CALL Stream::readBytes( uno::Sequence< sal_Int8 >& aData, + sal_Int32 nBytesToRead ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + return m_xWrappedInputStream->readBytes( aData, nBytesToRead ); +} + +//========================================================================= +// virtual +sal_Int32 SAL_CALL Stream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + return m_xWrappedInputStream->readSomeBytes( aData, nMaxBytesToRead ); +} + +//========================================================================= +// virtual +void SAL_CALL Stream::skipBytes( sal_Int32 nBytesToSkip ) + throw( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + m_xWrappedInputStream->skipBytes( nBytesToSkip ); +} + +//========================================================================= +// virtual +sal_Int32 SAL_CALL Stream::available() + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + return m_xWrappedInputStream->available(); +} + +//========================================================================= +// virtual +void SAL_CALL Stream::closeInput() + throw( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + m_xWrappedInputStream->closeInput(); +} + +//========================================================================= +// +// lang::XComponent +// +//========================================================================= + +// virtual +void SAL_CALL Stream::dispose() + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->dispose(); + + // Release parent storage. + // Now, that the stream is closed/disposed it is not needed any longer. + setParentStorage( uno::Reference< embed::XStorage >() ); +} + +//========================================================================= +// virtual +void SAL_CALL Stream::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->addEventListener( xListener ); +} + +//========================================================================= +// virtual +void SAL_CALL Stream::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) + throw ( uno::RuntimeException ) +{ + m_xWrappedComponent->removeEventListener( aListener ); +} + +//========================================================================= +// +// Non-UNO +// +//========================================================================= + +void Stream::commitChanges() + throw( io::IOException ) +{ + uno::Reference< embed::XTransactedObject > + xParentTA( getParentStorage(), uno::UNO_QUERY ); + OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" ); + + if ( xParentTA.is() ) + { + try + { + xParentTA->commit(); + } + catch ( lang::WrappedTargetException const & ) + { + throw io::IOException(); // @@@ + } + } +} + diff --git a/ucb/source/ucp/tdoc/tdoc_stgelems.hxx b/ucb/source/ucp/tdoc/tdoc_stgelems.hxx new file mode 100644 index 000000000000..7be8b3f1a878 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_stgelems.hxx @@ -0,0 +1,545 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_stgelems.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_TDOC_STGELEMS_HXX +#define INCLUDED_TDOC_STGELEMS_HXX + +#include <memory> + +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" + +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implbase5.hxx" + +#include "com/sun/star/embed/XStorage.hpp" +#include "com/sun/star/embed/XTransactedObject.hpp" +#include "com/sun/star/io/XOutputStream.hpp" +#include "com/sun/star/io/XStream.hpp" +#include "com/sun/star/io/XTruncate.hpp" +#include "com/sun/star/lang/XComponent.hpp" + +#include "tdoc_storage.hxx" + +namespace tdoc_ucp { + +struct MutexHolder +{ + osl::Mutex m_aMutex; +}; + +//======================================================================= + +class ParentStorageHolder : public MutexHolder +{ +public: + ParentStorageHolder( + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const rtl::OUString & rUri ); + + bool isParentARootStorage() const + { return m_bParentIsRootStorage; } + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + getParentStorage() const + { return m_xParentStorage; } + void setParentStorage( const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xStg ) + { osl::MutexGuard aGuard( m_aMutex ); m_xParentStorage = xStg; } + +private: + com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > m_xParentStorage; + bool m_bParentIsRootStorage; +}; + +//======================================================================= + +typedef + cppu::WeakImplHelper2< + com::sun::star::embed::XStorage, + com::sun::star::embed::XTransactedObject > StorageUNOBase; + +class Storage : public StorageUNOBase, public ParentStorageHolder +{ +public: + Storage( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr, + const rtl::Reference< StorageElementFactory > & xFactory, + const rtl::OUString & rUri, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xStorageToWrap ); + virtual ~Storage(); + + bool isDocumentStorage() const { return m_bIsDocumentStorage; } + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL queryInterface( + const com::sun::star::uno::Type& aType ) + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL acquire() + throw (); + virtual void SAL_CALL release() + throw (); + + // XTypeProvider (implemnented by base, but needs to be overridden for + // delegating to aggregate) + virtual com::sun::star::uno::Sequence< com::sun::star::uno::Type > SAL_CALL + getTypes() + throw ( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getImplementationId() + throw ( com::sun::star::uno::RuntimeException ); + + // XComponent ( one of XStorage bases ) + virtual void SAL_CALL + dispose() + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener > & xListener ) + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& aListener ) + throw ( com::sun::star::uno::RuntimeException ); + + // XNameAccess ( one of XStorage bases ) + virtual com::sun::star::uno::Any SAL_CALL + getByName( const rtl::OUString& aName ) + throw ( com::sun::star::container::NoSuchElementException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getElementNames() + throw ( com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasByName( const rtl::OUString& aName ) + throw ( com::sun::star::uno::RuntimeException ); + + // XElementAccess (base of XNameAccess) + virtual com::sun::star::uno::Type SAL_CALL + getElementType() + throw ( com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + hasElements() + throw ( com::sun::star::uno::RuntimeException ); + + // XStorage + virtual void SAL_CALL + copyToStorage( const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage >& xDest ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::io::XStream > SAL_CALL + openStreamElement( const ::rtl::OUString& aStreamName, + sal_Int32 nOpenMode ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::io::XStream > SAL_CALL + openEncryptedStreamElement( const ::rtl::OUString& aStreamName, + sal_Int32 nOpenMode, + const ::rtl::OUString& aPassword ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::packages::NoEncryptionException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::embed::XStorage > SAL_CALL + openStorageElement( const ::rtl::OUString& aStorName, + sal_Int32 nOpenMode ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::io::XStream > SAL_CALL + cloneStreamElement( const ::rtl::OUString& aStreamName ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Reference< com::sun::star::io::XStream > SAL_CALL + cloneEncryptedStreamElement( const ::rtl::OUString& aStreamName, + const ::rtl::OUString& aPassword ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::packages::NoEncryptionException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + copyLastCommitTo( const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage >& xTargetStorage ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + copyStorageElementLastCommitTo( const ::rtl::OUString& aStorName, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & + xTargetStorage ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isStreamElement( const ::rtl::OUString& aElementName ) + throw ( com::sun::star::container::NoSuchElementException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::embed::InvalidStorageException, + com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL + isStorageElement( const ::rtl::OUString& aElementName ) + throw ( com::sun::star::container::NoSuchElementException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::embed::InvalidStorageException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeElement( const ::rtl::OUString& aElementName ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + renameElement( const ::rtl::OUString& aEleName, + const ::rtl::OUString& aNewName ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::container::ElementExistException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + copyElementTo( const ::rtl::OUString& aElementName, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage >& xDest, + const ::rtl::OUString& aNewName ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::container::ElementExistException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + moveElementTo( const ::rtl::OUString& aElementName, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage >& xDest, + const ::rtl::OUString& rNewName ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::container::ElementExistException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + + // XTransactedObject + virtual void SAL_CALL commit() + throw ( com::sun::star::io::IOException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL revert() + throw ( com::sun::star::io::IOException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException ); + +private: + Storage( const rtl::Reference< Storage > & rFactory ); // n.i. + + rtl::Reference< StorageElementFactory > m_xFactory; + com::sun::star::uno::Reference< + com::sun::star::uno::XAggregation > m_xAggProxy; + com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > m_xWrappedStorage; + com::sun::star::uno::Reference< + com::sun::star::embed::XTransactedObject > m_xWrappedTransObj; + com::sun::star::uno::Reference< + com::sun::star::lang::XComponent > m_xWrappedComponent; + com::sun::star::uno::Reference< + com::sun::star::lang::XTypeProvider > m_xWrappedTypeProv; + bool m_bIsDocumentStorage; + + StorageElementFactory::StorageMap::iterator m_aContainerIt; + + friend class StorageElementFactory; + friend class std::auto_ptr< Storage >; +}; + +//======================================================================= + +typedef + cppu::WeakImplHelper2< + com::sun::star::io::XOutputStream, + com::sun::star::lang::XComponent > OutputStreamUNOBase; + +class OutputStream : public OutputStreamUNOBase, public ParentStorageHolder +{ +public: + OutputStream( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr, + const rtl::OUString & rUri, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & xStreamToWrap ); + virtual ~OutputStream(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( const com::sun::star::uno::Type& aType ) + throw ( com::sun::star::uno::RuntimeException ); + + // XTypeProvider (implemnented by base, but needs to be overridden for + // delegating to aggregate) + virtual com::sun::star::uno::Sequence< com::sun::star::uno::Type > SAL_CALL + getTypes() + throw ( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getImplementationId() + throw ( com::sun::star::uno::RuntimeException ); + + // XOutputStream + virtual void SAL_CALL + writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) + throw ( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + flush( ) + throw ( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + // Note: We need to intercept this one. + virtual void SAL_CALL + closeOutput( ) + throw ( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + // XComponent + // Note: We need to intercept this one. + virtual void SAL_CALL + dispose() + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& xListener ) + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& aListener ) + throw ( com::sun::star::uno::RuntimeException ); + +private: + com::sun::star::uno::Reference< + com::sun::star::uno::XAggregation > m_xAggProxy; + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > m_xWrappedStream; + com::sun::star::uno::Reference< + com::sun::star::lang::XComponent > m_xWrappedComponent; + com::sun::star::uno::Reference< + com::sun::star::lang::XTypeProvider > m_xWrappedTypeProv; +}; + +//======================================================================= + +typedef cppu::WeakImplHelper5< com::sun::star::io::XStream, + com::sun::star::io::XOutputStream, + com::sun::star::io::XTruncate, + com::sun::star::io::XInputStream, + com::sun::star::lang::XComponent > + StreamUNOBase; + +class Stream : public StreamUNOBase, public ParentStorageHolder +{ +public: + Stream( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr, + const rtl::OUString & rUri, + const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const com::sun::star::uno::Reference< + com::sun::star::io::XStream > & xStreamToWrap ); + + virtual ~Stream(); + + // XInterface + virtual com::sun::star::uno::Any SAL_CALL + queryInterface( const com::sun::star::uno::Type& aType ) + throw ( com::sun::star::uno::RuntimeException ); + + // XTypeProvider (implemnented by base, but needs to be overridden for + // delegating to aggregate) + virtual com::sun::star::uno::Sequence< com::sun::star::uno::Type > SAL_CALL + getTypes() + throw ( com::sun::star::uno::RuntimeException ); + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getImplementationId() + throw ( com::sun::star::uno::RuntimeException ); + + // XStream + virtual com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > SAL_CALL + getInputStream() + throw( com::sun::star::uno::RuntimeException ); + + virtual com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > SAL_CALL + getOutputStream() + throw( com::sun::star::uno::RuntimeException ); + + // XOutputStream + virtual void SAL_CALL + writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + flush() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + closeOutput() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + // XTruncate + virtual void SAL_CALL + truncate() + throw( com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + // XInputStream + virtual sal_Int32 SAL_CALL + readBytes( com::sun::star::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nBytesToRead ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL + readSomeBytes( com::sun::star::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + skipBytes( sal_Int32 nBytesToSkip ) + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::BufferSizeExceededException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual sal_Int32 SAL_CALL + available() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL + closeInput() + throw( com::sun::star::io::NotConnectedException, + com::sun::star::io::IOException, + com::sun::star::uno::RuntimeException ); + + // XComponent + // Note: We need to intercept this one. + virtual void SAL_CALL + dispose() + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + addEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& xListener ) + throw ( com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + removeEventListener( const com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener >& aListener ) + throw ( com::sun::star::uno::RuntimeException ); + +private: + void commitChanges() + throw( com::sun::star::io::IOException ); + + com::sun::star::uno::Reference< + com::sun::star::uno::XAggregation > m_xAggProxy; + com::sun::star::uno::Reference< + com::sun::star::io::XStream > m_xWrappedStream; + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > m_xWrappedOutputStream; + com::sun::star::uno::Reference< + com::sun::star::io::XTruncate > m_xWrappedTruncate; + com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > m_xWrappedInputStream; + com::sun::star::uno::Reference< + com::sun::star::lang::XComponent > m_xWrappedComponent; + com::sun::star::uno::Reference< + com::sun::star::lang::XTypeProvider > m_xWrappedTypeProv; +}; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_STGELEMS_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_storage.cxx b/ucb/source/ucp/tdoc/tdoc_storage.cxx new file mode 100644 index 000000000000..689fe80124da --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_storage.cxx @@ -0,0 +1,715 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_storage.cxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - remove root storage access workaround + + *************************************************************************/ + +#define ROOTSTORAGE_ACCESS_WORKAROUND 1 + +#include <memory> + +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/embed/ElementModes.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" + +#include "tdoc_uri.hxx" +#include "tdoc_docmgr.hxx" +#include "tdoc_stgelems.hxx" + +#include "tdoc_storage.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + + +//========================================================================= +//========================================================================= +// +// StorageElementFactory Implementation. +// +//========================================================================= +//========================================================================= + +StorageElementFactory::StorageElementFactory( + const uno::Reference< lang::XMultiServiceFactory > & xSMgr, + const rtl::Reference< OfficeDocumentsManager > & xDocsMgr ) +: m_xDocsMgr( xDocsMgr ), + m_xSMgr( xSMgr ) +{ +} + +//========================================================================= +StorageElementFactory::~StorageElementFactory() +{ + OSL_ENSURE( m_aMap.size() == 0, + "StorageElementFactory::~StorageElementFactory - Dangling storages!" ); +} + +//========================================================================= +uno::Reference< embed::XStorage > +StorageElementFactory::createTemporaryStorage() + throw ( uno::Exception, + uno::RuntimeException ) +{ + uno::Reference< embed::XStorage > xStorage; + uno::Reference< lang::XSingleServiceFactory > xStorageFac; + if ( m_xSMgr.is() ) + { + xStorageFac = uno::Reference< lang::XSingleServiceFactory >( + m_xSMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.embed.StorageFactory" ) ) ), + uno::UNO_QUERY ); + } + + OSL_ENSURE( xStorageFac.is(), "Can't create storage factory!" ); + if ( xStorageFac.is() ) + xStorage = uno::Reference< embed::XStorage >( + xStorageFac->createInstance(), + uno::UNO_QUERY ); + + if ( !xStorage.is() ) + throw uno::RuntimeException(); + + return xStorage; +} + +//========================================================================= +uno::Reference< embed::XStorage > +StorageElementFactory::createStorage( const rtl::OUString & rUri, + StorageAccessMode eMode ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( ( eMode != READ ) && + ( eMode != READ_WRITE_NOCREATE ) && + ( eMode != READ_WRITE_CREATE ) ) + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Invalid open mode!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 2 ) ); + + Uri aUri( rUri ); + if ( aUri.isRoot() ) + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Root never has a storage!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 1 ) ); + } + + rtl::OUString aUriKey + ( ( rUri.getStr()[ rUri.getLength() - 1 ] == sal_Unicode( '/' ) ) + ? rUri.copy( 0, rUri.getLength() - 1 ) + : rUri ); + + StorageMap::iterator aIt ( m_aMap.begin() ); + StorageMap::iterator aEnd( m_aMap.end() ); + + while ( aIt != aEnd ) + { + if ( (*aIt).first.first == aUriKey ) + { + // URI matches. Now, check open mode. + bool bMatch = true; + switch ( eMode ) + { + case READ: + // No need to check; storage is at least readable. + bMatch = true; + break; + + case READ_WRITE_NOCREATE: + case READ_WRITE_CREATE: + // If found storage is writable, it can be used. + // If not, a new one must be created. + bMatch = (*aIt).first.second; + break; + } + + if ( bMatch ) + break; + } + ++aIt; + } + + if ( aIt == aEnd ) + { + uno::Reference< embed::XStorage > xParentStorage; + + // documents never have a parent storage. + if ( !aUri.isDocument() ) + { + xParentStorage = queryParentStorage( aUriKey, eMode ); + + if ( !xParentStorage.is() ) + { + // requested to create new storage, but failed? + OSL_ENSURE( eMode != READ_WRITE_CREATE, + "Unable to create parent storage!" ); + return xParentStorage; + } + } + + uno::Reference< embed::XStorage > xStorage + = queryStorage( xParentStorage, aUriKey, eMode ); + + if ( !xStorage.is() ) + { + // requested to create new storage, but failed? + OSL_ENSURE( eMode != READ_WRITE_CREATE, + "Unable to create storage!" ); + return xStorage; + } + + bool bWritable = ( ( eMode == READ_WRITE_NOCREATE ) + || ( eMode == READ_WRITE_CREATE ) ); + + std::auto_ptr< Storage > xElement( + new Storage( m_xSMgr, this, aUriKey, xParentStorage, xStorage ) ); + + aIt = m_aMap.insert( + StorageMap::value_type( + std::pair< rtl::OUString, bool >( aUriKey, bWritable ), + xElement.get() ) ).first; + + aIt->second->m_aContainerIt = aIt; + xElement.release(); + return aIt->second; + } + else if ( osl_incrementInterlockedCount( &aIt->second->m_refCount ) > 1 ) + { + rtl::Reference< Storage > xElement( aIt->second ); + osl_decrementInterlockedCount( &aIt->second->m_refCount ); + return aIt->second; + } + else + { + osl_decrementInterlockedCount( &aIt->second->m_refCount ); + aIt->second->m_aContainerIt = m_aMap.end(); + + uno::Reference< embed::XStorage > xParentStorage; + + // documents never have a parent storage. + if ( !aUri.isDocument() ) + { + xParentStorage = queryParentStorage( aUriKey, eMode ); + + if ( !xParentStorage.is() ) + { + // requested to create new storage, but failed? + OSL_ENSURE( eMode != READ_WRITE_CREATE, + "Unable to create parent storage!" ); + return xParentStorage; + } + } + + uno::Reference< embed::XStorage > xStorage + = queryStorage( xParentStorage, aUriKey, eMode ); + + if ( !xStorage.is() ) + { + // requested to create new storage, but failed? + OSL_ENSURE( eMode != READ_WRITE_CREATE, + "Unable to create storage!" ); + return xStorage; + } + + aIt->second + = new Storage( m_xSMgr, this, aUriKey, xParentStorage, xStorage ); + aIt->second->m_aContainerIt = aIt; + return aIt->second; + } +} + +//========================================================================= +uno::Reference< io::XInputStream > +StorageElementFactory::createInputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + packages::WrongPasswordException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + uno::Reference< embed::XStorage > xParentStorage + = queryParentStorage( rUri, READ ); + + // Each stream must have a parent storage. + if ( !xParentStorage.is() ) + return uno::Reference< io::XInputStream >(); + + uno::Reference< io::XStream > xStream + = queryStream( xParentStorage, rUri, rPassword, READ, false ); + + if ( !xStream.is() ) + return uno::Reference< io::XInputStream >(); + + return xStream->getInputStream(); +} + +//========================================================================= +uno::Reference< io::XOutputStream > +StorageElementFactory::createOutputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + packages::WrongPasswordException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + uno::Reference< embed::XStorage > xParentStorage + = queryParentStorage( rUri, READ_WRITE_CREATE ); + + // Each stream must have a parent storage. + if ( !xParentStorage.is() ) + { + OSL_ENSURE( false, + "StorageElementFactory::createOutputStream - " + "Unable to create parent storage!" ); + return uno::Reference< io::XOutputStream >(); + } + + uno::Reference< io::XStream > xStream + = queryStream( + xParentStorage, rUri, rPassword, READ_WRITE_CREATE, bTruncate ); + + if ( !xStream.is() ) + { + OSL_ENSURE( false, + "StorageElementFactory::createOutputStream - " + "Unable to create stream!" ); + return uno::Reference< io::XOutputStream >(); + } + + // Note: We need a wrapper to hold a reference to the parent storage to + // ensure that nobody else owns it at the moment we want to commit + // our changes. (There can be only one writable instance at a time + // and even no writable instance if there is already another + // read-only instance!) + return uno::Reference< io::XOutputStream >( + new OutputStream( + m_xSMgr, rUri, xParentStorage, xStream->getOutputStream() ) ); +} + +//========================================================================= +uno::Reference< io::XStream > +StorageElementFactory::createStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + packages::WrongPasswordException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + uno::Reference< embed::XStorage > xParentStorage + = queryParentStorage( rUri, READ_WRITE_CREATE ); + + // Each stream must have a parent storage. + if ( !xParentStorage.is() ) + { + OSL_ENSURE( false, + "StorageElementFactory::createStream - " + "Unable to create parent storage!" ); + return uno::Reference< io::XStream >(); + } + + uno::Reference< io::XStream > xStream + = queryStream( + xParentStorage, rUri, rPassword, READ_WRITE_NOCREATE, bTruncate ); + + if ( !xStream.is() ) + { + OSL_ENSURE( false, + "StorageElementFactory::createStream - " + "Unable to create stream!" ); + return uno::Reference< io::XStream >(); + } + + return uno::Reference< io::XStream >( + new Stream( m_xSMgr, rUri, xParentStorage, xStream ) ); +} + +//========================================================================= +void StorageElementFactory::releaseElement( Storage * pElement ) SAL_THROW( () ) +{ + OSL_ASSERT( pElement ); + osl::MutexGuard aGuard( m_aMutex ); + if ( pElement->m_aContainerIt != m_aMap.end() ) + m_aMap.erase( pElement->m_aContainerIt ); +} + +//========================================================================= +// +// Non-UNO interface +// +//========================================================================= + +uno::Reference< embed::XStorage > StorageElementFactory::queryParentStorage( + const rtl::OUString & rUri, StorageAccessMode eMode ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< embed::XStorage > xParentStorage; + + Uri aUri( rUri ); + Uri aParentUri( aUri.getParentUri() ); + if ( !aParentUri.isRoot() ) + { + xParentStorage = createStorage( aUri.getParentUri(), eMode ); + OSL_ENSURE( xParentStorage.is() + // requested to create new storage, but failed? + || ( eMode != READ_WRITE_CREATE ), + "StorageElementFactory::queryParentStorage - No storage!" ); + } + return xParentStorage; +} + +//========================================================================= +uno::Reference< embed::XStorage > StorageElementFactory::queryStorage( + const uno::Reference< embed::XStorage > & xParentStorage, + const rtl::OUString & rUri, + StorageAccessMode eMode ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< embed::XStorage > xStorage; + + Uri aUri( rUri ); + + if ( !xParentStorage.is() ) + { + // document storage + + xStorage = m_xDocsMgr->queryStorage( aUri.getDocumentId() ); + + if ( !xStorage.is() ) + { + if ( eMode == READ_WRITE_CREATE ) + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Invalid open mode: document storages cannot be " + "created!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 2 ) ); + else + throw embed::InvalidStorageException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Invalid document id!" ) ), + uno::Reference< uno::XInterface >() ); + } + + // match xStorage's open mode against requested open mode + + uno::Reference< beans::XPropertySet > xPropSet( + xStorage, uno::UNO_QUERY ); + OSL_ENSURE( xPropSet.is(), + "StorageElementFactory::queryStorage - " + "No XPropertySet interface!" ); + try + { + uno::Any aPropValue = xPropSet->getPropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ) ) ); + + sal_Int32 nOpenMode = 0; + if ( aPropValue >>= nOpenMode ) + { + switch ( eMode ) + { + case READ: + if ( !( nOpenMode & embed::ElementModes::READ ) ) + { + // document opened, but not readable. + throw embed::InvalidStorageException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Storage is open, but not readable!" ) ), + uno::Reference< uno::XInterface >() ); + } + // storage okay + break; + + case READ_WRITE_NOCREATE: + case READ_WRITE_CREATE: + if ( !( nOpenMode & embed::ElementModes::WRITE ) ) + { + // document opened, but not writable. + throw embed::InvalidStorageException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Storage is open, but not writable!" ) ), + uno::Reference< uno::XInterface >() ); + } + // storage okay + break; + } + } + else + { + OSL_ENSURE( + false, "Bug! Value of property OpenMode has wrong type!" ); + + throw uno::RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Bug! Value of property OpenMode has wrong type!" ) ), + uno::Reference< uno::XInterface >() ); + } + } + catch ( beans::UnknownPropertyException const & e ) + { + OSL_ENSURE( false, "Property OpenMode not supported!" ); + + throw embed::StorageWrappedTargetException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Bug! Value of property OpenMode has wrong type!" ) ), + uno::Reference< uno::XInterface >(), + uno::makeAny( e ) ); + } + catch ( lang::WrappedTargetException const & e ) + { + OSL_ENSURE( false, "Caught WrappedTargetException!" ); + + throw embed::StorageWrappedTargetException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "WrappedTargetException during getPropertyValue!" ) ), + uno::Reference< uno::XInterface >(), + uno::makeAny( e ) ); + } + } + else + { + // sub storage + + const rtl::OUString & rName = aUri.getDecodedName(); + + if ( eMode == READ ) + { + try + { + sal_Int32 nOpenMode = embed::ElementModes::READ + | embed::ElementModes::NOCREATE; + xStorage + = xParentStorage->openStorageElement( rName, nOpenMode ); + } + catch ( io::IOException const & ) + { + // Another chance: Try to clone storage. + xStorage = createTemporaryStorage(); + xParentStorage->copyStorageElementLastCommitTo( rName, + xStorage ); + } + } + else + { + sal_Int32 nOpenMode = embed::ElementModes::READWRITE; + if ( eMode == READ_WRITE_NOCREATE ) + nOpenMode |= embed::ElementModes::NOCREATE; + + xStorage = xParentStorage->openStorageElement( rName, nOpenMode ); + } + } + + OSL_ENSURE( xStorage.is() || ( eMode != READ_WRITE_CREATE ), + "StorageElementFactory::queryStorage - No storage!" ); + return xStorage; +} + +//========================================================================= +uno::Reference< io::XStream > +StorageElementFactory::queryStream( + const uno::Reference< embed::XStorage > & xParentStorage, + const rtl::OUString & rUri, + const rtl::OUString & rPassword, + StorageAccessMode eMode, + bool bTruncate ) + throw ( embed::InvalidStorageException, + lang::IllegalArgumentException, + io::IOException, + embed::StorageWrappedTargetException, + packages::WrongPasswordException, + uno::RuntimeException ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !xParentStorage.is() ) + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "No parent storage!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 2 ) ); + } + + Uri aUri( rUri ); + if ( aUri.isRoot() ) + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Root never is a stream!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 2 ) ); + } + else if ( aUri.isDocument() ) + { + throw lang::IllegalArgumentException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "A document never is a stream!" ) ), + uno::Reference< uno::XInterface >(), + sal_Int16( 2 ) ); + } + + sal_Int32 nOpenMode; + switch ( eMode ) + { + case READ: + nOpenMode = embed::ElementModes::READ + | embed::ElementModes::NOCREATE + | embed::ElementModes::SEEKABLE; + break; + + case READ_WRITE_NOCREATE: + nOpenMode = embed::ElementModes::READWRITE + | embed::ElementModes::NOCREATE + | embed::ElementModes::SEEKABLE; + + if ( bTruncate ) + nOpenMode |= embed::ElementModes::TRUNCATE; + + break; + + case READ_WRITE_CREATE: + nOpenMode = embed::ElementModes::READWRITE + | embed::ElementModes::SEEKABLE; + + if ( bTruncate ) + nOpenMode |= embed::ElementModes::TRUNCATE; + + break; + + default: + OSL_ENSURE( false, + "StorageElementFactory::queryStream : Unknown open mode!" ); + + throw embed::InvalidStorageException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "Unknown open mode!" ) ), + uno::Reference< uno::XInterface >() ); + } + + // No object re-usage mechanism; streams are seekable => not stateless. + + uno::Reference< io::XStream > xStream; + if ( rPassword.getLength() > 0 ) + { + if ( eMode == READ ) + { + try + { + xStream = xParentStorage->cloneEncryptedStreamElement( + aUri.getDecodedName(), + rPassword ); + } + catch ( packages::NoEncryptionException const & ) + { + xStream + = xParentStorage->cloneStreamElement( aUri.getDecodedName() ); + } + } + else + { + try + { + xStream = xParentStorage->openEncryptedStreamElement( + aUri.getDecodedName(), + nOpenMode, + rPassword ); + } + catch ( packages::NoEncryptionException const & ) + { + xStream + = xParentStorage->openStreamElement( aUri.getDecodedName(), + nOpenMode ); + } + } + } + else + { + if ( eMode == READ ) + { + xStream = xParentStorage->cloneStreamElement( aUri.getDecodedName() ); + } + else + { + xStream = xParentStorage->openStreamElement( aUri.getDecodedName(), + nOpenMode ); + } + } + + if ( !xStream.is() ) + { + throw embed::InvalidStorageException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "No stream!" ) ), + uno::Reference< uno::XInterface >() ); + } + + return xStream; +} diff --git a/ucb/source/ucp/tdoc/tdoc_storage.hxx b/ucb/source/ucp/tdoc/tdoc_storage.hxx new file mode 100644 index 000000000000..612bfba967bd --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_storage.hxx @@ -0,0 +1,175 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_storage.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_TDOC_STORAGE_HXX +#define INCLUDED_TDOC_STORAGE_HXX + +#include <map> + +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "salhelper/simplereferenceobject.hxx" + +#include "com/sun/star/embed/XStorage.hpp" + +namespace tdoc_ucp { + + enum StorageAccessMode + { + READ, // Note: might be writable as well + READ_WRITE_NOCREATE, + READ_WRITE_CREATE + }; + + class Storage; + class OfficeDocumentsManager; + + class StorageElementFactory : public salhelper::SimpleReferenceObject + { + public: + StorageElementFactory( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > & xSMgr, + const rtl::Reference< OfficeDocumentsManager > & xDocsMgr ); + ~StorageElementFactory(); + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + createTemporaryStorage() + throw ( com::sun::star::uno::Exception, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + createStorage( const rtl::OUString & rUri, StorageAccessMode eMode ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + createInputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > + createOutputStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::io::XStream > + createStream( const rtl::OUString & rUri, + const rtl::OUString & rPassword, + bool bTruncate ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::uno::RuntimeException ); + + private: + friend class Storage; + + void releaseElement( Storage * pElement ) SAL_THROW(()); + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + queryParentStorage( const rtl::OUString & rUri, + StorageAccessMode eMode ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::embed::XStorage > + queryStorage( const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const rtl::OUString & rUri, + StorageAccessMode eMode ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::uno::RuntimeException ); + + com::sun::star::uno::Reference< com::sun::star::io::XStream > + queryStream( const com::sun::star::uno::Reference< + com::sun::star::embed::XStorage > & xParentStorage, + const rtl::OUString & rPassword, + const rtl::OUString & rUri, + StorageAccessMode eMode, + bool bTruncate /* ignored for read-only streams */ ) + throw ( com::sun::star::embed::InvalidStorageException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::io::IOException, + com::sun::star::embed::StorageWrappedTargetException, + com::sun::star::packages::WrongPasswordException, + com::sun::star::uno::RuntimeException ); + + struct ltstrbool + { + bool operator()( + const std::pair< rtl::OUString, bool > & s1, + const std::pair< rtl::OUString, bool > & s2 ) const + { + if ( s1.first < s2.first ) + return true; + else if ( s1.first == s2.first ) + return ( !s1.second && s2.second ); + else + return false; + } + }; + + // key: pair< storageuri, iswritable > + typedef std::map< + std::pair< rtl::OUString, bool >, Storage *, ltstrbool > StorageMap; + + StorageMap m_aMap; + osl::Mutex m_aMutex; + rtl::Reference< OfficeDocumentsManager > m_xDocsMgr; + com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + }; + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_STORAGE_HXX */ diff --git a/ucb/source/ucp/tdoc/tdoc_uri.cxx b/ucb/source/ucp/tdoc/tdoc_uri.cxx new file mode 100644 index 000000000000..d829490dec23 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_uri.cxx @@ -0,0 +1,138 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_uri.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include "rtl/ustrbuf.hxx" +#include "../inc/urihelper.hxx" + +#include "tdoc_uri.hxx" + +using namespace tdoc_ucp; + +//========================================================================= +//========================================================================= +// +// Uri Implementation. +// +//========================================================================= +//========================================================================= + +void Uri::init() const +{ + // Already inited? + if ( m_eState == UNKNOWN ) + { + m_eState = INVALID; + + // Check for proper length: must be at least length of <sheme>:/ + if ( ( m_aUri.getLength() < TDOC_URL_SCHEME_LENGTH + 2 ) ) + { + // Invaild length (to short). + return; + } + + // Check for proper scheme. (Scheme is case insensitive.) + rtl::OUString aScheme + = m_aUri.copy( 0, TDOC_URL_SCHEME_LENGTH ).toAsciiLowerCase(); + if ( !aScheme.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( TDOC_URL_SCHEME ) ) ) + { + // Invaild scheme. + return; + } + + // Remember normalized scheme string. + m_aUri = m_aUri.replaceAt( 0, aScheme.getLength(), aScheme ); + + if ( m_aUri.getStr()[ TDOC_URL_SCHEME_LENGTH ] + != sal_Unicode( ':' ) ) + { + // Invaild (no ':' after <scheme>). + return; + } + + if ( m_aUri.getStr()[ TDOC_URL_SCHEME_LENGTH + 1 ] + != sal_Unicode( '/' ) ) + { + // Invaild (no '/' after <scheme>:). + return; + } + + m_aPath = m_aUri.copy( TDOC_URL_SCHEME_LENGTH + 1 ); + + // Note: There must be at least one slash; see above. + sal_Int32 nLastSlash = m_aUri.lastIndexOf( '/' ); + bool bTrailingSlash = false; + if ( nLastSlash == m_aUri.getLength() - 1 ) + { + // ignore trailing slash + bTrailingSlash = true; + nLastSlash = m_aUri.lastIndexOf( '/', nLastSlash ); + } + + if ( nLastSlash != -1 ) // -1 is valid for the root folder + { + m_aParentUri = m_aUri.copy( 0, nLastSlash + 1 ); + + if ( bTrailingSlash ) + m_aName = m_aUri.copy( nLastSlash + 1, + m_aUri.getLength() - nLastSlash - 2 ); + else + m_aName = m_aUri.copy( nLastSlash + 1 ); + + m_aDecodedName = ::ucb_impl::urihelper::decodeSegment( m_aName ); + + sal_Int32 nSlash = m_aPath.indexOf( '/', 1 ); + if ( nSlash == -1 ) + m_aDocId = m_aPath.copy( 1 ); + else + m_aDocId = m_aPath.copy( 1, nSlash - 1 ); + } + + if ( m_aDocId.getLength() > 0 ) + { + sal_Int32 nSlash = m_aPath.indexOf( '/', 1 ); + if ( nSlash != - 1 ) + m_aInternalPath = m_aPath.copy( nSlash ); + else + m_aInternalPath = rtl::OUString::createFromAscii( "/" ); + } + + m_eState = VALID; + } +} diff --git a/ucb/source/ucp/tdoc/tdoc_uri.hxx b/ucb/source/ucp/tdoc/tdoc_uri.hxx new file mode 100644 index 000000000000..26c66d5e8d2f --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_uri.hxx @@ -0,0 +1,134 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tdoc_uri.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_TDOC_URI_HXX +#define INCLUDED_TDOC_URI_HXX + +#include "rtl/ustring.hxx" + +namespace tdoc_ucp { + +//========================================================================= + +#define TDOC_URL_SCHEME "vnd.sun.star.tdoc" +#define TDOC_URL_SCHEME_LENGTH 17 + +//========================================================================= + +class Uri +{ + enum State { UNKNOWN, INVALID, VALID }; + + mutable ::rtl::OUString m_aUri; + mutable ::rtl::OUString m_aParentUri; + mutable ::rtl::OUString m_aPath; + mutable ::rtl::OUString m_aDocId; + mutable ::rtl::OUString m_aInternalPath; + mutable ::rtl::OUString m_aName; + mutable ::rtl::OUString m_aDecodedName; + mutable State m_eState; + +private: + void init() const; + +public: + Uri() : m_eState( UNKNOWN ) {} + Uri( const ::rtl::OUString & rUri ) + : m_aUri( rUri ), m_eState( UNKNOWN ) {} + + bool operator== ( const Uri & rOther ) const + { init(); return m_aUri == rOther.m_aUri; } + + bool operator!= ( const Uri & rOther ) const + { return !operator==( rOther ); } + + sal_Bool isValid() const + { init(); return m_eState == VALID; } + + const ::rtl::OUString & getUri() const + { init(); return m_aUri; } + + inline void setUri( const ::rtl::OUString & rUri ); + + const ::rtl::OUString & getParentUri() const + { init(); return m_aParentUri; } + + const ::rtl::OUString & getPath() const + { init(); return m_aPath; } + + const ::rtl::OUString & getDocumentId() const + { init(); return m_aDocId; } + + const ::rtl::OUString & getInternalPath() const + { init(); return m_aInternalPath; } + + const ::rtl::OUString & getName() const + { init(); return m_aName; } + + const ::rtl::OUString & getDecodedName() const + { init(); return m_aDecodedName; } + + inline sal_Bool isRoot() const; + + inline sal_Bool isDocument() const; + + inline sal_Bool isFolder() const; +}; + +inline void Uri::setUri( const ::rtl::OUString & rUri ) +{ + m_eState = UNKNOWN; + m_aUri = rUri; + m_aParentUri = m_aDocId = m_aInternalPath = m_aPath = m_aName + = m_aDecodedName = rtl::OUString(); +} + +inline sal_Bool Uri::isRoot() const +{ + init(); + return ( m_aPath.getLength() == 1 ); +} + +inline sal_Bool Uri::isDocument() const +{ + init(); + return ( ( m_aDocId.getLength() > 0 ) /* not root */ + && ( m_aPath.copy( m_aDocId.getLength() + 1 ).getLength() < 2 ) ); +} + +inline sal_Bool Uri::isFolder() const +{ + init(); + return ( m_aPath.lastIndexOf( '/' ) == m_aPath.getLength() - 1 ); +} + +} // namespace tdoc_ucp + +#endif /* !INCLUDED_TDOC_URI_HXX */ diff --git a/ucb/source/ucp/tdoc/ucptdoc.xml b/ucb/source/ucp/tdoc/ucptdoc.xml new file mode 100644 index 000000000000..b47249269470 --- /dev/null +++ b/ucb/source/ucp/tdoc/ucptdoc.xml @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + ucptdoc + </module-name> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.TransientDocumentsContentProvider + </name> + <description> + This component implements a Content Provider for the Universal Content Broker. + It provides access to the hierachical structure of the documents that are active + in a running OpenOffice.org process. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.TransientDocumentsContentProvider + </supported-service> + + <service-dependency> + com.sun.star.frame.GlobalEventBroadcaster + </service-dependency> + <service-dependency> + com.sun.star.reflection.ProxyFactory + </service-dependency> + <service-dependency> + com.sun.star.embed.StorageFactory + </service-dependency> + </component-description> + + <component-description> + <author> + Kai Sommerfeld + </author> + <name> + com.sun.star.comp.ucb.TransientDocumentsDocumentContentFactory + </name> + <description> + This component implements a factory for + 'com.sun.star.ucb.TransientDocumentsDocumentContent's. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.frame.TransientDocumentsDocumentContentFactory + </supported-service> + + <service-dependency> + com.sun.star.ucb.TransientDocumentsContentProvider + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> salhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> ucbhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.Property </type> + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.PropertyValue </type> + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.container.XEnumerationAccess </type> + <type> com.sun.star.container.XNameAccess </type> + <type> com.sun.star.document.XStorageBasedDocument </type> + <type> com.sun.star.document.XEventBroadcaster </type> + <type> com.sun.star.document.XEventListener </type> + <type> com.sun.star.embed.ElementModes </type> + <type> com.sun.star.embed.XStorage </type> + <type> com.sun.star.embed.XTransactedObject </type> + <type> com.sun.star.frame.XTransientDocumentsDocumentContentFactory </type> + <type> com.sun.star.io.XActiveDataSink </type> + <type> com.sun.star.io.XActiveDataStreamer </type> + <type> com.sun.star.io.XSeekable </type> + <type> com.sun.star.io.XTruncate </type> + <type> com.sun.star.lang.DisposedException </type> + <type> com.sun.star.lang.IllegalAccessException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.reflection.XProxyFactory </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.task.DocumentPasswordRequest </type> + <type> com.sun.star.task.XInteractionPassword </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.CommandInfo </type> + <type> com.sun.star.ucb.ContentInfoAttribute </type> + <type> com.sun.star.ucb.InsertCommandArgument </type> + <type> com.sun.star.ucb.InteractiveBadTransferURLException </type> + <type> com.sun.star.ucb.MissingInputStreamException </type> + <type> com.sun.star.ucb.MissingPropertiesException </type> + <type> com.sun.star.ucb.NameClash </type> + <type> com.sun.star.ucb.NameClashException </type> + <type> com.sun.star.ucb.OpenCommandArgument2 </type> + <type> com.sun.star.ucb.OpenMode </type> + <type> com.sun.star.ucb.TransferInfo </type> + <type> com.sun.star.ucb.UnsupportedCommandException </type> + <type> com.sun.star.ucb.UnsupportedDataSinkException </type> + <type> com.sun.star.ucb.UnsupportedNameClashException </type> + <type> com.sun.star.ucb.UnsupportedOpenModeException </type> + <type> com.sun.star.ucb.XCommandInfo </type> + <type> com.sun.star.ucb.XContentCreator </type> + <type> com.sun.star.ucb.XPersistentPropertySet </type> + <type> com.sun.star.uno.XAggregation </type> + +</module-description> |