summaryrefslogtreecommitdiff
path: root/ucb
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2004-04-14 12:43:44 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2004-04-14 12:43:44 +0000
commitbc83e607beae4444a2e8a476869b79df2b3767be (patch)
tree09de88ff8075d5510a6d479de06acfb3c7cca1f2 /ucb
parent5665711656d976be60a48d8e197b4d98a0c20175 (diff)
INTEGRATION: CWS unopkg1 (1.1.2); FILE ADDED
2004/03/23 09:51:15 kso 1.1.2.5: #112920# - Cloning on error during openStorageElement. - Code cleanup. Issue number: Submitted by: Reviewed by: 2004/03/03 15:20:25 kso 1.1.2.4: #112920# - Adapted to css.embed.XStorage interface changes. Issue number: Submitted by: Reviewed by: 2004/02/23 15:59:50 kso 1.1.2.3: #112920# - Added support for encrypted streams. Issue number: Submitted by: Reviewed by: 2004/01/20 16:33:51 kso 1.1.2.2: #112920# - Fixed Solaris compile errors. Issue number: Submitted by: Reviewed by: 2004/01/20 15:19:42 kso 1.1.2.1: #112920# TDOC UCP: Initial revision.
Diffstat (limited to 'ucb')
-rw-r--r--ucb/source/ucp/tdoc/tdoc_storage.cxx1714
1 files changed, 1714 insertions, 0 deletions
diff --git a/ucb/source/ucp/tdoc/tdoc_storage.cxx b/ucb/source/ucp/tdoc/tdoc_storage.cxx
new file mode 100644
index 000000000000..efddc4a0e30f
--- /dev/null
+++ b/ucb/source/ucp/tdoc/tdoc_storage.cxx
@@ -0,0 +1,1714 @@
+/*************************************************************************
+ *
+ * $RCSfile: tdoc_storage.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: hr $ $Date: 2004-04-14 13:43:44 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (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.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Kai Sommerfeld ( kso@sun.com )
+ *
+ *
+ ************************************************************************/
+
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ *************************************************************************/
+
+#include <memory>
+
+#include "osl/mutex.hxx"
+
+#include "com/sun/star/beans/XPropertySet.hpp"
+#include "com/sun/star/embed/ElementModes.hpp"
+#include "com/sun/star/embed/XTransactedObject.hpp"
+#include "com/sun/star/io/IOException.hpp"
+#include "com/sun/star/lang/DisposedException.hpp"
+#include "com/sun/star/lang/XComponent.hpp"
+#include "com/sun/star/reflection/XProxyFactory.hpp"
+#include "com/sun/star/uno/XAggregation.hpp"
+
+#include "cppuhelper/implbase1.hxx"
+#include "cppuhelper/implbase2.hxx"
+
+#include "tdoc_uri.hxx"
+#include "tdoc_docmgr.hxx"
+
+#include "tdoc_storage.hxx"
+
+using namespace com::sun;
+using namespace com::sun::star;
+
+using namespace tdoc_ucp;
+
+namespace tdoc_ucp
+{
+ struct MutexHolder
+ {
+ osl::Mutex m_aMutex;
+ };
+
+ //=======================================================================
+
+ class ParentStorageHolder : public MutexHolder
+ {
+ public:
+ ParentStorageHolder(
+ const uno::Reference< embed::XStorage > & xParentStorage,
+ const rtl::OUString & rUri );
+
+ bool isRootParentStorage() const
+ { return m_bParentStorageIsRoot; }
+ uno::Reference< embed::XStorage > getParentStorage() const
+ { return m_xParentStorage; }
+ void setParentStorage( const uno::Reference< embed::XStorage > & xStg )
+ { osl::MutexGuard aGuard( m_aMutex ); m_xParentStorage = xStg; }
+
+ private:
+ uno::Reference< embed::XStorage > m_xParentStorage;
+ bool m_bParentStorageIsRoot;
+ };
+
+ //=======================================================================
+
+ typedef
+ cppu::WeakImplHelper2<
+ com::sun::star::embed::XStorage,
+ com::sun::star::embed::XTransactedObject > StorageUNOBase;
+
+ class Storage : public StorageUNOBase, public ParentStorageHolder
+ {
+ public:
+ Storage(
+ const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
+ const rtl::Reference< StorageElementFactory > & xFactory,
+ const rtl::OUString & rUri,
+ const uno::Reference< embed::XStorage > & xParentStorage,
+ const uno::Reference< embed::XStorage > & xStorageToWrap );
+ virtual ~Storage();
+
+ // XInterface
+ virtual uno::Any SAL_CALL queryInterface( const uno::Type& aType )
+ throw ( uno::RuntimeException );
+ virtual void SAL_CALL acquire()
+ throw ();
+ virtual void SAL_CALL release()
+ throw ();
+
+ // XStorage
+ virtual void SAL_CALL
+ copyToStorage( const uno::Reference< embed::XStorage >& xDest )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual uno::Reference< io::XStream > SAL_CALL
+ openStreamElement( const ::rtl::OUString& aStreamName,
+ sal_Int32 nOpenMode )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::WrongPasswordException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual uno::Reference< io::XStream > SAL_CALL
+ openEncryptedStreamElement( const ::rtl::OUString& aStreamName,
+ sal_Int32 nOpenMode,
+ const uno::Sequence< sal_Int8 >& aKey )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::NoEncryptionException,
+ packages::WrongPasswordException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual uno::Reference< embed::XStorage > SAL_CALL
+ openStorageElement( const ::rtl::OUString& aStorName,
+ sal_Int32 nOpenMode )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual uno::Reference< io::XStream > SAL_CALL
+ cloneStreamElement( const ::rtl::OUString& aStreamName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::WrongPasswordException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual uno::Reference< io::XStream > SAL_CALL
+ cloneEncryptedStreamElement( const ::rtl::OUString& aStreamName,
+ const uno::Sequence< sal_Int8 >& aKey )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::NoEncryptionException,
+ packages::WrongPasswordException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual uno::Reference< embed::XStorage > SAL_CALL
+ cloneStorageElement( const ::rtl::OUString& aStorName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual sal_Bool SAL_CALL
+ isStreamElement( const ::rtl::OUString& aElementName )
+ throw ( container::NoSuchElementException,
+ lang::IllegalArgumentException,
+ embed::InvalidStorageException,
+ uno::RuntimeException );
+ virtual sal_Bool SAL_CALL
+ isStorageElement( const ::rtl::OUString& aElementName )
+ throw ( container::NoSuchElementException,
+ lang::IllegalArgumentException,
+ embed::InvalidStorageException,
+ uno::RuntimeException );
+ virtual void SAL_CALL
+ removeElement( const ::rtl::OUString& aElementName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ container::NoSuchElementException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual void SAL_CALL
+ renameElement( const ::rtl::OUString& aEleName,
+ const ::rtl::OUString& aNewName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ container::NoSuchElementException,
+ container::ElementExistException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual void SAL_CALL
+ copyElementTo( const ::rtl::OUString& aElementName,
+ const uno::Reference< embed::XStorage >& xDest,
+ const ::rtl::OUString& aNewName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ container::NoSuchElementException,
+ container::ElementExistException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual void SAL_CALL
+ moveElementTo( const ::rtl::OUString& aElementName,
+ const uno::Reference< embed::XStorage >& xDest,
+ const ::rtl::OUString& rNewName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ container::NoSuchElementException,
+ container::ElementExistException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+ virtual void SAL_CALL
+ insertRawEncrStreamElement( const ::rtl::OUString& aStreamName,
+ const uno::Reference<
+ io::XInputStream >& xInStream )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::NoRawFormatException,
+ container::ElementExistException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException );
+
+ // XTransactedObject
+ virtual void SAL_CALL commit()
+ throw ( io::IOException,
+ lang::WrappedTargetException,
+ uno::RuntimeException );
+ virtual void SAL_CALL revert()
+ throw ( io::IOException,
+ lang::WrappedTargetException,
+ uno::RuntimeException );
+
+ private:
+ Storage( const rtl::Reference< Storage > & rFactory ); // n.i.
+
+ // not done in ctor to avoid refcounting problems.
+ void setDelegator();
+
+ rtl::Reference< StorageElementFactory > m_xFactory;
+ uno::Reference< embed::XStorage > m_xWrappedStorage;
+ uno::Reference< uno::XAggregation > m_xWrappedAggregate;
+ bool m_bDelegatorSet;
+ StorageElementFactory::StorageMap::iterator m_aContainerIt;
+
+ friend class StorageElementFactory;
+ friend class std::auto_ptr< Storage >;
+ };
+
+ //=======================================================================
+
+ typedef
+ cppu::WeakImplHelper1<
+ com::sun::star::io::XInputStream > InputStreamUNOBase;
+
+ class InputStream : public InputStreamUNOBase, public ParentStorageHolder
+ {
+ public:
+ InputStream(
+ const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
+ const rtl::OUString & rUri,
+ const uno::Reference< embed::XStorage > & xParentStorage,
+ const uno::Reference< io::XInputStream > & xStreamToWrap );
+ virtual ~InputStream();
+
+ // XInterface
+ virtual uno::Any SAL_CALL queryInterface( const uno::Type& aType )
+ throw ( uno::RuntimeException );
+
+ // XInputStream
+ virtual sal_Int32 SAL_CALL
+ readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException );
+ virtual sal_Int32 SAL_CALL
+ readSomeBytes( uno::Sequence< sal_Int8 >& aData,
+ sal_Int32 nMaxBytesToRead )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException );
+ virtual void SAL_CALL
+ skipBytes( sal_Int32 nBytesToSkip )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException );
+ virtual sal_Int32 SAL_CALL
+ available()
+ throw ( io::NotConnectedException,
+ io::IOException,
+ uno::RuntimeException );
+ // Note: We need to intercept this one.
+ virtual void SAL_CALL
+ closeInput()
+ throw ( io::NotConnectedException,
+ io::IOException,
+ uno::RuntimeException );
+ private:
+ uno::Reference< io::XInputStream > m_xWrappedStream;
+ uno::Reference< uno::XAggregation > m_xWrappedAggregate;
+ };
+
+ //=======================================================================
+
+ typedef
+ cppu::WeakImplHelper1<
+ com::sun::star::io::XOutputStream > OutputStreamUNOBase;
+
+ class OutputStream : public OutputStreamUNOBase, public ParentStorageHolder
+ {
+ public:
+ OutputStream(
+ const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
+ const rtl::OUString & rUri,
+ const uno::Reference< embed::XStorage > & xParentStorage,
+ const uno::Reference< io::XOutputStream > & xStreamToWrap );
+ virtual ~OutputStream();
+
+ // XInterface
+ virtual uno::Any SAL_CALL queryInterface( const uno::Type& aType )
+ throw ( uno::RuntimeException );
+
+ // XOutputStream
+ virtual void SAL_CALL
+ writeBytes( const uno::Sequence< sal_Int8 >& aData )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException );
+ virtual void SAL_CALL
+ flush( )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException );
+ // Note: We need to intercept this one.
+ virtual void SAL_CALL
+ closeOutput( )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException );
+ private:
+ uno::Reference< io::XOutputStream > m_xWrappedStream;
+ uno::Reference< uno::XAggregation > m_xWrappedAggregate;
+ };
+
+} // namespace tdoc_ucp
+
+//=========================================================================
+//=========================================================================
+//
+// StorageElementFactory Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+StorageElementFactory::StorageElementFactory(
+ const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
+ const rtl::Reference< OfficeDocumentsManager > & xDocsMgr )
+: m_xDocsMgr( xDocsMgr ),
+ m_xSMgr( xSMgr )
+{
+}
+
+//=========================================================================
+StorageElementFactory::~StorageElementFactory()
+{
+ OSL_ENSURE( m_aMap.size() == 0,
+ "StorageElementFactory::~StorageElementFactory - Dangling storages!" );
+}
+
+//=========================================================================
+uno::Reference< embed::XStorage >
+StorageElementFactory::createStorage( const rtl::OUString & rUri,
+ StorageAccessMode eMode )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( ( eMode != READ ) &&
+ ( eMode != READ_ONLY ) &&
+ ( eMode != READ_WRITE_NOCREATE ) &&
+ ( eMode != READ_WRITE_CREATE ) )
+ throw lang::IllegalArgumentException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Invalid open mode!" ) ),
+ uno::Reference< uno::XInterface >(),
+ sal_Int16( 2 ) );
+
+ Uri aUri( rUri );
+ if ( aUri.isRoot() )
+ {
+ throw lang::IllegalArgumentException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Root never has a storage!" ) ),
+ uno::Reference< uno::XInterface >(),
+ sal_Int16( 1 ) );
+ }
+
+ rtl::OUString aUriKey
+ ( ( rUri.getStr()[ rUri.getLength() - 1 ] == sal_Unicode( '/' ) )
+ ? rUri.copy( 0, rUri.getLength() - 1 )
+ : rUri );
+
+ StorageMap::iterator aIt ( m_aMap.begin() );
+ StorageMap::iterator aEnd( m_aMap.end() );
+
+ while ( aIt != aEnd )
+ {
+ if ( (*aIt).first.first == aUriKey )
+ {
+ // URI matches. Now, check open mode.
+ bool bMatch = true;
+ switch ( eMode )
+ {
+ case READ:
+ // No need to check; storage is at least readable.
+ bMatch = true;
+ break;
+
+ case READ_ONLY:
+ // If found storage is writable, it cannot be used.
+ bMatch = !(*aIt).first.second;
+ break;
+
+ case READ_WRITE_NOCREATE:
+ case READ_WRITE_CREATE:
+ // If found storage is writable, it can be used.
+ // If not, a new one must be created.
+ bMatch = (*aIt).first.second;
+ break;
+ }
+
+ if ( bMatch )
+ break;
+ }
+ ++aIt;
+ }
+
+ if ( aIt == aEnd )
+ {
+ uno::Reference< embed::XStorage > xParentStorage;
+
+ // documents never have a parent storage.
+ if ( !aUri.isDocument() )
+ {
+ xParentStorage = queryParentStorage( aUriKey, eMode );
+
+ if ( !xParentStorage.is() )
+ {
+ // requested to create new storage, but failed?
+ OSL_ENSURE( eMode != READ_WRITE_CREATE,
+ "Unable to create parent storage!" );
+ return xParentStorage;
+ }
+ }
+
+ uno::Reference< embed::XStorage > xStorage
+ = queryStorage( xParentStorage, aUriKey, eMode );
+
+ if ( !xStorage.is() )
+ {
+ // requested to create new storage, but failed?
+ OSL_ENSURE( eMode != READ_WRITE_CREATE,
+ "Unable to create storage!" );
+ return xStorage;
+ }
+
+ std::auto_ptr< Storage > xElement(
+ new Storage( m_xSMgr, this, aUriKey, xParentStorage, xStorage ) );
+
+ bool bWritable = ( ( eMode == READ_WRITE_NOCREATE )
+ || ( eMode == READ_WRITE_CREATE ) );
+
+ aIt = m_aMap.insert(
+ StorageMap::value_type(
+ std::pair< rtl::OUString, bool >( aUriKey, bWritable ),
+ xElement.get() ) ).first;
+
+ aIt->second->m_aContainerIt = aIt;
+ xElement.release();
+ return aIt->second;
+ }
+ else if ( osl_incrementInterlockedCount( &aIt->second->m_refCount ) > 1 )
+ {
+ rtl::Reference< Storage > xElement( aIt->second );
+ osl_decrementInterlockedCount( &aIt->second->m_refCount );
+ return aIt->second;
+ }
+ else
+ {
+ osl_decrementInterlockedCount( &aIt->second->m_refCount );
+ aIt->second->m_aContainerIt = m_aMap.end();
+
+ uno::Reference< embed::XStorage > xParentStorage;
+
+ // documents never have a parent storage.
+ if ( !aUri.isDocument() )
+ {
+ xParentStorage = queryParentStorage( aUriKey, eMode );
+
+ if ( !xParentStorage.is() )
+ {
+ // requested to create new storage, but failed?
+ OSL_ENSURE( eMode != READ_WRITE_CREATE,
+ "Unable to create parent storage!" );
+ return xParentStorage;
+ }
+ }
+
+ uno::Reference< embed::XStorage > xStorage
+ = queryStorage( xParentStorage, aUriKey, eMode );
+
+ if ( !xStorage.is() )
+ {
+ // requested to create new storage, but failed?
+ OSL_ENSURE( eMode != READ_WRITE_CREATE,
+ "Unable to create storage!" );
+ return xStorage;
+ }
+
+ aIt->second
+ = new Storage( m_xSMgr, this, aUriKey, xParentStorage, xStorage );
+ aIt->second->m_aContainerIt = aIt;
+ return aIt->second;
+ }
+}
+
+//=========================================================================
+uno::Reference< io::XInputStream >
+StorageElementFactory::createInputStream( const rtl::OUString & rUri,
+ const rtl::OUString & rPassword )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ packages::WrongPasswordException,
+ uno::RuntimeException )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ uno::Reference< embed::XStorage > xParentStorage
+ = queryParentStorage( rUri, READ );
+
+ // Each stream must have a parent storage.
+ if ( !xParentStorage.is() )
+ return uno::Reference< io::XInputStream >();
+
+ uno::Reference< io::XStream > xStream
+ = queryStream( xParentStorage, rUri, rPassword, READ );
+
+ if ( !xStream.is() )
+ return uno::Reference< io::XInputStream >();
+
+ return uno::Reference< io::XInputStream >(
+ new InputStream(
+ m_xSMgr, rUri, xParentStorage, xStream->getInputStream() ) );
+}
+
+//=========================================================================
+uno::Reference< io::XOutputStream >
+StorageElementFactory::createOutputStream( const rtl::OUString & rUri,
+ const rtl::OUString & rPassword )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ packages::WrongPasswordException,
+ uno::RuntimeException )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ uno::Reference< embed::XStorage > xParentStorage
+ = queryParentStorage( rUri, READ_WRITE_CREATE );
+
+ // Each stream must have a parent storage.
+ if ( !xParentStorage.is() )
+ {
+ OSL_ENSURE( false,
+ "StorageElementFactory::createOutputStream - "
+ "Unable to create parent storage!" );
+ return uno::Reference< io::XOutputStream >();
+ }
+
+ uno::Reference< io::XStream > xStream
+ = queryStream( xParentStorage, rUri, rPassword, READ_WRITE_CREATE );
+
+ if ( !xStream.is() )
+ {
+ OSL_ENSURE( false,
+ "StorageElementFactory::createOutputStream - "
+ "Unable to create stream!" );
+ return uno::Reference< io::XOutputStream >();
+ }
+
+ return uno::Reference< io::XOutputStream >(
+ new OutputStream(
+ m_xSMgr, rUri, xParentStorage, xStream->getOutputStream() ) );
+}
+
+//=========================================================================
+void StorageElementFactory::releaseElement( Storage * pElement ) SAL_THROW( () )
+{
+ OSL_ASSERT( pElement );
+ osl::MutexGuard aGuard( m_aMutex );
+ if ( pElement->m_aContainerIt != m_aMap.end() )
+ m_aMap.erase( pElement->m_aContainerIt );
+}
+
+//=========================================================================
+//
+// Non-UNO interface
+//
+//=========================================================================
+
+uno::Reference< embed::XStorage > StorageElementFactory::queryParentStorage(
+ const rtl::OUString & rUri, StorageAccessMode eMode )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ uno::Reference< embed::XStorage > xParentStorage;
+
+ Uri aUri( rUri );
+ Uri aParentUri( aUri.getParentUri() );
+ if ( !aParentUri.isRoot() )
+ {
+ xParentStorage = createStorage( aUri.getParentUri(), eMode );
+ OSL_ENSURE( xParentStorage.is()
+ // requested to create new storage, but failed?
+ || ( eMode != READ_WRITE_CREATE ),
+ "StorageElementFactory::queryParentStorage - No storage!" );
+ }
+ return xParentStorage;
+}
+
+//=========================================================================
+uno::Reference< embed::XStorage > StorageElementFactory::queryStorage(
+ const uno::Reference< embed::XStorage > & xParentStorage,
+ const rtl::OUString & rUri,
+ StorageAccessMode eMode )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ uno::Reference< embed::XStorage > xStorage;
+
+ Uri aUri( rUri );
+
+ if ( !xParentStorage.is() )
+ {
+ // document storage
+
+ xStorage = m_xDocsMgr->queryStorage( aUri.getDocumentId() );
+
+ if ( !xStorage.is() )
+ {
+ if ( eMode == READ_WRITE_CREATE )
+ throw lang::IllegalArgumentException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Invalid open mode: document storages cannot be "
+ "created!" ) ),
+ uno::Reference< uno::XInterface >(),
+ sal_Int16( 2 ) );
+ else
+ throw embed::InvalidStorageException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Invalid document id!" ) ),
+ uno::Reference< uno::XInterface >() );
+ }
+
+ // match xStorage's open mode against requested open mode
+
+ uno::Reference< beans::XPropertySet > xPropSet(
+ xStorage, uno::UNO_QUERY );
+ OSL_ENSURE( xPropSet.is(),
+ "StorageElementFactory::queryStorage - "
+ "No XPropertySet interface!" );
+ try
+ {
+ uno::Any aPropValue = xPropSet->getPropertyValue(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ) ) );
+
+ sal_Int32 nOpenMode;
+ if ( aPropValue >>= nOpenMode )
+ {
+ switch ( eMode )
+ {
+ case READ:
+ if ( !( nOpenMode
+ & embed::ElementModes::ELEMENT_READ ) )
+ {
+ // document opened, but not readable.
+ throw embed::InvalidStorageException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Storage is open, but not readable!" ) ),
+ uno::Reference< uno::XInterface >() );
+ }
+ // storage okay
+ break;
+
+ case READ_ONLY:
+ if ( nOpenMode & embed::ElementModes::ELEMENT_WRITE )
+ {
+ // document opened, but it's writable.
+ throw embed::InvalidStorageException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Storage is open, but writable!" ) ),
+ uno::Reference< uno::XInterface >() );
+ }
+ // storage okay
+ break;
+
+ case READ_WRITE_NOCREATE:
+ case READ_WRITE_CREATE:
+ if ( !( nOpenMode
+ & embed::ElementModes::ELEMENT_WRITE ) )
+ {
+ // document opened, but not writable.
+ throw embed::InvalidStorageException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Storage is open, but not writable!" ) ),
+ uno::Reference< uno::XInterface >() );
+ }
+ // storage okay
+ break;
+ }
+ }
+ else
+ {
+ OSL_ENSURE(
+ false, "Bug! Value of property OpenMode has wrong type!" );
+
+ throw uno::RuntimeException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Bug! Value of property OpenMode has wrong type!" ) ),
+ uno::Reference< uno::XInterface >() );
+ }
+ }
+ catch ( beans::UnknownPropertyException const & e )
+ {
+ OSL_ENSURE( false, "Property OpenMode not supported!" );
+
+ throw embed::StorageWTException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Bug! Value of property OpenMode has wrong type!" ) ),
+ uno::Reference< uno::XInterface >(),
+ uno::makeAny( e ) );
+ }
+ catch ( lang::WrappedTargetException const & e )
+ {
+ OSL_ENSURE( false, "Caught WrappedTargetException!" );
+
+ throw embed::StorageWTException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "WrappedTargetException during getPropertyValue!" ) ),
+ uno::Reference< uno::XInterface >(),
+ uno::makeAny( e ) );
+ }
+ }
+ else
+ {
+ // sub storage
+
+ sal_Int32 nOpenMode;
+ switch ( eMode )
+ {
+ case READ:
+ case READ_ONLY:
+ nOpenMode = embed::ElementModes::ELEMENT_READ
+ | embed::ElementModes::ELEMENT_NOCREATE;
+ break;
+
+ case READ_WRITE_NOCREATE:
+ nOpenMode = embed::ElementModes::ELEMENT_READWRITE
+ | embed::ElementModes::ELEMENT_NOCREATE;
+ break;
+
+ case READ_WRITE_CREATE:
+ nOpenMode = embed::ElementModes::ELEMENT_READWRITE;
+ break;
+ }
+
+ const rtl::OUString & rName = aUri.getDecodedName();
+ try
+ {
+ xStorage = xParentStorage->openStorageElement( rName, nOpenMode );
+ }
+ catch ( io::IOException const & )
+ {
+ if ( ( eMode == READ ) || ( eMode == READ_ONLY ) )
+ {
+ // Distinguish between 'not existing' and 'access denied'
+ // (somebody else already opened storage for writing?) and
+ // "existing, but stream".
+
+ bool bAccessDenied = true;
+ try
+ {
+ // true: element exists and is a storage, but access is
+ // denied false: element exists, but is a stream
+ bAccessDenied = xParentStorage->isStorageElement( rName );
+ }
+ catch ( container::NoSuchElementException const & )
+ {
+ // element does not exist
+ bAccessDenied = false;
+ }
+
+ if ( bAccessDenied )
+ {
+ // Clone
+ xStorage = xParentStorage->cloneStorageElement( rName );
+ }
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+
+ OSL_ENSURE( xStorage.is() || ( eMode != READ_WRITE_CREATE ),
+ "StorageElementFactory::queryStorage - No storage!" );
+ return xStorage;
+}
+
+//=========================================================================
+uno::Reference< io::XStream >
+StorageElementFactory::queryStream(
+ const uno::Reference< embed::XStorage > & xParentStorage,
+ const rtl::OUString & rUri,
+ const rtl::OUString & rPassword,
+ StorageAccessMode eMode )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ packages::WrongPasswordException,
+ uno::RuntimeException )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !xParentStorage.is() )
+ {
+ throw lang::IllegalArgumentException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "No parent storage!" ) ),
+ uno::Reference< uno::XInterface >(),
+ sal_Int16( 2 ) );
+ }
+
+ Uri aUri( rUri );
+ if ( aUri.isRoot() )
+ {
+ throw lang::IllegalArgumentException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Root never is a stream!" ) ),
+ uno::Reference< uno::XInterface >(),
+ sal_Int16( 2 ) );
+ }
+ else if ( aUri.isDocument() )
+ {
+ throw lang::IllegalArgumentException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "A document never is a stream!" ) ),
+ uno::Reference< uno::XInterface >(),
+ sal_Int16( 2 ) );
+ }
+
+ // @@@ Sophisticated object reusage (like for storages) needed???
+
+ sal_Int32 nOpenMode;
+ switch ( eMode )
+ {
+ case READ:
+ case READ_ONLY:
+ nOpenMode = embed::ElementModes::ELEMENT_READ
+ | embed::ElementModes::ELEMENT_NOCREATE;
+ break;
+
+ case READ_WRITE_NOCREATE:
+ nOpenMode = embed::ElementModes::ELEMENT_READWRITE
+ | embed::ElementModes::ELEMENT_NOCREATE;
+ break;
+
+ case READ_WRITE_CREATE:
+ nOpenMode = embed::ElementModes::ELEMENT_READWRITE;
+ break;
+ }
+
+ uno::Reference< io::XStream > xStream;
+ if ( rPassword.getLength() > 0 )
+ {
+ try
+ {
+ rtl::OString aByteString(
+ rtl::OUStringToOString( rPassword, RTL_TEXTENCODING_MS_1252 ) );
+ uno::Sequence< sal_Int8 > aKey(
+ reinterpret_cast< const sal_Int8 *>( aByteString.getStr() ),
+ aByteString.getLength() );
+ xStream = xParentStorage->openEncryptedStreamElement(
+ aUri.getDecodedName(),
+ nOpenMode,
+ aKey );
+ }
+ catch ( packages::NoEncryptionException const & )
+ {
+ xStream = xParentStorage->openStreamElement( aUri.getDecodedName(),
+ nOpenMode );
+ }
+ }
+ else
+ {
+ xStream = xParentStorage->openStreamElement( aUri.getDecodedName(),
+ nOpenMode );
+ }
+
+ if ( !xStream.is() )
+ {
+ throw embed::InvalidStorageException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "No stream!" ) ),
+ uno::Reference< uno::XInterface >() );
+ }
+
+ return xStream;
+}
+
+//=========================================================================
+//=========================================================================
+//
+// ParentStorageHolder Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+ParentStorageHolder::ParentStorageHolder(
+ const uno::Reference< embed::XStorage > & xParentStorage,
+ const rtl::OUString & rUri )
+: m_xParentStorage( xParentStorage ),
+ m_bParentStorageIsRoot( false )
+{
+ Uri aUri( rUri );
+ if ( aUri.isDocument() ) // This correct; aUri.isRoot() is not!
+ m_bParentStorageIsRoot = true;
+}
+
+//=========================================================================
+//=========================================================================
+//
+// Storage Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+Storage::Storage( const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
+ const rtl::Reference< StorageElementFactory > & xFactory,
+ const rtl::OUString & rUri,
+ const uno::Reference< embed::XStorage > & xParentStorage,
+ const uno::Reference< embed::XStorage > & xStorageToWrap )
+: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ),
+ m_xFactory( xFactory ),
+ m_xWrappedStorage( xStorageToWrap ),
+ m_bDelegatorSet( false )
+{
+ OSL_ENSURE( m_xWrappedStorage.is(),
+ "Storage::Storage: No storage to wrap!" );
+
+ // Use proxy factory service to create aggregatable proxy.
+ try
+ {
+ uno::Reference< reflection::XProxyFactory > xProxyFac(
+ xSMgr->createInstance(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.reflection.ProxyFactory" ) ) ),
+ uno::UNO_QUERY );
+ if ( xProxyFac.is() )
+ {
+ m_xWrappedAggregate
+ = xProxyFac->createProxy( m_xWrappedStorage );
+ m_xWrappedStorage
+ = uno::Reference< embed::XStorage >(
+ m_xWrappedAggregate, uno::UNO_QUERY );
+ }
+ }
+ catch ( uno::Exception const & )
+ {
+ OSL_ENSURE( false, "Storage::Storage: Caught exception!" );
+ }
+
+ OSL_ENSURE( m_xWrappedAggregate.is(),
+ "Storage::Storage: Wrapped storage cannot be aggregated!" );
+}
+
+//=========================================================================
+// virtual
+Storage::~Storage()
+{
+ if ( m_xWrappedAggregate.is() )
+ m_xWrappedAggregate->setDelegator(
+ uno::Reference< uno::XInterface >() );
+
+ if ( m_xWrappedStorage.is() )
+ {
+ // "Auto-dispose"...
+ uno::Reference< lang::XComponent >
+ xC( m_xWrappedStorage, uno::UNO_QUERY );
+ OSL_ENSURE ( xC.is(), "Required interface XComponent missing!" );
+
+ try
+ {
+ xC->dispose();
+ }
+ catch ( lang::DisposedException const & )
+ {
+ // might happen.
+ }
+ catch ( ... )
+ {
+ OSL_ENSURE( false, "Storage::~Storage - Caught exception!" );
+ }
+ }
+}
+
+//=========================================================================
+void Storage::setDelegator()
+{
+ if ( !m_bDelegatorSet )
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+ if ( !m_bDelegatorSet )
+ {
+ m_xWrappedAggregate->setDelegator(
+ static_cast< cppu::OWeakObject * >( this ) );
+ m_bDelegatorSet = true;
+ }
+ }
+}
+
+//=========================================================================
+//
+// uno::XInterface
+//
+//=========================================================================
+
+// virtual
+uno::Any SAL_CALL Storage::queryInterface( const uno::Type& aType )
+ throw ( uno::RuntimeException)
+{
+ // First, try to use interfaces implemented by myself and base class(es)
+ uno::Any aRet = StorageUNOBase::queryInterface( aType );
+
+ if ( aRet.hasValue() )
+ return aRet;
+
+ // Late init: Set this as delegator for wrapped storage.
+ setDelegator();
+
+ // Try to use requested interface from aggregated storage
+ return m_xWrappedAggregate->queryAggregation( aType );
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Storage::acquire()
+ throw ()
+{
+ osl_incrementInterlockedCount( &m_refCount );
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Storage::release()
+ throw ()
+{
+ if ( osl_decrementInterlockedCount( &m_refCount ) == 0 )
+ {
+ m_xFactory->releaseElement( this );
+ delete this;
+ }
+}
+
+//=========================================================================
+//
+// embed::XStorage
+//
+//=========================================================================
+
+// virtual
+void SAL_CALL Storage::copyToStorage(
+ const uno::Reference< embed::XStorage >& xDest )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ m_xWrappedStorage->copyToStorage( xDest );
+}
+
+//=========================================================================
+// virtual
+uno::Reference< io::XStream > SAL_CALL Storage::openStreamElement(
+ const ::rtl::OUString& aStreamName, sal_Int32 nOpenMode )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::WrongPasswordException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStorage->openStreamElement( aStreamName, nOpenMode );
+}
+
+//=========================================================================
+// virtual
+uno::Reference< io::XStream > SAL_CALL Storage::openEncryptedStreamElement(
+ const ::rtl::OUString& aStreamName,
+ sal_Int32 nOpenMode,
+ const uno::Sequence< sal_Int8 >& aKey )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::NoEncryptionException,
+ packages::WrongPasswordException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStorage->openEncryptedStreamElement(
+ aStreamName, nOpenMode, aKey );
+}
+
+//=========================================================================
+// virtual
+uno::Reference< embed::XStorage > SAL_CALL Storage::openStorageElement(
+ const ::rtl::OUString& aStorName, sal_Int32 nOpenMode )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStorage->openStorageElement( aStorName, nOpenMode );
+}
+
+//=========================================================================
+// virtual
+uno::Reference< io::XStream > SAL_CALL Storage::cloneStreamElement(
+ const ::rtl::OUString& aStreamName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::WrongPasswordException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStorage->cloneStreamElement( aStreamName );
+}
+
+//=========================================================================
+// virtual
+uno::Reference< io::XStream > SAL_CALL Storage::cloneEncryptedStreamElement(
+ const ::rtl::OUString& aStreamName,
+ const uno::Sequence< sal_Int8 >& aKey )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::NoEncryptionException,
+ packages::WrongPasswordException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStorage->cloneEncryptedStreamElement( aStreamName, aKey );
+}
+
+//=========================================================================
+// virtual
+uno::Reference< embed::XStorage > SAL_CALL Storage::cloneStorageElement(
+ const ::rtl::OUString& aStorName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStorage->cloneStorageElement( aStorName );
+}
+
+//=========================================================================
+// virtual
+sal_Bool SAL_CALL Storage::isStreamElement(
+ const ::rtl::OUString& aElementName )
+ throw ( container::NoSuchElementException,
+ lang::IllegalArgumentException,
+ embed::InvalidStorageException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStorage->isStreamElement( aElementName );
+}
+
+//=========================================================================
+// virtual
+sal_Bool SAL_CALL Storage::isStorageElement(
+ const ::rtl::OUString& aElementName )
+ throw ( container::NoSuchElementException,
+ lang::IllegalArgumentException,
+ embed::InvalidStorageException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStorage->isStorageElement( aElementName );
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Storage::removeElement( const ::rtl::OUString& aElementName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ container::NoSuchElementException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ m_xWrappedStorage->removeElement( aElementName );
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Storage::renameElement( const ::rtl::OUString& aEleName,
+ const ::rtl::OUString& aNewName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ container::NoSuchElementException,
+ container::ElementExistException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ m_xWrappedStorage->renameElement( aEleName, aNewName );
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Storage::copyElementTo(
+ const ::rtl::OUString& aElementName,
+ const uno::Reference< embed::XStorage >& xDest,
+ const ::rtl::OUString& aNewName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ container::NoSuchElementException,
+ container::ElementExistException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ m_xWrappedStorage->copyElementTo( aElementName, xDest, aNewName );
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Storage::moveElementTo(
+ const ::rtl::OUString& aElementName,
+ const uno::Reference< embed::XStorage >& xDest,
+ const ::rtl::OUString& rNewName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ container::NoSuchElementException,
+ container::ElementExistException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ m_xWrappedStorage->moveElementTo( aElementName, xDest, rNewName );
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Storage::insertRawEncrStreamElement(
+ const ::rtl::OUString& aStreamName,
+ const uno::Reference< io::XInputStream >& xInStream )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::NoRawFormatException,
+ container::ElementExistException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ m_xWrappedStorage->insertRawEncrStreamElement( aStreamName, xInStream );
+}
+
+//=========================================================================
+//
+// embed::XTransactedObject
+//
+//=========================================================================
+
+// virtual
+void SAL_CALL Storage::commit()
+ throw ( io::IOException,
+ lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ // Never commit a root storage (-> has no parent)!
+ // Would lead in writing the whole document to disk.
+
+ uno::Reference< embed::XStorage > xParentStorage = getParentStorage();
+ if ( xParentStorage.is() )
+ {
+ // Important: don't use 'normal' queryInterface-based ctor here
+ // to obtain XTransactedObject reference. wrapped storage is aggregated.
+ // qI call will lead to Storage::qI, which returns 'this' -> endless
+ // recursion!!!
+ uno::Reference< embed::XTransactedObject > xTA(
+ m_xWrappedAggregate->queryAggregation(
+ getCppuType( static_cast<
+ const uno::Reference<
+ embed::XTransactedObject > * >( 0 ) ) ),
+ uno::UNO_QUERY );
+ OSL_ENSURE( xTA.is(), "No XTransactedObject interface!" );
+
+ if ( xTA.is() )
+ xTA->commit();
+
+ if ( !isRootParentStorage() )
+ {
+ uno::Reference< embed::XTransactedObject > xParentTA(
+ xParentStorage, uno::UNO_QUERY );
+ OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" );
+
+ if ( xParentTA.is() )
+ xParentTA->commit();
+ }
+ }
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Storage::revert()
+ throw ( io::IOException,
+ lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ uno::Reference< embed::XStorage > xParentStorage = getParentStorage();
+ if ( xParentStorage.is() )
+ {
+ // Important: don't use 'normal' queryInterface-based ctor here
+ // to obtain XTransactedObject reference. wrapped storage is aggregated.
+ // qI call will lead to Storage::qI, which returns 'this' -> endless
+ // recursion!!!
+ uno::Reference< embed::XTransactedObject > xTA(
+ m_xWrappedAggregate->queryAggregation(
+ getCppuType( static_cast<
+ const uno::Reference<
+ embed::XTransactedObject > * >( 0 ) ) ),
+ uno::UNO_QUERY );
+ OSL_ENSURE( xTA.is(), "No XTransactedObject interface!" );
+
+ if ( xTA.is() )
+ xTA->revert();
+
+ if ( !isRootParentStorage() )
+ {
+ uno::Reference< embed::XTransactedObject > xParentTA(
+ xParentStorage, uno::UNO_QUERY );
+ OSL_ENSURE( xParentTA.is(), "No XTransactedObject interface!" );
+
+ if ( xParentTA.is() )
+ xParentTA->revert();
+ }
+ }
+}
+
+//=========================================================================
+//=========================================================================
+//
+// InputStream Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+InputStream::InputStream(
+ const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
+ const rtl::OUString & rUri,
+ const uno::Reference< embed::XStorage > & xParentStorage,
+ const uno::Reference< io::XInputStream > & xStreamToWrap )
+: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ),
+ m_xWrappedStream( xStreamToWrap )
+{
+ OSL_ENSURE( m_xWrappedStream.is(),
+ "InputStream::InputStream: No stream to wrap!" );
+
+ // Use proxy factory service to create aggregatable proxy.
+ try
+ {
+ uno::Reference< reflection::XProxyFactory > xProxyFac(
+ xSMgr->createInstance(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.reflection.ProxyFactory" ) ) ),
+ uno::UNO_QUERY );
+ if ( xProxyFac.is() )
+ {
+ m_xWrappedAggregate
+ = xProxyFac->createProxy( m_xWrappedStream );
+ m_xWrappedStream
+ = uno::Reference< io::XInputStream >(
+ m_xWrappedAggregate, uno::UNO_QUERY );
+ }
+ }
+ catch ( uno::Exception const & )
+ {
+ OSL_ENSURE( false, "InputStream::InputStream: Caught exception!" );
+ }
+
+ OSL_ENSURE( m_xWrappedAggregate.is(),
+ "InputStream::InputStream: Wrapped stream cannot be aggregated!" );
+
+ if ( m_xWrappedAggregate.is() )
+ {
+ osl_incrementInterlockedCount( &m_refCount );
+ m_xWrappedAggregate->setDelegator(
+ static_cast< cppu::OWeakObject * >( this ) );
+ osl_decrementInterlockedCount( &m_refCount );
+ }
+}
+
+//=========================================================================
+// virtual
+InputStream::~InputStream()
+{
+ if ( m_xWrappedAggregate.is() )
+ m_xWrappedAggregate->setDelegator(
+ uno::Reference< uno::XInterface >() );
+}
+
+//=========================================================================
+//
+// uno::XInterface
+//
+//=========================================================================
+
+// virtual
+uno::Any SAL_CALL InputStream::queryInterface( const uno::Type& aType )
+ throw ( uno::RuntimeException)
+{
+ uno::Any aRet = InputStreamUNOBase::queryInterface( aType );
+
+ if ( aRet.hasValue() )
+ return aRet;
+
+ if ( m_xWrappedAggregate.is() )
+ return m_xWrappedAggregate->queryAggregation( aType );
+ else
+ return uno::Any();
+}
+
+//=========================================================================
+//
+// io::XInputStream
+//
+//=========================================================================
+
+// virtual
+sal_Int32 SAL_CALL
+InputStream::readBytes( uno::Sequence< sal_Int8 >& aData,
+ sal_Int32 nBytesToRead )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStream->readBytes( aData, nBytesToRead );
+}
+
+//=========================================================================
+// virtual
+sal_Int32 SAL_CALL
+InputStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData,
+ sal_Int32 nMaxBytesToRead )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStream->readSomeBytes( aData, nMaxBytesToRead );
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL
+InputStream::skipBytes( sal_Int32 nBytesToSkip )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ m_xWrappedStream->skipBytes( nBytesToSkip );
+}
+
+//=========================================================================
+// virtual
+sal_Int32 SAL_CALL
+InputStream::available()
+ throw ( io::NotConnectedException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ return m_xWrappedStream->available();
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL
+InputStream::closeInput()
+ throw ( io::NotConnectedException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ m_xWrappedStream->closeInput();
+
+ // Release parent storage.
+ // Now, that the stream is closed it is not needed any longer.
+ setParentStorage( uno::Reference< embed::XStorage >() );
+}
+
+//=========================================================================
+//=========================================================================
+//
+// OutputStream Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+OutputStream::OutputStream(
+ const uno::Reference< lang::XMultiServiceFactory > & xSMgr,
+ const rtl::OUString & rUri,
+ const uno::Reference< embed::XStorage > & xParentStorage,
+ const uno::Reference< io::XOutputStream > & xStreamToWrap )
+: ParentStorageHolder( xParentStorage, Uri( rUri ).getParentUri() ),
+ m_xWrappedStream( xStreamToWrap )
+{
+ OSL_ENSURE( m_xWrappedStream.is(),
+ "OutputStream::OutputStream: No stream to wrap!" );
+
+ // Use proxy factory service to create aggregatable proxy.
+ try
+ {
+ uno::Reference< reflection::XProxyFactory > xProxyFac(
+ xSMgr->createInstance(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.reflection.ProxyFactory" ) ) ),
+ uno::UNO_QUERY );
+ if ( xProxyFac.is() )
+ {
+ m_xWrappedAggregate
+ = xProxyFac->createProxy( m_xWrappedStream );
+ m_xWrappedStream
+ = uno::Reference< io::XOutputStream >(
+ m_xWrappedAggregate, uno::UNO_QUERY );
+ }
+ }
+ catch ( uno::Exception const & )
+ {
+ OSL_ENSURE( false, "OutputStream::OutputStream: Caught exception!" );
+ }
+
+ OSL_ENSURE( m_xWrappedAggregate.is(),
+ "OutputStream::OutputStream: Wrapped stream cannot be aggregated!" );
+
+ if ( m_xWrappedAggregate.is() )
+ {
+ osl_incrementInterlockedCount( &m_refCount );
+ m_xWrappedAggregate->setDelegator(
+ static_cast< cppu::OWeakObject * >( this ) );
+ osl_decrementInterlockedCount( &m_refCount );
+ }
+}
+
+//=========================================================================
+// virtual
+OutputStream::~OutputStream()
+{
+ if ( m_xWrappedAggregate.is() )
+ m_xWrappedAggregate->setDelegator(
+ uno::Reference< uno::XInterface >() );
+}
+
+//=========================================================================
+//
+// uno::XInterface
+//
+//=========================================================================
+
+// virtual
+uno::Any SAL_CALL OutputStream::queryInterface( const uno::Type& aType )
+ throw ( uno::RuntimeException)
+{
+ uno::Any aRet = OutputStreamUNOBase::queryInterface( aType );
+
+ if ( aRet.hasValue() )
+ return aRet;
+
+ if ( m_xWrappedAggregate.is() )
+ return m_xWrappedAggregate->queryAggregation( aType );
+ else
+ return uno::Any();
+}
+
+//=========================================================================
+//
+// io::XOutputStream
+//
+//=========================================================================
+
+// virtual
+void SAL_CALL
+OutputStream::writeBytes( const uno::Sequence< sal_Int8 >& aData )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ m_xWrappedStream->writeBytes( aData );
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL
+OutputStream::flush( )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ m_xWrappedStream->flush();
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL
+OutputStream::closeOutput( )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ m_xWrappedStream->closeOutput();
+
+ // Release parent storage.
+ // Now, that the stream is closed it is not needed any longer.
+ setParentStorage( uno::Reference< embed::XStorage >() );
+}