diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /svl/source/fsstor | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'svl/source/fsstor')
-rw-r--r-- | svl/source/fsstor/fsfactory.cxx | 160 | ||||
-rw-r--r-- | svl/source/fsstor/fsstorage.component | 27 | ||||
-rw-r--r-- | svl/source/fsstor/fsstorage.cxx | 1102 | ||||
-rw-r--r-- | svl/source/fsstor/fsstorage.hxx | 178 | ||||
-rw-r--r-- | svl/source/fsstor/oinputstreamcontainer.cxx | 260 | ||||
-rw-r--r-- | svl/source/fsstor/oinputstreamcontainer.hxx | 83 | ||||
-rw-r--r-- | svl/source/fsstor/ostreamcontainer.cxx | 451 | ||||
-rw-r--r-- | svl/source/fsstor/ostreamcontainer.hxx | 109 |
8 files changed, 2370 insertions, 0 deletions
diff --git a/svl/source/fsstor/fsfactory.cxx b/svl/source/fsstor/fsfactory.cxx new file mode 100644 index 000000000..b611ff530 --- /dev/null +++ b/svl/source/fsstor/fsfactory.cxx @@ -0,0 +1,160 @@ +/* -*- 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 . + */ + + +#include <fsfactory.hxx> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <comphelper/processfactory.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/weak.hxx> +#include <ucbhelper/content.hxx> + +#include <unotools/tempfile.hxx> +#include <unotools/ucbhelper.hxx> + +#include "fsstorage.hxx" + + +using namespace ::com::sun::star; + + +uno::Reference< uno::XInterface > SAL_CALL FSStorageFactory::createInstance() +{ + OUString aTempURL = ::utl::TempFile( nullptr, true ).GetURL(); + + if ( aTempURL.isEmpty() ) + throw uno::RuntimeException("Cannot create tempfile."); + + ::ucbhelper::Content aResultContent( + aTempURL, uno::Reference< ucb::XCommandEnvironment >(), + comphelper::getProcessComponentContext() ); + + return uno::Reference< uno::XInterface >( + static_cast< OWeakObject* >( + new FSStorage( aResultContent, + embed::ElementModes::READWRITE, + m_xContext ) ), + uno::UNO_QUERY ); +} + +/** + * The request for storage can be done with up to three arguments. + * The first argument specifies a source for the storage it must be URL. + * The second value is a mode the storage should be open in. + * The third value is a media descriptor. + */ +uno::Reference< uno::XInterface > SAL_CALL FSStorageFactory::createInstanceWithArguments( + const uno::Sequence< uno::Any >& aArguments ) +{ + sal_Int32 nArgNum = aArguments.getLength(); + OSL_ENSURE( nArgNum < 4, "Wrong parameter number" ); + + if ( !nArgNum ) + return createInstance(); + + // first try to retrieve storage open mode if any + // by default the storage will be open in readonly mode + sal_Int32 nStorageMode = embed::ElementModes::READ; + if ( nArgNum >= 2 ) + { + if( !( aArguments[1] >>= nStorageMode ) ) + { + throw lang::IllegalArgumentException( + ("second argument to css.embed.FileSystemStorageFactory." + "createInstanceWithArguments must be a" + " css.embed.ElementModes"), + static_cast< OWeakObject * >(this), -1); + } + // it's always possible to read written storage in this implementation + nStorageMode |= embed::ElementModes::READ; + } + + // retrieve storage source URL + OUString aURL; + + if ( !( aArguments[0] >>= aURL ) || aURL.isEmpty() ) + { + throw lang::IllegalArgumentException( + ("first argument to" + " css.embed.FileSystemStorageFactory.createInstanceWithArguments" + " must be a (non-empty) URL"), + static_cast< OWeakObject * >(this), -1); + } + + // allow to use other ucp's + // if ( !isLocalNotFile_Impl( aURL ) ) + if ( aURL.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:") + || aURL.startsWithIgnoreAsciiCase("vnd.sun.star.zip:") + || ::utl::UCBContentHelper::IsDocument( aURL ) ) + { + throw lang::IllegalArgumentException( + ("URL \"" + aURL + "\" passed as first argument to" + " css.embed.FileSystemStorageFactory.createInstanceWithArguments" + " must be a file URL denoting a directory"), + static_cast< OWeakObject * >(this), -1); + } + + if ( ( nStorageMode & embed::ElementModes::WRITE ) && !( nStorageMode & embed::ElementModes::NOCREATE ) ) + FSStorage::MakeFolderNoUI( aURL ); + else if ( !::utl::UCBContentHelper::IsFolder( aURL ) ) + throw io::IOException( + ("URL \"" + aURL + "\" passed to" + " css.embed.FileSystemStorageFactory.createInstanceWithArguments" + " does not denote an existing directory"), + static_cast< OWeakObject * >(this)); + + ::ucbhelper::Content aResultContent( + aURL, uno::Reference< ucb::XCommandEnvironment >(), + comphelper::getProcessComponentContext() ); + + // create storage based on source + return uno::Reference< uno::XInterface >( + static_cast< OWeakObject* >( new FSStorage( aResultContent, + nStorageMode, + m_xContext ) ), + uno::UNO_QUERY ); +} + +OUString SAL_CALL FSStorageFactory::getImplementationName() +{ + return "com.sun.star.comp.embed.FileSystemStorageFactory"; +} + +sal_Bool SAL_CALL FSStorageFactory::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL FSStorageFactory::getSupportedServiceNames() +{ + return { "com.sun.star.embed.FileSystemStorageFactory", + "com.sun.star.comp.embed.FileSystemStorageFactory" }; +} + + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +svl_FSStorageFactory_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new FSStorageFactory(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/fsstor/fsstorage.component b/svl/source/fsstor/fsstorage.component new file mode 100644 index 000000000..7d20474b3 --- /dev/null +++ b/svl/source/fsstor/fsstorage.component @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.embed.FileSystemStorageFactory" + constructor="svl_FSStorageFactory_get_implementation" single-instance="true"> + <service name="com.sun.star.comp.embed.FileSystemStorageFactory"/> + <service name="com.sun.star.embed.FileSystemStorageFactory"/> + </implementation> +</component> diff --git a/svl/source/fsstor/fsstorage.cxx b/svl/source/fsstor/fsstorage.cxx new file mode 100644 index 000000000..8d2da219d --- /dev/null +++ b/svl/source/fsstor/fsstorage.cxx @@ -0,0 +1,1102 @@ +/* -*- 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 . + */ + +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/InvalidStorageException.hpp> +#include <com/sun/star/embed/StorageWrappedTargetException.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/packages/NoEncryptionException.hpp> +#include <com/sun/star/packages/WrongPasswordException.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/SimpleFileAccess.hpp> + +#include <com/sun/star/ucb/InteractiveIOException.hpp> +#include <com/sun/star/ucb/IOErrorCode.hpp> +#include <com/sun/star/container/ElementExistException.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/io/TempFile.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XRow.hpp> + +#include <comphelper/fileurl.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/storagehelper.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/exc_hlp.hxx> + +#include <osl/diagnose.h> +#include <tools/urlobj.hxx> +#include <unotools/ucbhelper.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/streamwrap.hxx> +#include <ucbhelper/content.hxx> + +#include "fsstorage.hxx" +#include "oinputstreamcontainer.hxx" +#include "ostreamcontainer.hxx" + +using namespace ::com::sun::star; + +FSStorage::FSStorage( const ::ucbhelper::Content& aContent, + sal_Int32 nMode, + uno::Reference< uno::XComponentContext > const & xContext ) +: m_aURL( aContent.getURL() ) +, m_aContent( aContent ) +, m_nMode( nMode ) +, m_xContext( xContext ) +{ + OSL_ENSURE( !m_aURL.isEmpty(), "The URL must not be empty" ); + // TODO: use properties + if ( !xContext.is() ) + throw uno::RuntimeException(); + + GetContent(); +} + +FSStorage::~FSStorage() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + osl_atomic_increment(&m_refCount); // to call dispose + try { + dispose(); + } + catch( uno::RuntimeException& ) + {} +} + +bool FSStorage::MakeFolderNoUI( std::u16string_view rFolder ) +{ + INetURLObject aURL( rFolder ); + OUString aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset ); + aURL.removeSegment(); + ::ucbhelper::Content aParent; + ::ucbhelper::Content aResultContent; + + if ( ::ucbhelper::Content::create( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), + uno::Reference< ucb::XCommandEnvironment >(), + comphelper::getProcessComponentContext(), + aParent ) ) + return ::utl::UCBContentHelper::MakeFolder( aParent, aTitle, aResultContent ); + + return false; +} + +ucbhelper::Content& FSStorage::GetContent() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return m_aContent; +} + +void FSStorage::CopyStreamToSubStream( const OUString& aSourceURL, + const uno::Reference< embed::XStorage >& xDest, + const OUString& aNewEntryName ) +{ + if ( !xDest.is() ) + throw uno::RuntimeException(); + + uno::Reference< ucb::XCommandEnvironment > xDummyEnv; + ::ucbhelper::Content aSourceContent( aSourceURL, xDummyEnv, comphelper::getProcessComponentContext() ); + uno::Reference< io::XInputStream > xSourceInput = aSourceContent.openStream(); + + if ( !xSourceInput.is() ) + throw io::IOException(); // TODO: error handling + + uno::Reference< io::XStream > xSubStream = xDest->openStreamElement( + aNewEntryName, + embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); + if ( !xSubStream.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XOutputStream > xDestOutput = xSubStream->getOutputStream(); + if ( !xDestOutput.is() ) + throw uno::RuntimeException(); + + ::comphelper::OStorageHelper::CopyInputToOutput( xSourceInput, xDestOutput ); + xDestOutput->closeOutput(); +} + +void FSStorage::CopyContentToStorage_Impl(ucbhelper::Content& rContent, + const uno::Reference<embed::XStorage>& xDest) +{ + // get list of contents of the Content + // create cursor for access to children + uno::Sequence< OUString > aProps( 2 ); + OUString* pProps = aProps.getArray(); + pProps[0] = "TargetURL"; + pProps[1] = "IsFolder"; + + try + { + uno::Reference<sdbc::XResultSet> xResultSet + = rContent.createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS); + uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY ); + if ( xResultSet.is() ) + { + // go through the list: insert files as streams, insert folders as substorages using recursion + while ( xResultSet->next() ) + { + OUString aSourceURL( xRow->getString( 1 ) ); + bool bIsFolder( xRow->getBoolean(2) ); + + // TODO/LATER: not sure whether the entry name must be encoded + OUString aNewEntryName( INetURLObject( aSourceURL ).getName( INetURLObject::LAST_SEGMENT, + true, + INetURLObject::DecodeMechanism::NONE ) ); + if ( bIsFolder ) + { + uno::Reference< embed::XStorage > xSubStorage = xDest->openStorageElement( aNewEntryName, + embed::ElementModes::READWRITE ); + if ( !xSubStorage.is() ) + throw uno::RuntimeException(); + + uno::Reference< ucb::XCommandEnvironment > xDummyEnv; + ::ucbhelper::Content aSourceContent( aSourceURL, xDummyEnv, comphelper::getProcessComponentContext() ); + CopyContentToStorage_Impl( aSourceContent, xSubStorage ); + } + else + { + CopyStreamToSubStream( aSourceURL, xDest, aNewEntryName ); + } + } + } + + uno::Reference< embed::XTransactedObject > xTransact( xDest, uno::UNO_QUERY ); + if ( xTransact.is() ) + xTransact->commit(); + } + catch( ucb::InteractiveIOException& r ) + { + if ( r.Code == ucb::IOErrorCode_NOT_EXISTING ) + OSL_FAIL( "The folder does not exist!" ); + else + throw; + } +} + +// XInterface + +uno::Any SAL_CALL FSStorage::queryInterface( const uno::Type& rType ) +{ + uno::Any aReturn = ::cppu::queryInterface + ( rType + , static_cast<lang::XTypeProvider*> ( this ) + , static_cast<embed::XStorage*> ( this ) + , static_cast<embed::XHierarchicalStorageAccess*> ( this ) + , static_cast<container::XNameAccess*> ( this ) + , static_cast<container::XElementAccess*> ( this ) + , static_cast<lang::XComponent*> ( this ) + , static_cast<beans::XPropertySet*> ( this ) ); + + if ( aReturn.hasValue() ) + return aReturn ; + + return OWeakObject::queryInterface( rType ); +} + +void SAL_CALL FSStorage::acquire() noexcept +{ + OWeakObject::acquire(); +} + +void SAL_CALL FSStorage::release() noexcept +{ + OWeakObject::release(); +} + +// XTypeProvider + +uno::Sequence< uno::Type > SAL_CALL FSStorage::getTypes() +{ + static const uno::Sequence<uno::Type> aTypes { + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<embed::XStorage>::get(), + cppu::UnoType<embed::XHierarchicalStorageAccess>::get(), + cppu::UnoType<beans::XPropertySet>::get() }; + return aTypes; +} + +uno::Sequence< sal_Int8 > SAL_CALL FSStorage::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XStorage + +void SAL_CALL FSStorage::copyToStorage( const uno::Reference< embed::XStorage >& xDest ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !xDest.is() || xDest == uno::Reference< uno::XInterface >( static_cast< OWeakObject*> ( this ), uno::UNO_QUERY ) ) + throw lang::IllegalArgumentException(); // TODO: + + try + { + CopyContentToStorage_Impl( GetContent(), xDest ); + } + catch( embed::InvalidStorageException& ) + { + throw; + } + catch( lang::IllegalArgumentException& ) + { + throw; + } + catch( embed::StorageWrappedTargetException& ) + { + throw; + } + catch( io::IOException& ) + { + throw; + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw embed::StorageWrappedTargetException("Can't copy raw stream", + uno::Reference< io::XInputStream >(), + aCaught ); + } +} + +uno::Reference< io::XStream > SAL_CALL FSStorage::openStreamElement( + const OUString& aStreamName, sal_Int32 nOpenMode ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked + INetURLObject aFileURL( m_aURL ); + aFileURL.Append( aStreamName ); + + if ( ::utl::UCBContentHelper::IsFolder( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + throw io::IOException(); + + if ( ( nOpenMode & embed::ElementModes::NOCREATE ) + && !::utl::UCBContentHelper::IsDocument( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + throw io::IOException(); // TODO: + + uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any + uno::Reference< io::XStream > xResult; + try + { + if ( nOpenMode & embed::ElementModes::WRITE ) + { + if ( aFileURL.GetProtocol() == INetProtocol::File ) + { + uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess( + ucb::SimpleFileAccess::create( m_xContext ) ); + xResult = xSimpleFileAccess->openFileReadWrite( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + } + else + { + // TODO: test whether it really works for http and fwp + std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), + StreamMode::STD_WRITE ); + if ( pStream && !pStream->GetError() ) + xResult.set( new ::utl::OStreamWrapper( std::move(pStream) ) ); + } + + if ( !xResult.is() ) + throw io::IOException(); + + if ( nOpenMode & embed::ElementModes::TRUNCATE ) + { + uno::Reference< io::XTruncate > xTrunc( xResult->getOutputStream(), uno::UNO_QUERY_THROW ); + xTrunc->truncate(); + } + } + else + { + if ( ( nOpenMode & embed::ElementModes::TRUNCATE ) + || !::utl::UCBContentHelper::IsDocument( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + throw io::IOException(); // TODO: access denied + + ::ucbhelper::Content aResultContent( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() ); + uno::Reference< io::XInputStream > xInStream = aResultContent.openStream(); + xResult = new OFSInputStreamContainer(xInStream); + } + } + catch( embed::InvalidStorageException& ) + { + throw; + } + catch( lang::IllegalArgumentException& ) + { + throw; + } + catch( packages::WrongPasswordException& ) + { + throw; + } + catch( embed::StorageWrappedTargetException& ) + { + throw; + } + catch( io::IOException& ) + { + throw; + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw embed::StorageWrappedTargetException("Can't copy raw stream", + uno::Reference< io::XInputStream >(), + aCaught ); + } + + return xResult; +} + +uno::Reference< io::XStream > SAL_CALL FSStorage::openEncryptedStreamElement( + const OUString&, sal_Int32, const OUString& ) +{ + throw packages::NoEncryptionException(); +} + +uno::Reference< embed::XStorage > SAL_CALL FSStorage::openStorageElement( + const OUString& aStorName, sal_Int32 nStorageMode ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( ( nStorageMode & embed::ElementModes::WRITE ) + && !( m_nMode & embed::ElementModes::WRITE ) ) + throw io::IOException(); // TODO: error handling + + // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked + INetURLObject aFolderURL( m_aURL ); + aFolderURL.Append( aStorName ); + + bool bFolderExists = ::utl::UCBContentHelper::IsFolder( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + if ( !bFolderExists && ::utl::UCBContentHelper::IsDocument( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + throw io::IOException(); // TODO: + + if ( ( nStorageMode & embed::ElementModes::NOCREATE ) && !bFolderExists ) + throw io::IOException(); // TODO: + + uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any + uno::Reference< embed::XStorage > xResult; + try + { + if ( nStorageMode & embed::ElementModes::WRITE ) + { + if ( ( nStorageMode & embed::ElementModes::TRUNCATE ) && bFolderExists ) + { + ::utl::UCBContentHelper::Kill( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + bFolderExists = + MakeFolderNoUI( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); // TODO: not atomic :( + } + else if ( !bFolderExists ) + { + bFolderExists = + MakeFolderNoUI( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); // TODO: not atomic :( + } + } + else if ( nStorageMode & embed::ElementModes::TRUNCATE ) + throw io::IOException(); // TODO: access denied + + if ( !bFolderExists ) + throw io::IOException(); // there is no such folder + + ::ucbhelper::Content aResultContent( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() ); + xResult = new FSStorage( aResultContent, nStorageMode, m_xContext ); + } + catch( embed::InvalidStorageException& ) + { + throw; + } + catch( lang::IllegalArgumentException& ) + { + throw; + } + catch( embed::StorageWrappedTargetException& ) + { + throw; + } + catch( io::IOException& ) + { + throw; + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw embed::StorageWrappedTargetException("Can't copy raw stream", + uno::Reference< io::XInputStream >(), + aCaught ); + } + + return xResult; +} + +uno::Reference< io::XStream > SAL_CALL FSStorage::cloneStreamElement( const OUString& aStreamName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked + INetURLObject aFileURL( m_aURL ); + aFileURL.Append( aStreamName ); + + uno::Reference < io::XStream > xTempResult; + try + { + uno::Reference< ucb::XCommandEnvironment > xDummyEnv; + ::ucbhelper::Content aResultContent( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() ); + uno::Reference< io::XInputStream > xInStream = aResultContent.openStream(); + + xTempResult = io::TempFile::create(m_xContext); + uno::Reference < io::XOutputStream > xTempOut = xTempResult->getOutputStream(); + uno::Reference < io::XInputStream > xTempIn = xTempResult->getInputStream(); + + if ( !xTempOut.is() || !xTempIn.is() ) + throw io::IOException(); + + ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOut ); + xTempOut->closeOutput(); + } + catch( embed::InvalidStorageException& ) + { + throw; + } + catch( lang::IllegalArgumentException& ) + { + throw; + } + catch( packages::WrongPasswordException& ) + { + throw; + } + catch( io::IOException& ) + { + throw; + } + catch( embed::StorageWrappedTargetException& ) + { + throw; + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw embed::StorageWrappedTargetException("Can't copy raw stream", + uno::Reference< io::XInputStream >(), + aCaught ); + } + + return xTempResult; +} + +uno::Reference< io::XStream > SAL_CALL FSStorage::cloneEncryptedStreamElement( + const OUString&, + const OUString& ) +{ + throw packages::NoEncryptionException(); +} + +void SAL_CALL FSStorage::copyLastCommitTo( + const uno::Reference< embed::XStorage >& xTargetStorage ) +{ + copyToStorage( xTargetStorage ); +} + +void SAL_CALL FSStorage::copyStorageElementLastCommitTo( + const OUString& aStorName, + const uno::Reference< embed::XStorage >& xTargetStorage ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + uno::Reference< embed::XStorage > xSourceStor( openStorageElement( aStorName, embed::ElementModes::READ ), + uno::UNO_SET_THROW ); + xSourceStor->copyToStorage( xTargetStorage ); +} + +sal_Bool SAL_CALL FSStorage::isStreamElement( const OUString& aElementName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + INetURLObject aURL( m_aURL ); + aURL.Append( aElementName ); + + return !::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); +} + +sal_Bool SAL_CALL FSStorage::isStorageElement( const OUString& aElementName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + INetURLObject aURL( m_aURL ); + aURL.Append( aElementName ); + + return ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); +} + +void SAL_CALL FSStorage::removeElement( const OUString& aElementName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + INetURLObject aURL( m_aURL ); + aURL.Append( aElementName ); + + if ( !::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) + && !::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + throw container::NoSuchElementException(); // TODO: + + ::utl::UCBContentHelper::Kill( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); +} + +void SAL_CALL FSStorage::renameElement( const OUString& aElementName, const OUString& aNewName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + INetURLObject aOldURL( m_aURL ); + aOldURL.Append( aElementName ); + + INetURLObject aNewURL( m_aURL ); + aNewURL.Append( aNewName ); + + if ( !::utl::UCBContentHelper::IsFolder( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) + && !::utl::UCBContentHelper::IsDocument( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + throw container::NoSuchElementException(); // TODO: + + if ( ::utl::UCBContentHelper::IsFolder( aNewURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) + || ::utl::UCBContentHelper::IsDocument( aNewURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + throw container::ElementExistException(); // TODO: + + try + { + uno::Reference< ucb::XCommandEnvironment > xDummyEnv; + ::ucbhelper::Content aSourceContent( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() ); + + GetContent().transferContent(aSourceContent, ::ucbhelper::InsertOperation::Move, aNewName, + ucb::NameClash::ERROR); + } + catch( embed::InvalidStorageException& ) + { + throw; + } + catch( lang::IllegalArgumentException& ) + { + throw; + } + catch( container::NoSuchElementException& ) + { + throw; + } + catch( container::ElementExistException& ) + { + throw; + } + catch( io::IOException& ) + { + throw; + } + catch( embed::StorageWrappedTargetException& ) + { + throw; + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw embed::StorageWrappedTargetException("Can't copy raw stream", + uno::Reference< io::XInputStream >(), + aCaught ); + } +} + +void SAL_CALL FSStorage::copyElementTo( const OUString& aElementName, + const uno::Reference< embed::XStorage >& xDest, + const OUString& aNewName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !xDest.is() ) + throw uno::RuntimeException(); + + INetURLObject aOwnURL( m_aURL ); + aOwnURL.Append( aElementName ); + + if ( xDest->hasByName( aNewName ) ) + throw container::ElementExistException(); // TODO: + + try + { + uno::Reference< ucb::XCommandEnvironment > xDummyEnv; + if ( ::utl::UCBContentHelper::IsFolder( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + { + ::ucbhelper::Content aSourceContent( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() ); + uno::Reference< embed::XStorage > xDestSubStor( + xDest->openStorageElement( aNewName, embed::ElementModes::READWRITE ), + uno::UNO_SET_THROW ); + + CopyContentToStorage_Impl( aSourceContent, xDestSubStor ); + } + else if ( ::utl::UCBContentHelper::IsDocument( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + { + CopyStreamToSubStream( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDest, aNewName ); + } + else + throw container::NoSuchElementException(); // TODO: + } + catch( embed::InvalidStorageException& ) + { + throw; + } + catch( lang::IllegalArgumentException& ) + { + throw; + } + catch( container::NoSuchElementException& ) + { + throw; + } + catch( container::ElementExistException& ) + { + throw; + } + catch( embed::StorageWrappedTargetException& ) + { + throw; + } + catch( io::IOException& ) + { + throw; + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw embed::StorageWrappedTargetException("Can't copy raw stream", + uno::Reference< io::XInputStream >(), + aCaught ); + } +} + +void SAL_CALL FSStorage::moveElementTo( const OUString& aElementName, + const uno::Reference< embed::XStorage >& xDest, + const OUString& aNewName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + copyElementTo( aElementName, xDest, aNewName ); + + INetURLObject aOwnURL( m_aURL ); + aOwnURL.Append( aElementName ); + if ( !::utl::UCBContentHelper::Kill( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + throw io::IOException(); // TODO: error handling +} + +// XNameAccess + +uno::Any SAL_CALL FSStorage::getByName( const OUString& aName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( aName.isEmpty() ) + throw lang::IllegalArgumentException(); + + uno::Any aResult; + try + { + INetURLObject aURL( m_aURL ); + aURL.Append( aName ); + + + if ( ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + { + aResult <<= openStorageElement( aName, embed::ElementModes::READ ); + } + else if ( ::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ) + { + aResult <<= openStreamElement( aName, embed::ElementModes::READ ); + } + else + throw container::NoSuchElementException(); // TODO: + } + catch (const container::NoSuchElementException&) + { + throw; + } + catch (const lang::WrappedTargetException&) + { + throw; + } + catch (const uno::RuntimeException&) + { + throw; + } + catch (const uno::Exception&) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw lang::WrappedTargetException( "Can not open element!", + static_cast< OWeakObject* >( this ), + aCaught ); + } + + return aResult; +} + + +uno::Sequence< OUString > SAL_CALL FSStorage::getElementNames() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + uno::Sequence< OUString > aResult; + + try + { + uno::Sequence<OUString> aProps { "Title" }; + + sal_Int32 nSize = 0; + uno::Reference<sdbc::XResultSet> xResultSet + = GetContent().createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS); + uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY ); + if ( xResultSet.is() ) + { + // go through the list + while ( xResultSet->next() ) + { + OUString aName( xRow->getString( 1 ) ); + aResult.realloc( ++nSize ); + aResult.getArray()[nSize-1] = aName; + } + } + } + catch( const ucb::InteractiveIOException& r ) + { + if ( r.Code == ucb::IOErrorCode_NOT_EXISTING ) + OSL_FAIL( "The folder does not exist!" ); + else + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( "Can not open storage!", + static_cast< OWeakObject* >( this ), + aCaught ); + } + } + catch (const uno::RuntimeException&) + { + throw; + } + catch (const uno::Exception&) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( "Can not open storage!", + static_cast< OWeakObject* >( this ), + aCaught ); + } + + return aResult; +} + +sal_Bool SAL_CALL FSStorage::hasByName( const OUString& aName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( aName.isEmpty() ) + throw lang::IllegalArgumentException(); + + INetURLObject aURL( m_aURL ); + aURL.Append( aName ); + + return ( ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) + || ::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ); +} + +uno::Type SAL_CALL FSStorage::getElementType() +{ + // it is a multitype container + return uno::Type(); +} + +sal_Bool SAL_CALL FSStorage::hasElements() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + try + { + uno::Sequence<OUString> aProps { "TargetURL" }; + + uno::Reference<sdbc::XResultSet> xResultSet + = GetContent().createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS); + return ( xResultSet.is() && xResultSet->next() ); + } + catch (const uno::RuntimeException&) + { + throw; + } + catch (const uno::Exception& ex) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw lang::WrappedTargetRuntimeException( ex.Message, + nullptr, anyEx ); + } +} + +// XDisposable +void SAL_CALL FSStorage::dispose() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pListenersContainer ) + { + lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); + m_pListenersContainer->disposeAndClear( aSource ); + } +} + +void SAL_CALL FSStorage::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pListenersContainer ) + m_pListenersContainer.reset(new ::comphelper::OInterfaceContainerHelper3<css::lang::XEventListener>( m_aMutex )); + + m_pListenersContainer->addInterface( xListener ); +} + +void SAL_CALL FSStorage::removeEventListener( + const uno::Reference< lang::XEventListener >& xListener ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pListenersContainer ) + m_pListenersContainer->removeInterface( xListener ); +} + +// XPropertySet + +uno::Reference< beans::XPropertySetInfo > SAL_CALL FSStorage::getPropertySetInfo() +{ + //TODO: + return uno::Reference< beans::XPropertySetInfo >(); +} + + +void SAL_CALL FSStorage::setPropertyValue( const OUString& aPropertyName, const uno::Any& ) +{ + if ( aPropertyName == "URL" || aPropertyName == "OpenMode" ) + throw beans::PropertyVetoException(); // TODO + else + throw beans::UnknownPropertyException(aPropertyName); // TODO +} + + +uno::Any SAL_CALL FSStorage::getPropertyValue( const OUString& aPropertyName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( aPropertyName == "URL" ) + return uno::Any( m_aURL ); + else if ( aPropertyName == "OpenMode" ) + return uno::Any( m_nMode ); + + throw beans::UnknownPropertyException(aPropertyName); // TODO +} + + +void SAL_CALL FSStorage::addPropertyChangeListener( + const OUString& /*aPropertyName*/, + const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ ) +{ + //TODO: +} + + +void SAL_CALL FSStorage::removePropertyChangeListener( + const OUString& /*aPropertyName*/, + const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ ) +{ + //TODO: +} + + +void SAL_CALL FSStorage::addVetoableChangeListener( + const OUString& /*PropertyName*/, + const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ ) +{ + //TODO: +} + + +void SAL_CALL FSStorage::removeVetoableChangeListener( + const OUString& /*PropertyName*/, + const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ ) +{ + //TODO: +} + +// XHierarchicalStorageAccess +uno::Reference< embed::XExtendedStorageStream > SAL_CALL FSStorage::openStreamElementByHierarchicalName( const OUString& sStreamPath, ::sal_Int32 nOpenMode ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( sStreamPath.toChar() == '/' ) + throw lang::IllegalArgumentException(); + + INetURLObject aBaseURL( m_aURL ); + if ( !aBaseURL.setFinalSlash() ) + throw uno::RuntimeException(); + + OUString aFileURL = INetURLObject::GetAbsURL( + aBaseURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), + sStreamPath ); + + if ( ::utl::UCBContentHelper::IsFolder( aFileURL ) ) + throw io::IOException(); + + if ( ( nOpenMode & embed::ElementModes::NOCREATE ) + && !::utl::UCBContentHelper::IsDocument( aFileURL ) ) + throw io::IOException(); // TODO: + + uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any + uno::Reference< io::XStream > xResult; + try + { + if ( nOpenMode & embed::ElementModes::WRITE ) + { + if ( comphelper::isFileUrl( aFileURL ) ) + { + uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess( + ucb::SimpleFileAccess::create( m_xContext ) ); + uno::Reference< io::XStream > xStream = + xSimpleFileAccess->openFileReadWrite( aFileURL ); + + xResult = new OFSStreamContainer(xStream); + } + else + { + // TODO: test whether it really works for http and fwp + std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( aFileURL, + StreamMode::STD_WRITE ); + if ( pStream && !pStream->GetError() ) + { + uno::Reference< io::XStream > xStream( new ::utl::OStreamWrapper( std::move(pStream) ) ); + xResult = new OFSStreamContainer(xStream); + } + } + + if ( !xResult.is() ) + throw io::IOException(); + + if ( nOpenMode & embed::ElementModes::TRUNCATE ) + { + uno::Reference< io::XTruncate > xTrunc( xResult->getOutputStream(), uno::UNO_QUERY_THROW ); + xTrunc->truncate(); + } + } + else + { + if ( ( nOpenMode & embed::ElementModes::TRUNCATE ) + || !::utl::UCBContentHelper::IsDocument( aFileURL ) ) + throw io::IOException(); // TODO: access denied + + ::ucbhelper::Content aResultContent( aFileURL, xDummyEnv, comphelper::getProcessComponentContext() ); + uno::Reference< io::XInputStream > xInStream = aResultContent.openStream(); + xResult = new OFSInputStreamContainer(xInStream); + } + } + catch( embed::InvalidStorageException& ) + { + throw; + } + catch( lang::IllegalArgumentException& ) + { + throw; + } + catch( packages::WrongPasswordException& ) + { + throw; + } + catch( embed::StorageWrappedTargetException& ) + { + throw; + } + catch( io::IOException& ) + { + throw; + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw embed::StorageWrappedTargetException("Can't copy raw stream", + uno::Reference< io::XInputStream >(), + aCaught ); + } + + return uno::Reference< embed::XExtendedStorageStream >( xResult, uno::UNO_QUERY_THROW ); +} + +uno::Reference< embed::XExtendedStorageStream > SAL_CALL FSStorage::openEncryptedStreamElementByHierarchicalName( const OUString& /*sStreamName*/, ::sal_Int32 /*nOpenMode*/, const OUString& /*sPassword*/ ) +{ + throw packages::NoEncryptionException(); +} + +void SAL_CALL FSStorage::removeStreamElementByHierarchicalName( const OUString& sStreamPath ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked + INetURLObject aBaseURL( m_aURL ); + if ( !aBaseURL.setFinalSlash() ) + throw uno::RuntimeException(); + + OUString aFileURL = INetURLObject::GetAbsURL( + aBaseURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), + sStreamPath ); + + if ( !::utl::UCBContentHelper::IsDocument( aFileURL ) ) + { + if ( ::utl::UCBContentHelper::IsFolder( aFileURL ) ) + throw lang::IllegalArgumentException(); + else + throw container::NoSuchElementException(); // TODO: + } + + if ( !::utl::UCBContentHelper::Kill( aFileURL ) ) + throw io::IOException(); // TODO: error handling +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/fsstor/fsstorage.hxx b/svl/source/fsstor/fsstorage.hxx new file mode 100644 index 000000000..1c4ae7030 --- /dev/null +++ b/svl/source/fsstor/fsstorage.hxx @@ -0,0 +1,178 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_SVL_SOURCE_FSSTOR_FSSTORAGE_HXX +#define INCLUDED_SVL_SOURCE_FSSTOR_FSSTORAGE_HXX + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/XHierarchicalStorageAccess.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <comphelper/interfacecontainer3.hxx> +#include <cppuhelper/weak.hxx> + +#include <ucbhelper/content.hxx> + +class FSStorage : public css::lang::XTypeProvider + , public css::embed::XStorage + , public css::embed::XHierarchicalStorageAccess + , public css::beans::XPropertySet + , public ::cppu::OWeakObject +{ + ::osl::Mutex m_aMutex; + OUString m_aURL; + ::ucbhelper::Content m_aContent; + sal_Int32 m_nMode; + std::unique_ptr<::comphelper::OInterfaceContainerHelper3<css::lang::XEventListener>> m_pListenersContainer; // list of listeners + css::uno::Reference< css::uno::XComponentContext > m_xContext; + +public: + + FSStorage( const ::ucbhelper::Content& aContent, + sal_Int32 nMode, + css::uno::Reference< css::uno::XComponentContext > const & xContext ); + + virtual ~FSStorage() override; + + ucbhelper::Content& GetContent(); + + static void CopyStreamToSubStream( const OUString& aSourceURL, + const css::uno::Reference< css::embed::XStorage >& xDest, + const OUString& aNewEntryName ); + + void CopyContentToStorage_Impl(ucbhelper::Content& rContent, + const css::uno::Reference<css::embed::XStorage>& xDest); + + static bool MakeFolderNoUI( std::u16string_view rFolder ); + + // XInterface + + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& rType ) override; + + virtual void SAL_CALL acquire() noexcept override; + + virtual void SAL_CALL release() noexcept override; + + // XTypeProvider + + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override; + + // XStorage + + virtual void SAL_CALL copyToStorage( const css::uno::Reference< css::embed::XStorage >& xDest ) override; + + virtual css::uno::Reference< css::io::XStream > SAL_CALL openStreamElement( + const OUString& aStreamName, sal_Int32 nOpenMode ) override; + + virtual css::uno::Reference< css::io::XStream > SAL_CALL openEncryptedStreamElement( + const OUString& aStreamName, sal_Int32 nOpenMode, const OUString& aPass ) override; + + virtual css::uno::Reference< css::embed::XStorage > SAL_CALL openStorageElement( + const OUString& aStorName, sal_Int32 nStorageMode ) override; + + virtual css::uno::Reference< css::io::XStream > SAL_CALL cloneStreamElement( + const OUString& aStreamName ) override; + + virtual css::uno::Reference< css::io::XStream > SAL_CALL cloneEncryptedStreamElement( + const OUString& aStreamName, const OUString& aPass ) override; + + virtual void SAL_CALL copyLastCommitTo( + const css::uno::Reference< css::embed::XStorage >& xTargetStorage ) override; + + virtual void SAL_CALL copyStorageElementLastCommitTo( + const OUString& aStorName, + const css::uno::Reference< css::embed::XStorage >& xTargetStorage ) override; + + virtual sal_Bool SAL_CALL isStreamElement( const OUString& aElementName ) override; + + virtual sal_Bool SAL_CALL isStorageElement( const OUString& aElementName ) override; + + virtual void SAL_CALL removeElement( const OUString& aElementName ) override; + + virtual void SAL_CALL renameElement( const OUString& rEleName, const OUString& rNewName ) override; + + virtual void SAL_CALL copyElementTo( const OUString& aElementName, + const css::uno::Reference< css::embed::XStorage >& xDest, + const OUString& aNewName ) override; + + virtual void SAL_CALL moveElementTo( const OUString& aElementName, + const css::uno::Reference< css::embed::XStorage >& xDest, + const OUString& rNewName ) override; + + // XNameAccess + + virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override; + + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override; + + virtual css::uno::Type SAL_CALL getElementType() override; + + virtual sal_Bool SAL_CALL hasElements() override; + + // XComponent + + virtual void SAL_CALL dispose() override; + + virtual void SAL_CALL addEventListener( + const css::uno::Reference< css::lang::XEventListener >& xListener ) override; + + virtual void SAL_CALL removeEventListener( + const css::uno::Reference< css::lang::XEventListener >& xListener ) override; + + // XPropertySet + + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override; + + virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override; + + virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override; + + virtual void SAL_CALL addPropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override; + + virtual void SAL_CALL removePropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override; + + virtual void SAL_CALL addVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override; + + virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override; + + // XHierarchicalStorageAccess + + virtual css::uno::Reference< css::embed::XExtendedStorageStream > SAL_CALL openStreamElementByHierarchicalName( const OUString& sStreamPath, ::sal_Int32 nOpenMode ) override; + + virtual css::uno::Reference< css::embed::XExtendedStorageStream > SAL_CALL openEncryptedStreamElementByHierarchicalName( const OUString& sStreamName, ::sal_Int32 nOpenMode, const OUString& sPassword ) override; + + virtual void SAL_CALL removeStreamElementByHierarchicalName( const OUString& sElementPath ) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/fsstor/oinputstreamcontainer.cxx b/svl/source/fsstor/oinputstreamcontainer.cxx new file mode 100644 index 000000000..f6481b76f --- /dev/null +++ b/svl/source/fsstor/oinputstreamcontainer.cxx @@ -0,0 +1,260 @@ +/* -*- 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 . + */ + + +#include "oinputstreamcontainer.hxx" +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/queryinterface.hxx> + +using namespace ::com::sun::star; + +OFSInputStreamContainer::OFSInputStreamContainer( const uno::Reference< io::XInputStream >& xStream ) +: m_xInputStream( xStream ) +, m_xSeekable( xStream, uno::UNO_QUERY ) +, m_bSeekable( false ) +, m_bDisposed( false ) +{ + m_bSeekable = m_xSeekable.is(); +} + +OFSInputStreamContainer::~OFSInputStreamContainer() +{ +} + +uno::Sequence< uno::Type > SAL_CALL OFSInputStreamContainer::getTypes() +{ + if (m_bSeekable) + { + static cppu::OTypeCollection aTypeCollection(cppu::UnoType<io::XStream>::get(), + cppu::UnoType<io::XInputStream>::get(), + cppu::UnoType<io::XSeekable>::get()); + + return aTypeCollection.getTypes(); + } + else + { + static cppu::OTypeCollection aTypeCollection(cppu::UnoType<io::XStream>::get(), + cppu::UnoType<io::XInputStream>::get()); + + return aTypeCollection.getTypes(); + } +} + +uno::Any SAL_CALL OFSInputStreamContainer::queryInterface( const uno::Type& rType ) +{ + // Attention: + // Don't use mutex or guard in this method!!! Is a method of XInterface. + + uno::Any aReturn; + if ( m_bSeekable ) + aReturn = ::cppu::queryInterface( rType, + static_cast< io::XStream* >( this ), + static_cast< io::XInputStream* >( this ), + static_cast< io::XSeekable* >( this ) ); + else + aReturn = ::cppu::queryInterface( rType, + static_cast< io::XStream* >( this ), + static_cast< io::XInputStream* >( this ) ); + + if ( aReturn.hasValue() ) + return aReturn ; + + return ::cppu::OWeakObject::queryInterface( rType ) ; +} + +void SAL_CALL OFSInputStreamContainer::acquire() + noexcept +{ + ::cppu::OWeakObject::acquire(); +} + +void SAL_CALL OFSInputStreamContainer::release() + noexcept +{ + ::cppu::OWeakObject::release(); +} + +sal_Int32 SAL_CALL OFSInputStreamContainer::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xInputStream.is() ) + throw uno::RuntimeException(); + + return m_xInputStream->readBytes( aData, nBytesToRead ); +} + +sal_Int32 SAL_CALL OFSInputStreamContainer::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xInputStream.is() ) + throw uno::RuntimeException(); + + return m_xInputStream->readSomeBytes( aData, nMaxBytesToRead ); +} + +void SAL_CALL OFSInputStreamContainer::skipBytes( sal_Int32 nBytesToSkip ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xInputStream.is() ) + throw uno::RuntimeException(); + + m_xInputStream->skipBytes( nBytesToSkip ); +} + +sal_Int32 SAL_CALL OFSInputStreamContainer::available( ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xInputStream.is() ) + throw uno::RuntimeException(); + + return m_xInputStream->available(); +} + +void SAL_CALL OFSInputStreamContainer::closeInput( ) +{ + { + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xInputStream.is() ) + throw uno::RuntimeException(); + } + dispose(); +} + +uno::Reference< io::XInputStream > SAL_CALL OFSInputStreamContainer::getInputStream() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xInputStream.is() ) + return uno::Reference< io::XInputStream >(); + + return this; +} + +uno::Reference< io::XOutputStream > SAL_CALL OFSInputStreamContainer::getOutputStream() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + return uno::Reference< io::XOutputStream >(); +} + +void SAL_CALL OFSInputStreamContainer::seek( sal_Int64 location ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xSeekable.is() ) + throw uno::RuntimeException(); + + m_xSeekable->seek( location ); +} + +sal_Int64 SAL_CALL OFSInputStreamContainer::getPosition() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xSeekable.is() ) + throw uno::RuntimeException(); + + return m_xSeekable->getPosition(); +} + +sal_Int64 SAL_CALL OFSInputStreamContainer::getLength() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xSeekable.is() ) + throw uno::RuntimeException(); + + return m_xSeekable->getLength(); +} + +void SAL_CALL OFSInputStreamContainer::dispose( ) +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xInputStream.is() ) + throw uno::RuntimeException(); + + m_xInputStream->closeInput(); + + lang::EventObject aSource( static_cast< ::cppu::OWeakObject*>( this ) ); + m_aListenersContainer.disposeAndClear( aGuard, aSource ); + + m_bDisposed = true; +} + +void SAL_CALL OFSInputStreamContainer::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + m_aListenersContainer.addInterface( aGuard, xListener ); +} + +void SAL_CALL OFSInputStreamContainer::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + m_aListenersContainer.removeInterface( aGuard, xListener ); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/fsstor/oinputstreamcontainer.hxx b/svl/source/fsstor/oinputstreamcontainer.hxx new file mode 100644 index 000000000..7228bcde5 --- /dev/null +++ b/svl/source/fsstor/oinputstreamcontainer.hxx @@ -0,0 +1,83 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_SVL_SOURCE_FSSTOR_OINPUTSTREAMCONTAINER_HXX +#define INCLUDED_SVL_SOURCE_FSSTOR_OINPUTSTREAMCONTAINER_HXX + +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/embed/XExtendedStorageStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> + + +#include <cppuhelper/implbase.hxx> +#include <comphelper/interfacecontainer4.hxx> + +#include <mutex> + +class OFSInputStreamContainer : public cppu::WeakImplHelper < css::io::XInputStream + ,css::embed::XExtendedStorageStream > + , public css::io::XSeekable +{ + std::mutex m_aMutex; + + css::uno::Reference < css::io::XInputStream > m_xInputStream; + css::uno::Reference < css::io::XSeekable > m_xSeekable; + + bool m_bSeekable; + + bool m_bDisposed; + + ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aListenersContainer; // list of listeners + +public: + explicit OFSInputStreamContainer( const css::uno::Reference < css::io::XInputStream >& xStream ); + + virtual ~OFSInputStreamContainer() override; + + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override; + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& rType ) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + // XInputStream + virtual sal_Int32 SAL_CALL readBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) override; + virtual sal_Int32 SAL_CALL readSomeBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) override; + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override; + virtual sal_Int32 SAL_CALL available( ) override; + virtual void SAL_CALL closeInput( ) override; + + //XStream + virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getInputStream( ) override; + virtual css::uno::Reference< css::io::XOutputStream > SAL_CALL getOutputStream( ) override; + + //XSeekable + virtual void SAL_CALL seek( sal_Int64 location ) override; + virtual sal_Int64 SAL_CALL getPosition() override; + virtual sal_Int64 SAL_CALL getLength() override; + + //XComponent + virtual void SAL_CALL dispose() override; + virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override; + virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override; + +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/fsstor/ostreamcontainer.cxx b/svl/source/fsstor/ostreamcontainer.cxx new file mode 100644 index 000000000..e02ce1383 --- /dev/null +++ b/svl/source/fsstor/ostreamcontainer.cxx @@ -0,0 +1,451 @@ +/* -*- 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 . + */ + +#include "ostreamcontainer.hxx" + +#include <cppuhelper/queryinterface.hxx> +#include <comphelper/sequence.hxx> + + +using namespace ::com::sun::star; + +OFSStreamContainer::OFSStreamContainer( const uno::Reference < io::XStream >& xStream ) +: m_bDisposed( false ) +, m_bInputClosed( false ) +, m_bOutputClosed( false ) +{ + try + { + m_xStream = xStream; + if ( !m_xStream.is() ) + throw uno::RuntimeException(); + + m_xSeekable.set( xStream, uno::UNO_QUERY ); + m_xInputStream = xStream->getInputStream(); + m_xOutputStream = xStream->getOutputStream(); + m_xTruncate.set( m_xOutputStream, uno::UNO_QUERY ); + m_xAsyncOutputMonitor.set( m_xOutputStream, uno::UNO_QUERY ); + } + catch( uno::Exception& ) + { + m_xStream.clear(); + m_xSeekable.clear(); + m_xInputStream.clear(); + m_xOutputStream.clear(); + m_xTruncate.clear(); + m_xAsyncOutputMonitor.clear(); + } +} + +OFSStreamContainer::~OFSStreamContainer() +{ +} + +// XInterface +uno::Any SAL_CALL OFSStreamContainer::queryInterface( const uno::Type& rType ) +{ + uno::Any aReturn = ::cppu::queryInterface + ( rType + , static_cast<lang::XTypeProvider*> ( this ) + , static_cast<io::XStream*> ( this ) + , static_cast<embed::XExtendedStorageStream*> ( this ) + , static_cast<lang::XComponent*> ( this ) ); + + if ( aReturn.hasValue() ) + return aReturn ; + + if ( m_xSeekable.is() ) + { + aReturn = ::cppu::queryInterface + ( rType + , static_cast<io::XSeekable*> ( this ) ); + + if ( aReturn.hasValue() ) + return aReturn ; + } + + if ( m_xInputStream.is() ) + { + aReturn = ::cppu::queryInterface + ( rType + , static_cast<io::XInputStream*> ( this ) ); + + if ( aReturn.hasValue() ) + return aReturn ; + } + if ( m_xOutputStream.is() ) + { + aReturn = ::cppu::queryInterface + ( rType + , static_cast<io::XOutputStream*> ( this ) ); + + if ( aReturn.hasValue() ) + return aReturn ; + } + if ( m_xTruncate.is() ) + { + aReturn = ::cppu::queryInterface + ( rType + , static_cast<io::XTruncate*> ( this ) ); + + if ( aReturn.hasValue() ) + return aReturn ; + } + if ( m_xAsyncOutputMonitor.is() ) + { + aReturn = ::cppu::queryInterface + ( rType + , static_cast<io::XAsyncOutputMonitor*> ( this ) ); + + if ( aReturn.hasValue() ) + return aReturn ; + } + + return OWeakObject::queryInterface( rType ); +} + +void SAL_CALL OFSStreamContainer::acquire() + noexcept +{ + OWeakObject::acquire(); +} + +void SAL_CALL OFSStreamContainer::release() + noexcept +{ + OWeakObject::release(); +} + +// XTypeProvider +uno::Sequence< uno::Type > SAL_CALL OFSStreamContainer::getTypes() +{ + if ( !m_aTypes.hasElements() ) + { + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_aTypes.hasElements() ) + { + std::vector<uno::Type> tmp + { + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<embed::XExtendedStorageStream>::get() + }; + + if ( m_xSeekable.is() ) + tmp.push_back(cppu::UnoType<io::XSeekable>::get()); + if ( m_xInputStream.is() ) + tmp.push_back(cppu::UnoType<io::XInputStream>::get()); + if ( m_xOutputStream.is() ) + tmp.push_back(cppu::UnoType<io::XOutputStream>::get()); + if ( m_xTruncate.is() ) + tmp.push_back(cppu::UnoType<io::XTruncate>::get()); + if ( m_xAsyncOutputMonitor.is() ) + tmp.push_back(cppu::UnoType<io::XAsyncOutputMonitor>::get()); + + m_aTypes = comphelper::containerToSequence(tmp); + } + } + return m_aTypes; +} + +uno::Sequence< sal_Int8 > SAL_CALL OFSStreamContainer::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XStream +uno::Reference< io::XInputStream > SAL_CALL OFSStreamContainer::getInputStream() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() ) + throw uno::RuntimeException(); + + if ( m_xInputStream.is() ) + return uno::Reference< io::XInputStream >( static_cast< io::XInputStream* >( this ) ); + + return uno::Reference< io::XInputStream >(); +} + +uno::Reference< io::XOutputStream > SAL_CALL OFSStreamContainer::getOutputStream() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() ) + throw uno::RuntimeException(); + + if ( m_xOutputStream.is() ) + return uno::Reference< io::XOutputStream >( static_cast< io::XOutputStream* >( this ) ); + + return uno::Reference< io::XOutputStream >(); +} + +// XComponent +void SAL_CALL OFSStreamContainer::dispose() +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() ) + throw uno::RuntimeException(); + + if ( m_xInputStream.is() && !m_bInputClosed ) + { + m_xInputStream->closeInput(); + m_bInputClosed = true; + } + + if ( m_xOutputStream.is() && !m_bOutputClosed ) + { + m_xOutputStream->closeOutput(); + m_bOutputClosed = true; + } + + lang::EventObject aSource( static_cast< ::cppu::OWeakObject*>( this ) ); + m_aListenersContainer.disposeAndClear( aGuard, aSource ); + m_bDisposed = true; +} + +void SAL_CALL OFSStreamContainer::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + m_aListenersContainer.addInterface( aGuard, xListener ); +} + +void SAL_CALL OFSStreamContainer::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + m_aListenersContainer.removeInterface( aGuard, xListener ); +} + + +// XSeekable +void SAL_CALL OFSStreamContainer::seek( sal_Int64 location ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xSeekable.is() ) + throw uno::RuntimeException(); + + m_xSeekable->seek( location ); +} + +sal_Int64 SAL_CALL OFSStreamContainer::getPosition() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xSeekable.is() ) + throw uno::RuntimeException(); + + return m_xSeekable->getPosition(); +} + +sal_Int64 SAL_CALL OFSStreamContainer::getLength() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xSeekable.is() ) + throw uno::RuntimeException(); + + return m_xSeekable->getLength(); +} + + +// XInputStream +sal_Int32 SAL_CALL OFSStreamContainer::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xInputStream.is() ) + throw uno::RuntimeException(); + + return m_xInputStream->readBytes( aData, nBytesToRead ); +} + +sal_Int32 SAL_CALL OFSStreamContainer::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xInputStream.is() ) + throw uno::RuntimeException(); + + return m_xInputStream->readSomeBytes( aData, nMaxBytesToRead ); +} + +void SAL_CALL OFSStreamContainer::skipBytes( sal_Int32 nBytesToSkip ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xInputStream.is() ) + throw uno::RuntimeException(); + + m_xInputStream->skipBytes( nBytesToSkip ); +} + +sal_Int32 SAL_CALL OFSStreamContainer::available() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xInputStream.is() ) + throw uno::RuntimeException(); + + return m_xInputStream->available(); +} + +void SAL_CALL OFSStreamContainer::closeInput() +{ + { + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xInputStream.is() ) + throw uno::RuntimeException(); + + if ( m_xInputStream.is() ) + { + m_xInputStream->closeInput(); + m_bInputClosed = true; + } + if ( !m_bOutputClosed ) + return; + } + + dispose(); +} + +// XOutputStream +void SAL_CALL OFSStreamContainer::writeBytes( const uno::Sequence< sal_Int8 >& aData ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xOutputStream.is() ) + throw uno::RuntimeException(); + + return m_xOutputStream->writeBytes( aData ); +} + +void SAL_CALL OFSStreamContainer::flush() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xOutputStream.is() ) + throw uno::RuntimeException(); + + return m_xOutputStream->flush(); +} + +void SAL_CALL OFSStreamContainer::closeOutput() +{ + { + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xOutputStream.is() ) + throw uno::RuntimeException(); + + if ( m_xOutputStream.is() ) + { + m_xOutputStream->closeOutput(); + m_bOutputClosed = true; + } + if ( !m_bInputClosed ) + return; + } + dispose(); +} + + +// XTruncate +void SAL_CALL OFSStreamContainer::truncate() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xTruncate.is() ) + throw uno::RuntimeException(); + + m_xTruncate->truncate(); +} + + +// XAsyncOutputMonitor +void SAL_CALL OFSStreamContainer::waitForCompletion() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_xStream.is() || !m_xAsyncOutputMonitor.is() ) + throw uno::RuntimeException(); + + m_xAsyncOutputMonitor->waitForCompletion(); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/fsstor/ostreamcontainer.hxx b/svl/source/fsstor/ostreamcontainer.hxx new file mode 100644 index 000000000..7dd821905 --- /dev/null +++ b/svl/source/fsstor/ostreamcontainer.hxx @@ -0,0 +1,109 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_SVL_SOURCE_FSSTOR_OSTREAMCONTAINER_HXX +#define INCLUDED_SVL_SOURCE_FSSTOR_OSTREAMCONTAINER_HXX + +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/embed/XExtendedStorageStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XAsyncOutputMonitor.hpp> +#include <cppuhelper/weak.hxx> +#include <comphelper/interfacecontainer4.hxx> +#include <mutex> + +class OFSStreamContainer : public cppu::OWeakObject, + public css::lang::XTypeProvider, + public css::embed::XExtendedStorageStream, + public css::io::XSeekable, + public css::io::XInputStream, + public css::io::XOutputStream, + public css::io::XTruncate, + public css::io::XAsyncOutputMonitor +{ + std::mutex m_aMutex; + + css::uno::Reference< css::io::XStream > m_xStream; + css::uno::Reference< css::io::XSeekable > m_xSeekable; + css::uno::Reference< css::io::XInputStream > m_xInputStream; + css::uno::Reference< css::io::XOutputStream > m_xOutputStream; + css::uno::Reference< css::io::XTruncate > m_xTruncate; + css::uno::Reference< css::io::XAsyncOutputMonitor > m_xAsyncOutputMonitor; + + bool m_bDisposed; + bool m_bInputClosed; + bool m_bOutputClosed; + + ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aListenersContainer; // list of listeners + css::uno::Sequence<css::uno::Type> m_aTypes; + +public: + explicit OFSStreamContainer( const css::uno::Reference < css::io::XStream >& xStream ); + virtual ~OFSStreamContainer() override; + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& rType ) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + // XTypeProvider + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override; + + // XStream + virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getInputStream( ) override; + virtual css::uno::Reference< css::io::XOutputStream > SAL_CALL getOutputStream( ) override; + + // XComponent + virtual void SAL_CALL dispose() override; + virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override; + virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override; + + // XSeekable + virtual void SAL_CALL seek( sal_Int64 location ) override; + virtual sal_Int64 SAL_CALL getPosition() override; + virtual sal_Int64 SAL_CALL getLength() override; + + // XInputStream + virtual sal_Int32 SAL_CALL readBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) override; + virtual sal_Int32 SAL_CALL readSomeBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) override; + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override; + virtual sal_Int32 SAL_CALL available( ) override; + virtual void SAL_CALL closeInput( ) override; + + // XOutputStream + virtual void SAL_CALL writeBytes( const css::uno::Sequence< sal_Int8 >& aData ) override; + virtual void SAL_CALL flush( ) override; + virtual void SAL_CALL closeOutput( ) override; + + // XTruncate + virtual void SAL_CALL truncate() override; + + // XAsyncOutputMonitor + virtual void SAL_CALL waitForCompletion( ) override; + +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |