diff options
Diffstat (limited to 'ucb/source/ucp/tdoc/tdoc_stgelems.cxx')
-rw-r--r-- | ucb/source/ucp/tdoc/tdoc_stgelems.cxx | 882 |
1 files changed, 882 insertions, 0 deletions
diff --git a/ucb/source/ucp/tdoc/tdoc_stgelems.cxx b/ucb/source/ucp/tdoc/tdoc_stgelems.cxx new file mode 100644 index 0000000000..dff9bf5909 --- /dev/null +++ b/ucb/source/ucp/tdoc/tdoc_stgelems.cxx @@ -0,0 +1,882 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +/************************************************************************** + TODO + ************************************************************************** + + - remove root storage access workaround + + *************************************************************************/ + +#include <comphelper/diagnose_ex.hxx> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/reflection/ProxyFactory.hpp> +#include <utility> + +#include "tdoc_docmgr.hxx" +#include "tdoc_uri.hxx" + +#include "tdoc_stgelems.hxx" + +using namespace com::sun::star; +using namespace tdoc_ucp; + + +// ParentStorageHolder Implementation. + + +ParentStorageHolder::ParentStorageHolder( + uno::Reference< embed::XStorage > xParentStorage, + const OUString & rUri ) +: m_xParentStorage(std::move( xParentStorage )), + m_bParentIsRootStorage( false ) +{ + Uri aUri( rUri ); + if ( aUri.isDocument() ) + m_bParentIsRootStorage = true; +} + + +// Storage Implementation. + + +Storage::Storage( const uno::Reference< uno::XComponentContext > & rxContext, + rtl::Reference< StorageElementFactory > xFactory, + const OUString & rUri, + const uno::Reference< embed::XStorage > & xParentStorage, + const uno::Reference< embed::XStorage > & xStorageToWrap ) +: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ), + m_xFactory(std::move( xFactory )), + m_xWrappedStorage( xStorageToWrap ), + m_xWrappedTransObj( xStorageToWrap, uno::UNO_QUERY ), // optional interface + m_xWrappedComponent( xStorageToWrap ), + 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 = + reflection::ProxyFactory::create( rxContext ); + m_xAggProxy = xProxyFac->createProxy( m_xWrappedStorage ); + } + catch ( uno::Exception const & ) + { + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + + OSL_ENSURE( m_xAggProxy.is(), + "Storage::Storage: Wrapped storage cannot be aggregated!" ); + + if ( !m_xAggProxy.is() ) + return; + + osl_atomic_increment( &m_refCount ); + { + // Solaris compiler problem: + // Extra block to enforce destruction of temporary object created + // in next statement _before_ osl_atomic_decrement is + // called. Otherwise 'this' will destroy itself even before ctor + // is completed (See impl. of XInterface::release())! + + m_xAggProxy->setDelegator( + getXWeak() ); + } + osl_atomic_decrement( &m_refCount ); +} + + +// virtual +Storage::~Storage() +{ + if ( m_xAggProxy.is() ) + m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() ); + + // Never dispose a document storage. Not owner! + if ( m_bIsDocumentStorage ) + return; + + if ( !m_xWrappedComponent.is() ) + return; + + // "Auto-dispose"... + try + { + m_xWrappedComponent->dispose(); + } + catch ( lang::DisposedException const & ) + { + // might happen. + } + catch ( ... ) + { + TOOLS_WARN_EXCEPTION( "ucb", "Storage::~Storage - Caught exception!" ); + } +} + + +// uno::XInterface + + +// virtual +uno::Any SAL_CALL Storage::queryInterface( const uno::Type& aType ) +{ + // 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() + noexcept +{ + osl_atomic_increment( &m_refCount ); +} + + +// virtual +void SAL_CALL Storage::release() + noexcept +{ + //#i120738, Storage::release overrides OWeakObject::release(), + //need call OWeakObject::release() to release OWeakObject::m_pWeakConnectionPoint + + if ( m_refCount == 1 ) + m_xFactory->releaseElement( this ); + + //delete this; + OWeakObject::release(); +} + + +// lang::XTypeProvider + + +// virtual +uno::Sequence< uno::Type > SAL_CALL Storage::getTypes() +{ + return m_xWrappedTypeProv->getTypes(); +} + + +// virtual +uno::Sequence< sal_Int8 > SAL_CALL Storage::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + + +// lang::XComponent (base of embed::XStorage) + + +// virtual +void SAL_CALL Storage::dispose() +{ + m_xWrappedStorage->dispose(); + m_xWrappedStorage.clear(); +} + + +// virtual +void SAL_CALL Storage::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) +{ + m_xWrappedStorage->addEventListener( xListener ); +} + +// virtual +void SAL_CALL Storage::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) +{ + m_xWrappedStorage->removeEventListener( aListener ); +} + + +// container::XElementAccess (base of container::XNameAccess) + + +// virtual +uno::Type SAL_CALL Storage::getElementType() +{ + return m_xWrappedStorage->getElementType(); +} + + +// virtual +sal_Bool SAL_CALL Storage::hasElements() +{ + return m_xWrappedStorage->hasElements(); +} + + +// container::XNameAccess (base of embed::XStorage) + + +// virtual +uno::Any SAL_CALL Storage::getByName( const OUString& aName ) +{ + return m_xWrappedStorage->getByName( aName ); +} + + +// virtual +uno::Sequence< OUString > SAL_CALL Storage::getElementNames() +{ + return m_xWrappedStorage->getElementNames(); +} + + +// virtual +sal_Bool SAL_CALL Storage::hasByName( const OUString& aName ) +{ + return m_xWrappedStorage->hasByName( aName ); +} + + +// embed::XStorage + + +// virtual +void SAL_CALL Storage::copyToStorage( + const uno::Reference< embed::XStorage >& xDest ) +{ + m_xWrappedStorage->copyToStorage( xDest ); +} + + +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::openStreamElement( + const OUString& aStreamName, sal_Int32 nOpenMode ) +{ + return m_xWrappedStorage->openStreamElement( aStreamName, nOpenMode ); +} + + +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::openEncryptedStreamElement( + const OUString& aStreamName, + sal_Int32 nOpenMode, + const OUString& aPassword ) +{ + return m_xWrappedStorage->openEncryptedStreamElement( + aStreamName, nOpenMode, aPassword ); +} + + +// virtual +uno::Reference< embed::XStorage > SAL_CALL Storage::openStorageElement( + const OUString& aStorName, sal_Int32 nOpenMode ) +{ + return m_xWrappedStorage->openStorageElement( aStorName, nOpenMode ); +} + + +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::cloneStreamElement( + const OUString& aStreamName ) +{ + return m_xWrappedStorage->cloneStreamElement( aStreamName ); +} + + +// virtual +uno::Reference< io::XStream > SAL_CALL Storage::cloneEncryptedStreamElement( + const OUString& aStreamName, + const OUString& aPassword ) +{ + return m_xWrappedStorage->cloneEncryptedStreamElement( aStreamName, + aPassword ); +} + + +// virtual +void SAL_CALL Storage::copyLastCommitTo( + const uno::Reference< embed::XStorage >& xTargetStorage ) +{ + m_xWrappedStorage->copyLastCommitTo( xTargetStorage ); +} + + +// virtual +void SAL_CALL Storage::copyStorageElementLastCommitTo( + const OUString& aStorName, + const uno::Reference< embed::XStorage >& xTargetStorage ) +{ + m_xWrappedStorage->copyStorageElementLastCommitTo( aStorName, xTargetStorage ); +} + + +// virtual +sal_Bool SAL_CALL Storage::isStreamElement( + const OUString& aElementName ) +{ + return m_xWrappedStorage->isStreamElement( aElementName ); +} + + +// virtual +sal_Bool SAL_CALL Storage::isStorageElement( + const OUString& aElementName ) +{ + return m_xWrappedStorage->isStorageElement( aElementName ); +} + + +// virtual +void SAL_CALL Storage::removeElement( const OUString& aElementName ) +{ + m_xWrappedStorage->removeElement( aElementName ); +} + + +// virtual +void SAL_CALL Storage::renameElement( const OUString& aEleName, + const OUString& aNewName ) +{ + m_xWrappedStorage->renameElement( aEleName, aNewName ); +} + + +// virtual +void SAL_CALL Storage::copyElementTo( + const OUString& aElementName, + const uno::Reference< embed::XStorage >& xDest, + const OUString& aNewName ) +{ + m_xWrappedStorage->copyElementTo( aElementName, xDest, aNewName ); +} + + +// virtual +void SAL_CALL Storage::moveElementTo( + const OUString& aElementName, + const uno::Reference< embed::XStorage >& xDest, + const OUString& rNewName ) +{ + m_xWrappedStorage->moveElementTo( aElementName, xDest, rNewName ); +} + + +// embed::XTransactedObject + + +// virtual +void SAL_CALL Storage::commit() +{ + // 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() ) + return; + + OSL_ENSURE( m_xWrappedTransObj.is(), "No XTransactedObject interface!" ); + + if ( !m_xWrappedTransObj.is() ) + return; + + 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() +{ + uno::Reference< embed::XStorage > xParentStorage = getParentStorage(); + if ( !xParentStorage.is() ) + return; + + OSL_ENSURE( m_xWrappedTransObj.is(), "No XTransactedObject interface!" ); + + if ( !m_xWrappedTransObj.is() ) + return; + + 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< uno::XComponentContext > & rxContext, + const 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 = + reflection::ProxyFactory::create( rxContext ); + m_xAggProxy = xProxyFac->createProxy( m_xWrappedStream ); + } + catch ( uno::Exception const & ) + { + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + + OSL_ENSURE( m_xAggProxy.is(), + "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" ); + + if ( !m_xAggProxy.is() ) + return; + + osl_atomic_increment( &m_refCount ); + { + // Solaris compiler problem: + // Extra block to enforce destruction of temporary object created + // in next statement _before_ osl_atomic_decrement is + // called. Otherwise 'this' will destroy itself even before ctor + // is completed (See impl. of XInterface::release())! + + m_xAggProxy->setDelegator( + getXWeak() ); + } + osl_atomic_decrement( &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 ) +{ + 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() +{ + return m_xWrappedTypeProv->getTypes(); +} + + +// virtual +uno::Sequence< sal_Int8 > SAL_CALL OutputStream::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + + +// io::XOutputStream + + +// virtual +void SAL_CALL +OutputStream::writeBytes( const uno::Sequence< sal_Int8 >& aData ) +{ + m_xWrappedStream->writeBytes( aData ); +} + + +// virtual +void SAL_CALL +OutputStream::flush() +{ + m_xWrappedStream->flush(); +} + + +// virtual +void SAL_CALL +OutputStream::closeOutput( ) +{ + 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() +{ + 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 ) +{ + m_xWrappedComponent->addEventListener( xListener ); +} + + +// virtual +void SAL_CALL +OutputStream::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) +{ + m_xWrappedComponent->removeEventListener( aListener ); +} + + +// Stream Implementation. + + +Stream::Stream( + const uno::Reference< uno::XComponentContext > & rxContext, + rtl::Reference<OfficeDocumentsManager> const & docsMgr, + const OUString & rUri, + const uno::Reference< embed::XStorage > & xParentStorage, + const uno::Reference< io::XStream > & xStreamToWrap ) +: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ), + m_docsMgr(docsMgr), + m_uri(rUri), + m_xWrappedStream( xStreamToWrap ), + m_xWrappedOutputStream( xStreamToWrap->getOutputStream() ), // might be empty + m_xWrappedTruncate( m_xWrappedOutputStream, uno::UNO_QUERY ), // might be empty + m_xWrappedInputStream( xStreamToWrap->getInputStream() ), + 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 = + reflection::ProxyFactory::create( rxContext ); + m_xAggProxy = xProxyFac->createProxy( m_xWrappedStream ); + } + catch ( uno::Exception const & ) + { + TOOLS_WARN_EXCEPTION("ucb.ucp", ""); + } + + OSL_ENSURE( m_xAggProxy.is(), + "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" ); + + if ( !m_xAggProxy.is() ) + return; + + osl_atomic_increment( &m_refCount ); + { + // Solaris compiler problem: + // Extra block to enforce destruction of temporary object created + // in next statement _before_ osl_atomic_decrement is + // called. Otherwise 'this' will destroy itself even before ctor + // is completed (See impl. of XInterface::release())! + + m_xAggProxy->setDelegator( + getXWeak() ); + } + osl_atomic_decrement( &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 ) +{ + 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() +{ + return m_xWrappedTypeProv->getTypes(); +} + + +// virtual +uno::Sequence< sal_Int8 > SAL_CALL Stream::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + + +// io::XStream. + + +// virtual +uno::Reference< io::XInputStream > SAL_CALL Stream::getInputStream() +{ + return uno::Reference< io::XInputStream >( this ); +} + + +// virtual +uno::Reference< io::XOutputStream > SAL_CALL Stream::getOutputStream() +{ + return uno::Reference< io::XOutputStream >( this ); +} + + +// io::XOutputStream. + + +// virtual +void SAL_CALL Stream::writeBytes( const uno::Sequence< sal_Int8 >& aData ) +{ + if ( m_xWrappedOutputStream.is() ) + { + m_xWrappedOutputStream->writeBytes( aData ); + commitChanges(); + } +} + + +// virtual +void SAL_CALL Stream::flush() +{ + if ( m_xWrappedOutputStream.is() ) + { + m_xWrappedOutputStream->flush(); + commitChanges(); + } +} + + +// virtual +void SAL_CALL Stream::closeOutput() +{ + 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() +{ + 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 ) +{ + return m_xWrappedInputStream->readBytes( aData, nBytesToRead ); +} + + +// virtual +sal_Int32 SAL_CALL Stream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) +{ + return m_xWrappedInputStream->readSomeBytes( aData, nMaxBytesToRead ); +} + + +// virtual +void SAL_CALL Stream::skipBytes( sal_Int32 nBytesToSkip ) +{ + m_xWrappedInputStream->skipBytes( nBytesToSkip ); +} + + +// virtual +sal_Int32 SAL_CALL Stream::available() +{ + return m_xWrappedInputStream->available(); +} + + +// virtual +void SAL_CALL Stream::closeInput() +{ + m_xWrappedInputStream->closeInput(); +} + + +// lang::XComponent + + +// virtual +void SAL_CALL Stream::dispose() +{ + 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 ) +{ + m_xWrappedComponent->addEventListener( xListener ); +} + + +// virtual +void SAL_CALL Stream::removeEventListener( + const uno::Reference< lang::XEventListener >& aListener ) +{ + m_xWrappedComponent->removeEventListener( aListener ); +} + + +// Non-UNO + + +void Stream::commitChanges() +{ + 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(); // @@@ + } + } + m_docsMgr->updateStreamDateModified(m_uri); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |