summaryrefslogtreecommitdiff
path: root/package/source
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2004-02-03 17:00:04 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2004-02-03 17:00:04 +0000
commitc670df16c4835c71b761c2b99ceae9c0f74698af (patch)
treecd1d4e6fa691660077c0db28dd7e073d7b4f6244 /package/source
parente4bf4dd29171efb81c14055972990eb1437ccb12 (diff)
INTEGRATION: CWS readstorage (1.3.10); FILE MERGED
2004/01/20 09:50:39 mav 1.3.10.4: #114521# if storage must be reopened the mode will be set on reopening 2004/01/15 17:57:55 mav 1.3.10.3: RESYNC: (1.3-1.5); FILE MERGED 2004/01/14 12:06:10 mav 1.3.10.2: #114521# multiple readonly access to substorages 2004/01/09 09:04:50 mav 1.3.10.1: #114521# cloning of storage's subelements
Diffstat (limited to 'package/source')
-rw-r--r--package/source/xstor/xstorage.cxx548
1 files changed, 478 insertions, 70 deletions
diff --git a/package/source/xstor/xstorage.cxx b/package/source/xstor/xstorage.cxx
index 2b8624d09e8a..a58f7047b4cd 100644
--- a/package/source/xstor/xstorage.cxx
+++ b/package/source/xstor/xstorage.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: xstorage.cxx,v $
*
- * $Revision: 1.5 $
+ * $Revision: 1.6 $
*
- * last change: $Author: rt $ $Date: 2004-01-06 08:46:41 $
+ * last change: $Author: hr $ $Date: 2004-02-03 18:00:04 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -96,6 +96,10 @@
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
+#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
+#include <com/sun/star/lang/XComponent.hpp>
+#endif
+
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
#include <com/sun/star/lang/DisposedException.hpp>
#endif
@@ -112,18 +116,48 @@
#include "xstorage.hxx"
#include "owriteablestream.hxx"
+#include "disposelistener.hxx"
#define STOR_MESS_PRECOMMIT 1
#define STOR_MESS_COMMITED 2
#define STOR_MESS_PREREVERT 3
#define STOR_MESS_REVERTED 4
+//=========================================================
+struct StorInternalData_Impl
+{
+ SotMutexHolderRef m_rSharedMutexRef;
+ ::cppu::OMultiTypeInterfaceContainerHelper m_aListenersContainer; // list of listeners
+ ::cppu::OTypeCollection* m_pTypeCollection;
+ sal_Bool m_bIsRoot;
+ sal_Bool m_bReadOnlyWrap;
+
+ OChildDispListener_Impl* m_pSubElDispListener;
+
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > >
+ m_aOpenSubComponentsList;
+
+ // the mutex reference MUST NOT be empty
+ StorInternalData_Impl( const SotMutexHolderRef& rMutexRef, sal_Bool bRoot, sal_Bool bReadOnlyWrap )
+ : m_rSharedMutexRef( rMutexRef )
+ , m_aListenersContainer( rMutexRef->GetMutex() )
+ , m_pTypeCollection( NULL )
+ , m_bIsRoot( bRoot )
+ , m_bReadOnlyWrap( bReadOnlyWrap )
+ , m_pSubElDispListener( NULL )
+ {}
+
+ ~StorInternalData_Impl();
+};
+//=========================================================
using namespace ::com::sun::star;
extern void copyInputToOutput_Impl( const uno::Reference< io::XInputStream >& aIn,
const uno::Reference< io::XOutputStream >& aOut );
+::rtl::OUString GetNewTempFileURL( const uno::Reference< lang::XMultiServiceFactory > xFactory );
+
void completeStorageStreamCopy_Impl( const uno::Reference< io::XStream >& xSource,
const uno::Reference< io::XStream >& xDest )
{
@@ -203,7 +237,7 @@ OStorage_Impl::OStorage_Impl( uno::Reference< io::XInputStream > xInputStream,
uno::Reference< lang::XMultiServiceFactory > xFactory )
: m_rMutexRef( new SotMutexHolder )
, m_pAntiImpl( NULL )
-, m_nStorageMode( nMode )
+, m_nStorageMode( nMode & ~embed::ElementModes::ELEMENT_SEEKABLE )
, m_bIsModified( sal_False )
, m_bCommited( sal_False )
, m_bIsRoot( sal_True )
@@ -232,7 +266,7 @@ OStorage_Impl::OStorage_Impl( uno::Reference< io::XStream > xStream,
uno::Reference< lang::XMultiServiceFactory > xFactory )
: m_rMutexRef( new SotMutexHolder )
, m_pAntiImpl( NULL )
-, m_nStorageMode( nMode )
+, m_nStorageMode( nMode & ~embed::ElementModes::ELEMENT_SEEKABLE )
, m_bIsModified( sal_False )
, m_bCommited( sal_False )
, m_bIsRoot( sal_True )
@@ -266,7 +300,7 @@ OStorage_Impl::OStorage_Impl( OStorage_Impl* pParent,
uno::Reference< lang::XMultiServiceFactory > xFactory )
: m_rMutexRef( new SotMutexHolder )
, m_pAntiImpl( NULL )
-, m_nStorageMode( nMode )
+, m_nStorageMode( nMode & ~embed::ElementModes::ELEMENT_SEEKABLE )
, m_bIsModified( sal_False )
, m_bCommited( sal_False )
, m_bIsRoot( sal_False )
@@ -274,11 +308,10 @@ OStorage_Impl::OStorage_Impl( OStorage_Impl* pParent,
, m_xPackageFolder( xPackageFolder )
, m_xPackage( xPackage )
, m_xFactory( xFactory )
-, m_pParent( pParent )
+, m_pParent( pParent ) // can be empty in case of temporary readonly substorages
, m_bControlMediaType( sal_False )
{
OSL_ENSURE( xPackageFolder.is(), "No package folder!\n" );
- OSL_ENSURE( pParent, "No parent is provided!\n" );
}
//-----------------------------------------------
@@ -291,12 +324,25 @@ OStorage_Impl::~OStorage_Impl()
OSL_ENSURE( !m_bIsRoot, "The root storage wrapper must be disposed already" );
try {
- m_pAntiImpl->dispose();
+ m_pAntiImpl->InternalDispose( sal_False );
}
catch ( uno::RuntimeException& )
{}
m_pAntiImpl = NULL;
}
+ else if ( !m_aReadOnlyWrapList.empty() )
+ {
+ for ( OStorageList_Impl::iterator pStorageIter = m_aReadOnlyWrapList.begin();
+ pStorageIter != m_aReadOnlyWrapList.end(); pStorageIter++ )
+ if ( *pStorageIter )
+ try {
+ (*pStorageIter)->InternalDispose( sal_False );
+ (*pStorageIter)->release();
+ (*pStorageIter) = NULL;
+ } catch( uno::Exception& ) {}
+
+ m_aReadOnlyWrapList.clear();
+ }
m_pParent = NULL;
}
@@ -344,6 +390,31 @@ OStorage_Impl::~OStorage_Impl()
}
//-----------------------------------------------
+void OStorage_Impl::SetReadOnlyWrap( OStorage& aStorage )
+{
+ aStorage.acquire();
+ m_aReadOnlyWrapList.push_back( &aStorage );
+}
+
+//-----------------------------------------------
+void OStorage_Impl::RemoveReadOnlyWrap( OStorage& aStorage )
+{
+ for ( OStorageList_Impl::iterator pStorageIter = m_aReadOnlyWrapList.begin();
+ pStorageIter != m_aReadOnlyWrapList.end(); pStorageIter++ )
+ if ( *pStorageIter == &aStorage )
+ {
+ try {
+ (*pStorageIter)->InternalDispose( sal_False );
+ } catch( uno::Exception& ) {}
+
+ (*pStorageIter)->release();
+ (*pStorageIter) = NULL;
+ }
+
+ m_aReadOnlyWrapList.remove( NULL );
+}
+
+//-----------------------------------------------
void OStorage_Impl::OpenOwnPackage()
{
OSL_ENSURE( m_bIsRoot, "Opening of the package has no sence!\n" );
@@ -511,7 +582,6 @@ void OStorage_Impl::CopyToStorage( const uno::Reference< embed::XStorage >& xDes
{
::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
-
uno::Reference< beans::XPropertySet > xPropSet( xDest, uno::UNO_QUERY );
if ( !xPropSet.is() )
throw lang::IllegalArgumentException(); // TODO:
@@ -629,6 +699,24 @@ void OStorage_Impl::CopyStorageElement( SotElement_Impl* pElement,
}
//-----------------------------------------------
+void OStorage_Impl::CopyLastCommitTo( const uno::Reference< embed::XStorage >& xNewStor )
+{
+ ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
+
+ OSL_ENSURE( m_xPackageFolder.is(), "A commited storage is incomplete!\n" );
+ if ( !m_xPackageFolder.is() )
+ throw uno::RuntimeException();
+
+ OStorage_Impl aTempRepresent( NULL,
+ embed::ElementModes::ELEMENT_READ,
+ m_xPackageFolder,
+ m_xPackage,
+ m_xFactory );
+
+ aTempRepresent.CopyToStorage( xNewStor );
+}
+
+//-----------------------------------------------
void OStorage_Impl::InsertIntoPackageFolder( const ::rtl::OUString& aName,
const uno::Reference< container::XNameContainer >& xParentPackageFolder )
{
@@ -893,6 +981,8 @@ void OStorage_Impl::SetModifiedInternally( sal_Bool bModified )
{
::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
+ OSL_ENSURE( m_aReadOnlyWrapList.empty(), "Opened for reading storage changes own modified state!\n" );
+
if ( m_pAntiImpl )
m_pAntiImpl->setModified( bModified );
else
@@ -1139,8 +1229,8 @@ void OStorage_Impl::RemoveElement( SotElement_Impl* pElement )
if ( !pElement )
return;
- if ( pElement->m_pStorage && pElement->m_pStorage->m_pAntiImpl
- || pElement->m_pStream && pElement->m_pStream->m_pAntiImpl )
+ if ( pElement->m_pStorage && ( pElement->m_pStorage->m_pAntiImpl || !pElement->m_pStorage->m_aReadOnlyWrapList.empty() )
+ || pElement->m_pStream && ( pElement->m_pStream->m_pAntiImpl || !pElement->m_pStream->m_aInputStreamsList.empty() ) )
throw io::IOException(); // TODO: Access denied
if ( pElement->m_bIsInserted )
@@ -1184,7 +1274,7 @@ OStorage::OStorage( uno::Reference< io::XInputStream > xInputStream,
: m_pImpl( new OStorage_Impl( xInputStream, nMode, xProperties, xFactory ) )
{
m_pImpl->m_pAntiImpl = this;
- m_pData = new StorInternalData_Impl( m_pImpl->m_rMutexRef, m_pImpl->m_bIsRoot );
+ m_pData = new StorInternalData_Impl( m_pImpl->m_rMutexRef, m_pImpl->m_bIsRoot, sal_False );
}
//-----------------------------------------------
@@ -1195,18 +1285,26 @@ OStorage::OStorage( uno::Reference< io::XStream > xStream,
: m_pImpl( new OStorage_Impl( xStream, nMode, xProperties, xFactory ) )
{
m_pImpl->m_pAntiImpl = this;
- m_pData = new StorInternalData_Impl( m_pImpl->m_rMutexRef, m_pImpl->m_bIsRoot );
+ m_pData = new StorInternalData_Impl( m_pImpl->m_rMutexRef, m_pImpl->m_bIsRoot, sal_False );
}
//-----------------------------------------------
-OStorage::OStorage( OStorage_Impl* pImpl )
+OStorage::OStorage( OStorage_Impl* pImpl, sal_Bool bReadOnlyWrap )
: m_pImpl( pImpl )
{
// this call can be done only from OStorage_Impl implementation to create child storage
OSL_ENSURE( m_pImpl && m_pImpl->m_rMutexRef.Is(), "The provided pointer & mutex MUST NOT be empty!\n" );
- m_pImpl->m_pAntiImpl = this;
- m_pData = new StorInternalData_Impl( m_pImpl->m_rMutexRef, m_pImpl->m_bIsRoot );
+ m_pData = new StorInternalData_Impl( m_pImpl->m_rMutexRef, m_pImpl->m_bIsRoot, bReadOnlyWrap );
+
+ OSL_ENSURE( ( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) == embed::ElementModes::ELEMENT_WRITE ||
+ m_pData->m_bReadOnlyWrap,
+ "The wrapper can not allow writing in case implementation does not!\n" );
+
+ if ( m_pData->m_bReadOnlyWrap )
+ m_pImpl->SetReadOnlyWrap( *this );
+ else
+ m_pImpl->m_pAntiImpl = this;
}
//-----------------------------------------------
@@ -1226,7 +1324,94 @@ OStorage::~OStorage()
}
if ( m_pData )
+ {
+ if ( m_pData->m_pSubElDispListener )
+ {
+ m_pData->m_pSubElDispListener->release();
+ m_pData->m_pSubElDispListener = NULL;
+ }
+
delete m_pData;
+ }
+}
+
+//-----------------------------------------------
+void SAL_CALL OStorage::InternalDispose( sal_Bool bNotifyImpl )
+{
+ if ( !m_pImpl )
+ throw lang::DisposedException();
+
+ lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
+ m_pData->m_aListenersContainer.disposeAndClear( aSource );
+
+ if ( m_pData->m_bReadOnlyWrap )
+ {
+ OSL_ENSURE( !m_pData->m_aOpenSubComponentsList.getLength() || m_pData->m_pSubElDispListener,
+ "If any subelements are open the listener must exist!\n" );
+
+ if ( m_pData->m_pSubElDispListener )
+ {
+ m_pData->m_pSubElDispListener->OwnerIsDisposed();
+
+ // iterate through m_pData->m_aOpenSubComponentsList
+ // deregister m_pData->m_pSubElDispListener and dispose all of them
+ for ( sal_Int32 nInd = 0; nInd < m_pData->m_aOpenSubComponentsList.getLength(); nInd++ )
+ if ( m_pData->m_aOpenSubComponentsList[nInd].is() )
+ {
+ m_pData->m_aOpenSubComponentsList[nInd]->removeEventListener( uno::Reference< lang::XEventListener >(
+ static_cast< lang::XEventListener* >( m_pData->m_pSubElDispListener ) ) );
+
+ try {
+ m_pData->m_aOpenSubComponentsList[nInd]->dispose();
+ } catch( uno::Exception& )
+ {}
+ m_pData->m_aOpenSubComponentsList[nInd] = uno::Reference< XComponent >();
+ }
+
+ m_pData->m_aOpenSubComponentsList.realloc( 0 );
+ }
+
+ if ( bNotifyImpl )
+ m_pImpl->RemoveReadOnlyWrap( *this );
+ }
+ else
+ {
+ m_pImpl->m_pAntiImpl = NULL;
+
+ if ( bNotifyImpl )
+ {
+ if ( m_pImpl->m_bIsRoot )
+ delete m_pImpl;
+ else
+ {
+ // the noncommited changes for the storage must be removed
+ m_pImpl->Revert();
+ }
+ }
+ }
+
+ m_pImpl = NULL;
+}
+
+//-----------------------------------------------
+void OStorage::ChildIsDisposed( const uno::Reference< uno::XInterface >& xChild )
+{
+ // this method can only be called by child disposing listener
+
+ // this method must not contain any locking
+ // the locking is done in the listener
+
+ sal_Int32 nOldLength = m_pData->m_aOpenSubComponentsList.getLength();
+ sal_Int32 nNewLength = 0;
+
+ uno::Sequence< uno::Reference< lang::XComponent > > aNewSeq( nOldLength );
+
+ for ( sal_Int32 nInd = 0; nInd < nOldLength; nInd++ )
+ if ( m_pData->m_aOpenSubComponentsList[nInd] != xChild )
+ aNewSeq[nNewLength++] = m_pData->m_aOpenSubComponentsList[nInd];
+
+ aNewSeq.realloc( nNewLength );
+ m_pData->m_aOpenSubComponentsList = aNewSeq;
}
//-----------------------------------------------
@@ -1235,6 +1420,8 @@ void OStorage::BroadcastModified()
if ( !m_pImpl )
throw lang::DisposedException();
+ OSL_ENSURE( !m_pData->m_bReadOnlyWrap, "The storage can not be modified at all!\n" );
+
lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
::cppu::OInterfaceContainerHelper* pContainer =
@@ -1262,6 +1449,8 @@ void OStorage::BroadcastTransaction( sal_Int8 nMessage )
if ( !m_pImpl )
throw lang::DisposedException();
+ OSL_ENSURE( !m_pData->m_bReadOnlyWrap, "The storage can not be modified at all!\n" );
+
lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
::cppu::OInterfaceContainerHelper* pContainer =
@@ -1298,6 +1487,9 @@ SotElement_Impl* OStorage::OpenStreamElement_Impl( const ::rtl::OUString& aStrea
{
::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
+ OSL_ENSURE( !m_pData->m_bReadOnlyWrap || ( nOpenMode & embed::ElementModes::ELEMENT_WRITE ) != embed::ElementModes::ELEMENT_WRITE,
+ "An element can not be opened for writing in readonly storage!\n" );
+
SotElement_Impl *pElement = m_pImpl->FindElement( aStreamName );
if ( !pElement )
{
@@ -1326,6 +1518,25 @@ SotElement_Impl* OStorage::OpenStreamElement_Impl( const ::rtl::OUString& aStrea
return pElement;
}
+//-----------------------------------------------
+void OStorage::MakeLinkToSubComponent_Impl( const uno::Reference< lang::XComponent >& xComponent )
+{
+ if ( !xComponent.is() )
+ throw uno::RuntimeException();
+
+ if ( !m_pData->m_pSubElDispListener )
+ {
+ m_pData->m_pSubElDispListener = new OChildDispListener_Impl( *this );
+ m_pData->m_pSubElDispListener->acquire();
+ }
+
+ xComponent->addEventListener( uno::Reference< lang::XEventListener >(
+ static_cast< ::cppu::OWeakObject* >( m_pData->m_pSubElDispListener ), uno::UNO_QUERY ) );
+
+ sal_Int32 nLength = m_pData->m_aOpenSubComponentsList.getLength();
+ m_pData->m_aOpenSubComponentsList.realloc( nLength + 1 );
+ m_pData->m_aOpenSubComponentsList[nLength] = xComponent;
+}
//____________________________________________________________________________________________________
// XInterface
@@ -1446,6 +1657,51 @@ uno::Sequence< sal_Int8 > SAL_CALL OStorage::getImplementationId()
}
+//-----------------------------------------------
+uno::Reference< io::XStream > OStorage_Impl::CloneStreamElement( const ::rtl::OUString& aStreamName,
+ sal_Bool bPassProvided,
+ const uno::Sequence< sal_Int8 >& aKey )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::WrongPasswordException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ SotElement_Impl *pElement = FindElement( aStreamName );
+ if ( !pElement )
+ {
+ // element does not exist, throw exception
+ throw io::IOException(); // TODO: access_denied
+ }
+ else if ( pElement->m_bIsStorage )
+ throw io::IOException(); // TODO:
+
+ if ( !pElement->m_pStream )
+ OpenSubStream( pElement );
+
+ uno::Reference< io::XStream > xResult;
+ if ( pElement->m_pStream && pElement->m_pStream->m_xPackageStream.is() )
+ {
+ // the existence of m_pAntiImpl of the child is not interesting,
+ // the copy will be created internally
+
+ // usual copying is not applicable here, only last flushed version of the
+ // child stream should be used for copiing. Probably the childs m_xPackageStream
+ // can be used as a base of a new stream, that would be copied to result
+ // storage. The only problem is that some package streams can be accessed from outside
+ // at the same time ( now solwed by wrappers that remember own position ).
+
+ if ( bPassProvided )
+ xResult = pElement->m_pStream->GetCopyOfLastCommit( aKey );
+ else
+ xResult = pElement->m_pStream->GetCopyOfLastCommit();
+ }
+ else
+ throw io::IOException(); // TODO: general_error
+
+ return xResult;
+}
//____________________________________________________________________________________________________
// XStorage
@@ -1476,7 +1732,7 @@ uno::Reference< io::XStream > SAL_CALL OStorage::openStreamElement(
const ::rtl::OUString& aStreamName, sal_Int32 nOpenMode )
throw ( embed::InvalidStorageException,
lang::IllegalArgumentException,
- ::com::sun::star::packages::WrongPasswordException,
+ packages::WrongPasswordException,
io::IOException,
embed::StorageWTException,
uno::RuntimeException )
@@ -1486,14 +1742,26 @@ uno::Reference< io::XStream > SAL_CALL OStorage::openStreamElement(
if ( !m_pImpl )
throw lang::DisposedException();
- if ( ( nOpenMode & embed::ElementModes::ELEMENT_WRITE )
- && !( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) )
+ if ( ( nOpenMode & embed::ElementModes::ELEMENT_WRITE ) && m_pData->m_bReadOnlyWrap )
throw io::IOException(); // TODO: access denied
SotElement_Impl *pElement = OpenStreamElement_Impl( aStreamName, nOpenMode, sal_False );
OSL_ENSURE( pElement && pElement->m_pStream, "In case element can not be created an exception must be thrown!" );
- return pElement->m_pStream->GetStream( nOpenMode );
+ uno::Reference< io::XStream > xResult = pElement->m_pStream->GetStream( nOpenMode );
+ OSL_ENSURE( xResult.is(), "The method must throw exception instead of removing empty result!\n" );
+
+ if ( m_pData->m_bReadOnlyWrap )
+ {
+ // before the storage disposes the stream it must deregister itself as listener
+ uno::Reference< lang::XComponent > xStreamComponent( xResult, uno::UNO_QUERY );
+ if ( !xStreamComponent.is() )
+ throw uno::RuntimeException(); // TODO
+
+ MakeLinkToSubComponent_Impl( xStreamComponent );
+ }
+
+ return xResult;
}
//-----------------------------------------------
@@ -1512,8 +1780,7 @@ uno::Reference< io::XStream > SAL_CALL OStorage::openEncryptedStreamElement(
if ( !m_pImpl )
throw lang::DisposedException();
- if ( ( nOpenMode & embed::ElementModes::ELEMENT_WRITE )
- && !( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) )
+ if ( ( nOpenMode & embed::ElementModes::ELEMENT_WRITE ) && m_pData->m_bReadOnlyWrap )
throw io::IOException(); // TODO: access denied
if ( !aKey.getLength() )
@@ -1522,7 +1789,20 @@ uno::Reference< io::XStream > SAL_CALL OStorage::openEncryptedStreamElement(
SotElement_Impl *pElement = OpenStreamElement_Impl( aStreamName, nOpenMode, sal_True );
OSL_ENSURE( pElement && pElement->m_pStream, "In case element can not be created an exception must be thrown!" );
- return pElement->m_pStream->GetStream( nOpenMode, aKey );
+ uno::Reference< io::XStream > xResult = pElement->m_pStream->GetStream( nOpenMode, aKey );
+ OSL_ENSURE( xResult.is(), "The method must throw exception instead of removing empty result!\n" );
+
+ if ( m_pData->m_bReadOnlyWrap )
+ {
+ // before the storage disposes the stream it must deregister itself as listener
+ uno::Reference< lang::XComponent > xStreamComponent( xResult, uno::UNO_QUERY );
+ if ( !xStreamComponent.is() )
+ throw uno::RuntimeException(); // TODO
+
+ MakeLinkToSubComponent_Impl( xStreamComponent );
+ }
+
+ return xResult;
}
//-----------------------------------------------
@@ -1539,8 +1819,7 @@ uno::Reference< embed::XStorage > SAL_CALL OStorage::openStorageElement(
if ( !m_pImpl )
throw lang::DisposedException();
- if ( ( nStorageMode & embed::ElementModes::ELEMENT_WRITE )
- && !( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) )
+ if ( ( nStorageMode & embed::ElementModes::ELEMENT_WRITE ) && m_pData->m_bReadOnlyWrap )
throw io::IOException(); // TODO: access denied
if ( ( nStorageMode & embed::ElementModes::ELEMENT_TRUNCATE )
@@ -1568,36 +1847,41 @@ uno::Reference< embed::XStorage > SAL_CALL OStorage::openStorageElement(
}
else if ( pElement->m_pStorage )
{
- // storage has already been opened; if it has no external reference, it may be opened another time
+ // storage has already been opened; it may be opened another time, if it the mode allows to do so
if ( pElement->m_pStorage->m_pAntiImpl )
{
throw io::IOException(); // TODO: access_denied
}
+ else if ( !pElement->m_pStorage->m_aReadOnlyWrapList.empty()
+ && ( nStorageMode & embed::ElementModes::ELEMENT_WRITE ) )
+ {
+ throw io::IOException(); // TODO: access_denied
+ }
else
{
- // in case substorage was opened for writing once
- // it will allways provide write access
-
- // TODO: in case of transacted mode is completly implemented for substorages
- // it will be possible to reopen written storage in readonly mode
-
- if ( pElement->m_pStorage->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE )
- nStorageMode |= embed::ElementModes::ELEMENT_WRITE;
-
- // in case parent storage allows writing the readonly mode of the child storage is
- // virtual, that means that it is just enough to change the flag to let it be writable
- // and since there is no AntiImpl nobody should be notified about it
- pElement->m_pStorage->m_nStorageMode = nStorageMode | embed::ElementModes::ELEMENT_READ;
-
- if ( ( nStorageMode & embed::ElementModes::ELEMENT_TRUNCATE ) )
+ if ( ( nStorageMode & embed::ElementModes::ELEMENT_WRITE )
+ && !( pElement->m_pStorage->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) )
{
- for ( SotElementList_Impl::iterator pElementIter = m_pImpl->m_aChildrenList.begin();
- pElementIter != m_pImpl->m_aChildrenList.end(); )
- {
- SotElement_Impl* pElement = (*pElementIter);
- pElementIter++;
+ delete pElement->m_pStorage;
+ pElement->m_pStorage = NULL;
+ }
+ else
+ {
+ // in case parent storage allows writing the readonly mode of the child storage is
+ // virtual, that means that it is just enough to change the flag to let it be writable
+ // and since there is no AntiImpl nobody should be notified about it
+ pElement->m_pStorage->m_nStorageMode = nStorageMode | embed::ElementModes::ELEMENT_READ;
- m_pImpl->RemoveElement( pElement );
+ if ( ( nStorageMode & embed::ElementModes::ELEMENT_TRUNCATE ) )
+ {
+ for ( SotElementList_Impl::iterator pElementIter = pElement->m_pStorage->m_aChildrenList.begin();
+ pElementIter != pElement->m_pStorage->m_aChildrenList.end(); )
+ {
+ SotElement_Impl* pElementToDel = (*pElementIter);
+ pElementIter++;
+
+ m_pImpl->RemoveElement( pElementToDel );
+ }
}
}
}
@@ -1609,8 +1893,142 @@ uno::Reference< embed::XStorage > SAL_CALL OStorage::openStorageElement(
if ( !pElement->m_pStorage )
throw io::IOException(); // TODO: general_error
- return uno::Reference< embed::XStorage >( static_cast< OWeakObject* >( new OStorage( pElement->m_pStorage ) ),
- uno::UNO_QUERY );
+ uno::Reference< embed::XStorage > xResult(
+ static_cast< OWeakObject* >( new OStorage(
+ pElement->m_pStorage,
+ ( nStorageMode & embed::ElementModes::ELEMENT_WRITE ) != embed::ElementModes::ELEMENT_WRITE ) ),
+ uno::UNO_QUERY );
+
+ if ( m_pData->m_bReadOnlyWrap )
+ {
+ // before the storage disposes the stream it must deregister itself as listener
+ uno::Reference< lang::XComponent > xStorageComponent( xResult, uno::UNO_QUERY );
+ if ( !xStorageComponent.is() )
+ throw uno::RuntimeException(); // TODO
+
+ MakeLinkToSubComponent_Impl( xStorageComponent );
+ }
+
+ return xResult;
+}
+
+//-----------------------------------------------
+uno::Reference< io::XStream > SAL_CALL OStorage::cloneStreamElement( const ::rtl::OUString& aStreamName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ packages::WrongPasswordException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
+
+ if ( !m_pImpl )
+ throw lang::DisposedException();
+
+ return m_pImpl->CloneStreamElement( aStreamName, sal_False, uno::Sequence< sal_Int8 >() );
+}
+
+//-----------------------------------------------
+uno::Reference< io::XStream > SAL_CALL OStorage::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 )
+{
+ ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
+
+ if ( !m_pImpl )
+ throw lang::DisposedException();
+
+ if ( !aKey.getLength() )
+ throw lang::IllegalArgumentException();
+
+ return m_pImpl->CloneStreamElement( aStreamName, sal_True, aKey );
+}
+
+//-----------------------------------------------
+uno::Reference< embed::XStorage > SAL_CALL OStorage::cloneStorageElement( const ::rtl::OUString& aStorName )
+ throw ( embed::InvalidStorageException,
+ lang::IllegalArgumentException,
+ io::IOException,
+ embed::StorageWTException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
+
+ if ( !m_pImpl )
+ throw lang::DisposedException();
+
+ // it's allways possible to read written storage in this implementation
+ sal_Int32 nStorageMode = embed::ElementModes::ELEMENT_READ;
+
+ SotElement_Impl *pElement = m_pImpl->FindElement( aStorName );
+ if ( !pElement )
+ {
+ // element does not exist, throw exception
+ throw io::IOException(); // TODO: access_denied
+ }
+ else if ( !pElement->m_bIsStorage )
+ {
+ throw io::IOException(); // TODO:
+ }
+
+ if ( !pElement->m_pStorage )
+ m_pImpl->OpenSubStorage( pElement, nStorageMode );
+
+ uno::Reference< embed::XStorage > xResult;
+ if ( pElement->m_pStorage )
+ {
+ // the existence of m_pAntiImpl of the child is not interesting,
+ // the copy will be created internally
+
+ uno::Reference < io::XStream > xTempFile(
+ m_pImpl->m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
+ uno::UNO_QUERY );
+
+ if ( !xTempFile.is() )
+ throw uno::RuntimeException(); // TODO
+
+ OStorage* pNewStorage = new OStorage( xTempFile,
+ embed::ElementModes::ELEMENT_WRITE,
+ uno::Sequence< beans::PropertyValue >(),
+ m_pImpl->m_xFactory );
+ uno::Reference< embed::XStorage > xNewStor = uno::Reference< embed::XStorage >( (embed::XStorage*)pNewStorage );
+
+ // usual copying is not applicable here, only last commited version of the
+ // child storage should be used for copiing. Probably the childs m_pPackageFolder
+ // can be used as a base of a new storage, that would be copied to result
+ // storage. The only problem is that some package streams can be accessed from outside
+ // at the same time ( now solwed by wrappers that remember own position ).
+
+ pElement->m_pStorage->CopyLastCommitTo( xNewStor );
+
+ // In general a readonly mode could be set by changing of m_nStorageMode member value
+ // but it would not be a very clean solution that could be affected by future changes
+ // so the storage is just reopened on the same stream.
+ uno::Reference< lang::XComponent > xComp( xNewStor, uno::UNO_QUERY );
+ if ( !xComp.is() )
+ throw uno::RuntimeException(); // TODO:
+
+ try {
+ xComp->dispose();
+ } catch ( uno::Exception& ) {}
+
+ xResult = uno::Reference< embed::XStorage > ( (embed::XStorage*) new OStorage( xTempFile,
+ embed::ElementModes::ELEMENT_READ,
+ uno::Sequence< beans::PropertyValue >(),
+ m_pImpl->m_xFactory ) );
+ }
+ else
+ throw io::IOException(); // TODO: general_error
+
+ return xResult;
}
//-----------------------------------------------
@@ -1838,7 +2256,7 @@ void SAL_CALL OStorage::commit()
if ( !m_pImpl )
throw lang::DisposedException();
- if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) )
+ if ( m_pData->m_bReadOnlyWrap )
throw io::IOException(); // TODO: access_denied
if ( !m_pImpl->m_bListCreated )
@@ -1885,11 +2303,13 @@ void SAL_CALL OStorage::revert()
for ( SotElementList_Impl::iterator pElementIter = m_pImpl->m_aChildrenList.begin();
pElementIter != m_pImpl->m_aChildrenList.end(); pElementIter++ )
- if ( (*pElementIter)->m_pStorage && (*pElementIter)->m_pStorage->m_pAntiImpl
- || (*pElementIter)->m_pStream && (*pElementIter)->m_pStream->m_pAntiImpl )
+ if ( (*pElementIter)->m_pStorage
+ && ( (*pElementIter)->m_pStorage->m_pAntiImpl || !(*pElementIter)->m_pStorage->m_aReadOnlyWrapList.empty() )
+ || (*pElementIter)->m_pStream
+ && ( (*pElementIter)->m_pStream->m_pAntiImpl || !(*pElementIter)->m_pStream->m_aInputStreamsList.empty() ) )
throw io::IOException(); // TODO: access denied
- if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) || !m_pImpl->m_bListCreated )
+ if ( m_pData->m_bReadOnlyWrap || !m_pImpl->m_bListCreated )
return; // nothing to do
try {
@@ -1978,7 +2398,7 @@ void SAL_CALL OStorage::setModified( sal_Bool bModified )
if ( !m_pImpl )
throw lang::DisposedException();
- if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) )
+ if ( m_pData->m_bReadOnlyWrap )
throw beans::PropertyVetoException(); // TODO: access denied
if ( m_pImpl->m_bIsModified != bModified )
@@ -2137,27 +2557,12 @@ sal_Bool SAL_CALL OStorage::hasElements()
void SAL_CALL OStorage::dispose()
throw ( uno::RuntimeException )
{
- // should be an internal method since it can be called only from parent storage
-
::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
if ( !m_pImpl )
throw lang::DisposedException();
- lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
- m_pData->m_aListenersContainer.disposeAndClear( aSource );
-
- m_pImpl->m_pAntiImpl = NULL;
-
- if ( m_pImpl->m_bIsRoot )
- delete m_pImpl;
- else
- {
- // the noncommited changes for the storage must be removed
- m_pImpl->Revert();
- }
-
- m_pImpl = NULL;
+ InternalDispose( sal_True );
}
//-----------------------------------------------
@@ -2259,6 +2664,9 @@ void SAL_CALL OStorage::setPropertyValue( const ::rtl::OUString& aPropertyName,
//TODO: think about interaction handler
+ if ( m_pData->m_bReadOnlyWrap )
+ throw io::IOException(); // TODO: Access denied
+
if ( aPropertyName.equalsAscii( "MediaType" ) )
{
aValue >>= m_pImpl->m_aMediaType;