summaryrefslogtreecommitdiff
path: root/package/source/xstor/xstorage.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'package/source/xstor/xstorage.cxx')
-rw-r--r--package/source/xstor/xstorage.cxx492
1 files changed, 304 insertions, 188 deletions
diff --git a/package/source/xstor/xstorage.cxx b/package/source/xstor/xstorage.cxx
index 41ce446bfd26..590ad41ca79b 100644
--- a/package/source/xstor/xstorage.cxx
+++ b/package/source/xstor/xstorage.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: xstorage.cxx,v $
*
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
*
- * last change: $Author: kz $ $Date: 2003-09-11 10:16:30 $
+ * last change: $Author: rt $ $Date: 2003-10-30 09:48:27 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -87,6 +87,11 @@
#include <com/sun/star/util/XChangesBatch.hpp>
#endif
+#ifndef _COM_SUN_STAR_UTIL_XCLONEABLE_HPP_
+#include <com/sun/star/util/XCloneable.hpp>
+#endif
+
+
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
@@ -108,6 +113,12 @@
#include "xstorage.hxx"
#include "owriteablestream.hxx"
+#define STOR_MESS_PRECOMMIT 1
+#define STOR_MESS_COMMITED 2
+#define STOR_MESS_PREREVERT 3
+#define STOR_MESS_REVERTED 4
+
+
using namespace ::com::sun::star;
extern void copyInputToOutput_Impl( const uno::Reference< io::XInputStream >& aIn,
@@ -157,7 +168,6 @@ uno::Reference< io::XInputStream > GetSeekableTempCopy( uno::Reference< io::XInp
return xTempIn;
}
-
StorInternalData_Impl::~StorInternalData_Impl()
{
if ( m_pTypeCollection )
@@ -202,6 +212,7 @@ OStorage_Impl::OStorage_Impl( uno::Reference< io::XInputStream > xInputStream,
, m_xInputStream( xInputStream )
, m_xProperties( xProperties )
, m_pParent( NULL )
+, m_bControlMediaType( sal_False )
{
// all the checks done below by assertion statements must be done by factory
OSL_ENSURE( xInputStream.is(), "No input stream is provided!\n" );
@@ -230,6 +241,7 @@ OStorage_Impl::OStorage_Impl( uno::Reference< io::XStream > xStream,
, m_xStream( xStream )
, m_xProperties( xProperties )
, m_pParent( NULL )
+, m_bControlMediaType( sal_False )
{
// all the checks done below by assertion statements must be done by factory
OSL_ENSURE( xStream.is(), "No stream is provided!\n" );
@@ -256,13 +268,14 @@ OStorage_Impl::OStorage_Impl( OStorage_Impl* pParent,
, m_pAntiImpl( NULL )
, m_nStorageMode( nMode )
, m_bIsModified( sal_False )
-, m_bCommited( sal_True ) // substorages are allways used in direct mode
+, m_bCommited( sal_False )
, m_bIsRoot( sal_False )
, m_bListCreated( sal_False )
, m_xPackageFolder( xPackageFolder )
, m_xPackage( xPackage )
, m_xFactory( xFactory )
, m_pParent( pParent )
+, m_bControlMediaType( sal_False )
{
OSL_ENSURE( xPackageFolder.is(), "No package folder!\n" );
OSL_ENSURE( pParent, "No parent is provided!\n" );
@@ -423,11 +436,15 @@ SotElementList_Impl& OStorage_Impl::GetChildrenList()
//-----------------------------------------------
void OStorage_Impl::GetStorageProperties()
{
- uno::Reference< beans::XPropertySet > xProps( m_xPackageFolder, uno::UNO_QUERY );
- if ( !xProps.is() )
- throw uno::RuntimeException(); // TODO:
+ if ( !m_bControlMediaType )
+ {
+ uno::Reference< beans::XPropertySet > xProps( m_xPackageFolder, uno::UNO_QUERY );
+ if ( !xProps.is() )
+ throw uno::RuntimeException(); // TODO:
- xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ) >>= m_aMediaType;
+ xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ) >>= m_aMediaType;
+ m_bControlMediaType = sal_True;
+ }
}
//-----------------------------------------------
@@ -623,18 +640,66 @@ void OStorage_Impl::CopyStorageElement( SotElement_Impl* pElement,
}
//-----------------------------------------------
-void OStorage_Impl::Commit()
+void OStorage_Impl::InsertIntoPackageFolder( const ::rtl::OUString& aName,
+ const uno::Reference< container::XNameContainer >& xParentPackageFolder )
{
::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
- if ( !m_bCommited )
- return; // the storage is not commited explicitly
+ OSL_ENSURE( m_xPackageFolder.is(), "An inserted storage is incomplete!\n" );
+ uno::Reference< lang::XUnoTunnel > xTunnel( m_xPackageFolder, uno::UNO_QUERY );
+ if ( !xTunnel.is() )
+ throw uno::RuntimeException(); // TODO
+
+ xParentPackageFolder->insertByName( aName, uno::makeAny( xTunnel ) );
+
+ m_bCommited = sal_False;
+}
+
+//-----------------------------------------------
+void OStorage_Impl::Commit()
+{
+ ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
// if storage is commited it should have a valid Package representation
OSL_ENSURE( m_xPackageFolder.is(), "The package representation should exist!\n" );
if ( !m_xPackageFolder.is() )
throw embed::InvalidStorageException(); // TODO:
+ OSL_ENSURE( m_nStorageMode & embed::ElementModes::ELEMENT_WRITE,
+ "Commit of readonly storage, should be detected before!\n" );
+
+ uno::Reference< container::XNameContainer > xNewPackageFolder;
+
+ // here the storage will switch to the temporary package folder
+ // if the storage was already commited and the parent was not commited after that
+ // the switch should not be done since the package folder in use is a temporary one;
+ // it can be detected by m_bCommited flag ( root storage doesn't need temporary representation )
+ if ( !m_bCommited && !m_bIsRoot )
+ {
+ uno::Sequence< uno::Any > aSeq( 1 );
+ aSeq[0] <<= sal_True;
+
+ xNewPackageFolder = uno::Reference< container::XNameContainer >(
+ m_xPackage->createInstanceWithArguments( aSeq ),
+ uno::UNO_QUERY );
+ }
+ else
+ xNewPackageFolder = m_xPackageFolder;
+
+ // remove replaced removed elements
+ for ( SotElementList_Impl::iterator pDeletedIter = m_aDeletedList.begin();
+ pDeletedIter != m_aDeletedList.end();
+ pDeletedIter++ )
+ {
+ // the removed elements are not in new temporary storage
+ if ( m_bCommited || m_bIsRoot )
+ xNewPackageFolder->removeByName( (*pDeletedIter)->m_aOriginalName );
+ delete *pDeletedIter;
+ pDeletedIter = NULL;
+ }
+ m_aDeletedList.clear();
+
+ // remove removed elements
SotElementList_Impl::iterator pElementIter = m_aChildrenList.begin();
while ( pElementIter != m_aChildrenList.end() )
{
@@ -643,7 +708,10 @@ void OStorage_Impl::Commit()
if ( (*pElementIter)->m_bIsRemoved )
{
- m_xPackageFolder->removeByName( (*pElementIter)->m_aOriginalName );
+ // the removed elements are not in new temporary storage
+ if ( m_bCommited || m_bIsRoot )
+ xNewPackageFolder->removeByName( (*pElementIter)->m_aOriginalName );
+
SotElement_Impl* pToDelete = *pElementIter;
pElementIter++; // to let the iterator be valid it should be increased before removing
@@ -655,20 +723,45 @@ void OStorage_Impl::Commit()
pElementIter++;
}
+ // there should be no more deleted elements
for ( pElementIter = m_aChildrenList.begin(); pElementIter != m_aChildrenList.end(); pElementIter++ )
{
- // there should be no more deleted elements
-
- // inserted elements must be really inserted to package later
+ // if it is a 'duplicate commit' inserted elements must be really inserted to package later
// since thay can conflict with renamed elements
if ( !(*pElementIter)->m_bIsInserted )
{
- // inserted elements must be really inserted to package later
- // since thay can conflict with removed or renamed elements
- if ( (*pElementIter)->m_aName.compareTo( (*pElementIter)->m_aOriginalName ) )
+ // if the storage was not open, there is no need to commit it ???
+ // the storage should be checked that it is commited
+ if ( (*pElementIter)->m_bIsStorage && (*pElementIter)->m_pStorage && (*pElementIter)->m_pStorage->m_bCommited )
{
- // in case the name was changed rename the element
+ // it's temporary PackageFolder should be inserted instead of current one
+ // also the new copy of PackageFolder should be used by the children storages
+
+ xNewPackageFolder->removeByName( (*pElementIter)->m_aOriginalName );
+ (*pElementIter)->m_pStorage->InsertIntoPackageFolder( (*pElementIter)->m_aName, xNewPackageFolder );
+ }
+ else if ( !(*pElementIter)->m_bIsStorage && (*pElementIter)->m_pStream )
+ {
+ // for now stream is opened in direct mode that means that in case
+ // storage is commited all the streams from it are commited in current state.
+ // following two steps are separated to allow easily implement transacted mode
+ // for streams if we need it in future.
+
+ (*pElementIter)->m_pStream->Commit();
+
+ xNewPackageFolder->removeByName( (*pElementIter)->m_aOriginalName );
+ (*pElementIter)->m_pStream->InsertIntoPackageFolder( (*pElementIter)->m_aName, xNewPackageFolder );
+ }
+ else if ( !m_bCommited && !m_bIsRoot )
+ {
+ // the element must be just copied to the new temporary package folder
+ uno::Any aPackageElement = m_xPackageFolder->getByName( (*pElementIter)->m_aOriginalName );
+ xNewPackageFolder->insertByName( (*pElementIter)->m_aOriginalName, aPackageElement );
+ }
+ else if ( (*pElementIter)->m_aName.compareTo( (*pElementIter)->m_aOriginalName ) )
+ {
+ // in case the name was changed and it is not a changed storage - rename the element
uno::Reference< container::XNamed > xNamed;
uno::Any aPackageElement = m_xPackageFolder->getByName( (*pElementIter)->m_aOriginalName );
@@ -676,21 +769,9 @@ void OStorage_Impl::Commit()
OSL_ENSURE( xNamed.is(), "PackageFolder/PackageStream MUST support XNamed interface" );
xNamed->setName( (*pElementIter)->m_aName );
- (*pElementIter)->m_aOriginalName = (*pElementIter)->m_aName;
}
- if ( (*pElementIter)->m_bIsStorage )
- {
- // if the storage was not open, there is no need to commit it ???
- if ( (*pElementIter)->m_pStorage )
- (*pElementIter)->m_pStorage->Commit();
- }
- else
- {
- // if the stream was not open, there is no need to commit it ???
- if ( (*pElementIter)->m_pStream )
- (*pElementIter)->m_pStream->Commit();
- }
+ (*pElementIter)->m_aOriginalName = (*pElementIter)->m_aName;
}
}
@@ -704,48 +785,33 @@ void OStorage_Impl::Commit()
if ( (*pElementIter)->m_bIsStorage )
{
- OSL_ENSURE( (*pElementIter)->m_pStorage && (*pElementIter)->m_pStorage->m_xPackageFolder.is(),
- "An inserted storage is incomplete!\n" );
- if ( !(*pElementIter)->m_pStorage || !(*pElementIter)->m_pStorage->m_xPackageFolder.is() )
- throw uno::RuntimeException(); // TODO
+ if ( (*pElementIter)->m_pStorage->m_bCommited )
+ {
+ OSL_ENSURE( (*pElementIter)->m_pStorage, "An inserted storage is incomplete!\n" );
+ if ( !(*pElementIter)->m_pStorage )
+ throw uno::RuntimeException(); // TODO
+
+ (*pElementIter)->m_pStorage->InsertIntoPackageFolder( (*pElementIter)->m_aName, xNewPackageFolder );
- xNewElement = uno::Reference< lang::XUnoTunnel >( (*pElementIter)->m_pStorage->m_xPackageFolder,
- uno::UNO_QUERY );
- (*pElementIter)->m_pStorage->Commit();
+ (*pElementIter)->m_bIsInserted = sal_False;
+ }
}
else
{
- OSL_ENSURE( (*pElementIter)->m_pStream && (*pElementIter)->m_pStream->m_xPackageStream.is(),
- "An inserted stream is incomplete!\n" );
- if ( !(*pElementIter)->m_pStream || !(*pElementIter)->m_pStream->m_xPackageStream.is() )
+ OSL_ENSURE( (*pElementIter)->m_pStream, "An inserted stream is incomplete!\n" );
+ if ( !(*pElementIter)->m_pStream )
throw uno::RuntimeException(); // TODO
- xNewElement = uno::Reference< lang::XUnoTunnel >( (*pElementIter)->m_pStream->m_xPackageStream,
- uno::UNO_QUERY );
- (*pElementIter)->m_pStream->Commit();
- }
+ (*pElementIter)->m_pStream->Commit(); // direct mode
+ (*pElementIter)->m_pStream->InsertIntoPackageFolder( (*pElementIter)->m_aName, xNewPackageFolder );
- if ( !xNewElement.is() )
- throw uno::RuntimeException(); // TODO
-
- m_xPackageFolder->insertByName( (*pElementIter)->m_aName, uno::makeAny( xNewElement ) );
- (*pElementIter)->m_bIsInserted = sal_False;
+ (*pElementIter)->m_bIsInserted = sal_False;
+ }
}
}
- // remove replaced removed elements
- for ( SotElementList_Impl::iterator pDeletedIter = m_aDeletedList.begin();
- pDeletedIter != m_aDeletedList.end();
- pDeletedIter++ )
- {
- delete *pDeletedIter;
- pDeletedIter = NULL;
- }
- m_aDeletedList.clear();
-
-
// move properties to the destination package folder
- uno::Reference< beans::XPropertySet > xProps( m_xPackageFolder, uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySet > xProps( xNewPackageFolder, uno::UNO_QUERY );
if ( !xProps.is() )
throw uno::RuntimeException(); // TODO:
@@ -761,8 +827,17 @@ void OStorage_Impl::Commit()
xChangesBatch->commitChanges();
}
+ else if ( !m_bCommited )
+ {
+ m_xPackageFolder = xNewPackageFolder;
+ m_bCommited = sal_True;
+ }
SetModifiedInternally( sal_False );
+
+ // when the storage is commited the parent is modified
+ if ( m_pParent )
+ m_pParent->SetModifiedInternally( sal_True );
}
//-----------------------------------------------
@@ -773,12 +848,14 @@ void OStorage_Impl::Revert()
if ( !( m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) )
return; // nothing to do
+ // all the children must be removed
+ // they will be created later on demand
+
SotElementList_Impl::iterator pElementIter = m_aChildrenList.begin();
while ( pElementIter != m_aChildrenList.end() )
{
if ( (*pElementIter)->m_bIsInserted )
{
- m_xPackageFolder->removeByName( (*pElementIter)->m_aOriginalName );
SotElement_Impl* pToDelete = *pElementIter;
pElementIter++; // to let the iterator be valid it should be increased before removing
@@ -788,14 +865,7 @@ void OStorage_Impl::Revert()
}
else
{
- if ( (*pElementIter)->m_pStream )
- {
- (*pElementIter)->m_pStream->Revert();
- }
- else if ( (*pElementIter)->m_pStorage )
- {
- (*pElementIter)->m_pStorage->Revert();
- }
+ ClearElement( *pElementIter );
(*pElementIter)->m_aName = (*pElementIter)->m_aOriginalName;
(*pElementIter)->m_bIsRemoved = sal_False;
@@ -809,29 +879,10 @@ void OStorage_Impl::Revert()
pDeletedIter != m_aDeletedList.end();
pDeletedIter++ )
{
- if ( (*pDeletedIter)->m_bIsStorage )
- {
- OSL_ENSURE( (*pDeletedIter)->m_aOriginalName.getLength()
- && (*pDeletedIter)->m_pStorage
- && (*pDeletedIter)->m_pStorage->m_xPackageFolder.is(),
- "Deleted substorage information is corrupted!\n" );
-
- m_xPackageFolder->insertByName( (*pDeletedIter)->m_aOriginalName,
- uno::makeAny( (*pDeletedIter)->m_pStorage->m_xPackageFolder ) );
- }
- else
- {
- OSL_ENSURE( (*pDeletedIter)->m_aOriginalName.getLength()
- && (*pDeletedIter)->m_pStorage
- && (*pDeletedIter)->m_pStorage->m_xPackageFolder.is(),
- "Deleted substream information is corrupted!\n" );
-
- m_xPackageFolder->insertByName( (*pDeletedIter)->m_aOriginalName,
- uno::makeAny( (*pDeletedIter)->m_pStorage->m_xPackageFolder ) );
- }
-
m_aChildrenList.push_back( (*pDeletedIter) );
+ ClearElement( *pDeletedIter );
+
(*pDeletedIter)->m_aName = (*pDeletedIter)->m_aOriginalName;
(*pDeletedIter)->m_bIsRemoved = sal_False;
}
@@ -851,9 +902,6 @@ void OStorage_Impl::SetModifiedInternally( sal_Bool bModified )
m_pAntiImpl->setModified( bModified );
else
m_bIsModified = bModified;
-
- if ( bModified && m_pParent )
- m_pParent->SetModifiedInternally( sal_True );
}
//-----------------------------------------------
@@ -908,6 +956,7 @@ SotElement_Impl* OStorage_Impl::InsertStream( ::rtl::OUString aName, sal_Bool bE
//-----------------------------------------------
SotElement_Impl* OStorage_Impl::InsertRawStream( ::rtl::OUString aName, const uno::Reference< io::XInputStream >& xInStream )
{
+ // insert of raw stream means insert and commit
OSL_ENSURE( m_xPackage.is(), "Not possible to refer to package as to factory!\n" );
if ( !m_xPackage.is() )
throw embed::InvalidStorageException(); // TODO
@@ -934,6 +983,8 @@ SotElement_Impl* OStorage_Impl::InsertRawStream( ::rtl::OUString aName, const un
// the mode is not needed for storage stream internal implementation
SotElement_Impl* pNewElement = InsertElement( aName, sal_False );
pNewElement->m_pStream = new OWriteStream_Impl( this, xPackageSubStream, m_xPackage, m_xFactory, sal_True );
+ // the stream is inserted and must be treated as a commited one
+ pNewElement->m_pStream->SetToBeCommited();
m_aChildrenList.push_back( pNewElement );
SetModifiedInternally( sal_True );
@@ -1002,7 +1053,6 @@ SotElement_Impl* OStorage_Impl::InsertElement( ::rtl::OUString aName, sal_Bool b
else
OpenSubStream( pDeletedElm );
- m_xPackageFolder->removeByName( pDeletedElm->m_aOriginalName );
m_aChildrenList.remove( pDeletedElm ); // correct usage of list ???
m_aDeletedList.push_back( pDeletedElm );
}
@@ -1094,6 +1144,10 @@ 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 )
+ throw io::IOException(); // TODO: Access denied
+
if ( pElement->m_bIsInserted )
{
m_aChildrenList.remove( pElement );
@@ -1102,38 +1156,23 @@ void OStorage_Impl::RemoveElement( SotElement_Impl* pElement )
else
{
pElement->m_bIsRemoved = sal_True;
-
- if ( pElement->m_pStorage )
- {
- delete pElement->m_pStorage;
- pElement->m_pStorage = NULL;
- }
-
- if ( pElement->m_pStream )
- {
- delete pElement->m_pStream;
- pElement->m_pStream = NULL;
- }
+ ClearElement( pElement );
}
}
//-----------------------------------------------
-void OStorage_Impl::DisposeChildren()
+void OStorage_Impl::ClearElement( SotElement_Impl* pElement )
{
- for ( SotElementList_Impl::iterator pElementIter = m_aChildrenList.begin();
- pElementIter != m_aChildrenList.end(); pElementIter++ )
+ if ( pElement->m_pStorage )
{
- OSL_ENSURE( !(*pElementIter)->m_bIsRemoved
- || ( (*pElementIter)->m_pStorage == NULL && (*pElementIter)->m_pStream == NULL ),
- "The removed element must not have contents!" );
+ delete pElement->m_pStorage;
+ pElement->m_pStorage = NULL;
+ }
- if ( !(*pElementIter)->m_bIsRemoved )
- {
- if ( (*pElementIter)->m_bIsStorage && (*pElementIter)->m_pStorage && (*pElementIter)->m_pStorage->m_pAntiImpl )
- (*pElementIter)->m_pStorage->m_pAntiImpl->dispose();
- if ( !(*pElementIter)->m_bIsStorage && (*pElementIter)->m_pStream )
- (*pElementIter)->m_pStream->DisposeWrappers();
- }
+ if ( pElement->m_pStream )
+ {
+ delete pElement->m_pStream;
+ pElement->m_pStream = NULL;
}
}
@@ -1198,8 +1237,6 @@ OStorage::~OStorage()
//-----------------------------------------------
void OStorage::BroadcastModified()
{
- ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
-
if ( !m_pImpl )
throw lang::DisposedException();
@@ -1219,6 +1256,49 @@ void OStorage::BroadcastModified()
}
//-----------------------------------------------
+void OStorage::BroadcastTransaction( sal_Int8 nMessage )
+/*
+ 1 - preCommit
+ 2 - commited
+ 3 - preRevert
+ 4 - reverted
+*/
+{
+ if ( !m_pImpl )
+ throw lang::DisposedException();
+
+ lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
+
+ ::cppu::OInterfaceContainerHelper* pContainer =
+ m_pData->m_aListenersContainer.getContainer(
+ ::getCppuType( ( const uno::Reference< embed::XTransactionListener >*) NULL ) );
+ if ( pContainer )
+ {
+ ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
+ while ( pIterator.hasMoreElements( ) )
+ {
+ OSL_ENSURE( nMessage >= 1 && nMessage <= 4, "Wrong internal notification code is used!\n" );
+
+ switch( nMessage )
+ {
+ case STOR_MESS_PRECOMMIT:
+ ( ( embed::XTransactionListener* )pIterator.next( ) )->preCommit( aSource );
+ break;
+ case STOR_MESS_COMMITED:
+ ( ( embed::XTransactionListener* )pIterator.next( ) )->commited( aSource );
+ break;
+ case STOR_MESS_PREREVERT:
+ ( ( embed::XTransactionListener* )pIterator.next( ) )->preRevert( aSource );
+ break;
+ case STOR_MESS_REVERTED:
+ ( ( embed::XTransactionListener* )pIterator.next( ) )->reverted( aSource );
+ break;
+ }
+ }
+ }
+}
+
+//-----------------------------------------------
SotElement_Impl* OStorage::OpenStreamElement_Impl( const ::rtl::OUString& aStreamName, sal_Int32 nOpenMode, sal_Bool bEncr )
{
::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
@@ -1268,6 +1348,7 @@ uno::Any SAL_CALL OStorage::queryInterface( const uno::Type& rType )
, static_cast<lang::XTypeProvider*> ( this )
, static_cast<embed::XStorage*> ( this )
, static_cast<embed::XTransactedObject*> ( this )
+ , static_cast<embed::XTransactionBroadcaster*> ( this )
, static_cast<util::XModifiable*> ( this )
, static_cast<container::XNameAccess*> ( this )
, static_cast<lang::XComponent*> ( this )
@@ -1280,6 +1361,7 @@ uno::Any SAL_CALL OStorage::queryInterface( const uno::Type& rType )
( rType
, static_cast<lang::XTypeProvider*> ( this )
, static_cast<embed::XStorage*> ( this )
+ , static_cast<embed::XTransactedObject*> ( this )
, static_cast<util::XModifiable*> ( this )
, static_cast<container::XNameAccess*> ( this )
, static_cast<lang::XComponent*> ( this )
@@ -1324,6 +1406,7 @@ uno::Sequence< uno::Type > SAL_CALL OStorage::getTypes()
( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
, ::getCppuType( ( const uno::Reference< embed::XStorage >* )NULL )
, ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
+ , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL )
, ::getCppuType( ( const uno::Reference< util::XModifiable >* )NULL )
, ::getCppuType( ( const uno::Reference< container::XNameAccess >* )NULL )
, ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
@@ -1335,6 +1418,7 @@ uno::Sequence< uno::Type > SAL_CALL OStorage::getTypes()
m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
, ::getCppuType( ( const uno::Reference< embed::XStorage >* )NULL )
+ , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
, ::getCppuType( ( const uno::Reference< util::XModifiable >* )NULL )
, ::getCppuType( ( const uno::Reference< container::XNameAccess >* )NULL )
, ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
@@ -1754,43 +1838,36 @@ void SAL_CALL OStorage::commit()
if ( !m_pImpl )
throw lang::DisposedException();
- OSL_ENSURE( m_pImpl->m_bIsRoot, "commit() method is not available for nonroot storages!\n" );
-
- if ( m_pImpl->m_bIsRoot )
- {
-
- if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) )
- throw io::IOException(); // TODO: access_denied
+ if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) )
+ throw io::IOException(); // TODO: access_denied
- if ( !m_pImpl->m_bListCreated )
- return; // nothing was changed
+ if ( !m_pImpl->m_bListCreated )
+ return; // nothing was changed
- m_pImpl->m_bCommited = sal_True;
- if ( m_pImpl->m_bIsRoot )
- {
- try {
- m_pImpl->Commit(); // the root storage initiates the main commit
- }
- catch( io::IOException& )
- {
- throw;
- }
- catch( embed::StorageWTException& )
- {
- throw;
- }
- catch( uno::RuntimeException& )
- {
- throw;
- }
- catch( uno::Exception& e )
- {
- throw embed::StorageWTException( ::rtl::OUString::createFromAscii( "Problems on commit!" ),
- uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ),
- uno::makeAny( e ) );
- }
- }
+ try {
+ BroadcastTransaction( STOR_MESS_PRECOMMIT );
+ m_pImpl->Commit(); // the root storage initiates the storing to source
}
+ catch( io::IOException& )
+ {
+ throw;
+ }
+ catch( embed::StorageWTException& )
+ {
+ throw;
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& e )
+ {
+ throw embed::StorageWTException( ::rtl::OUString::createFromAscii( "Problems on commit!" ),
+ uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ),
+ uno::makeAny( e ) );
+ }
+
+ BroadcastTransaction( STOR_MESS_COMMITED );
}
//-----------------------------------------------
@@ -1799,48 +1876,83 @@ void SAL_CALL OStorage::revert()
embed::StorageWTException,
uno::RuntimeException )
{
- // the method is reload actually
- // TODO: real revert should be implemented and used for substorages
- // for now thay does not provide this method
+ // the method removes all the changes done after last commit
::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
if ( !m_pImpl )
throw lang::DisposedException();
- OSL_ENSURE( m_pImpl->m_bIsRoot, "revert() method is not available for nonroot storages!\n" );
+ 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 )
+ throw io::IOException(); // TODO: access denied
- if ( m_pImpl->m_bIsRoot )
- {
- if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) || !m_pImpl->m_bListCreated )
- return; // nothing to do
+ if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::ELEMENT_WRITE ) || !m_pImpl->m_bListCreated )
+ return; // nothing to do
- try {
- m_pImpl->Revert();
- }
- catch( io::IOException& )
- {
- throw;
- }
- catch( embed::StorageWTException& )
- {
- throw;
- }
- catch( uno::RuntimeException& )
- {
- throw;
- }
- catch( uno::Exception& e )
- {
- throw embed::StorageWTException( ::rtl::OUString::createFromAscii( "Problems on revert!" ),
- uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ),
- uno::makeAny( e ) );
- }
+ try {
+ BroadcastTransaction( STOR_MESS_PREREVERT );
+ m_pImpl->Revert();
+ }
+ catch( io::IOException& )
+ {
+ throw;
+ }
+ catch( embed::StorageWTException& )
+ {
+ throw;
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& e )
+ {
+ throw embed::StorageWTException( ::rtl::OUString::createFromAscii( "Problems on revert!" ),
+ uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ),
+ uno::makeAny( e ) );
}
+
+ BroadcastTransaction( STOR_MESS_REVERTED );
+}
+
+//____________________________________________________________________________________________________
+// XTransactionBroadcaster
+//____________________________________________________________________________________________________
+
+//-----------------------------------------------
+void SAL_CALL OStorage::addTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
+
+ if ( !m_pImpl )
+ throw lang::DisposedException();
+
+ m_pData->m_aListenersContainer.addInterface( ::getCppuType((const uno::Reference< embed::XTransactionListener >*)0),
+ aListener );
+}
+
+//-----------------------------------------------
+void SAL_CALL OStorage::removeTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
+
+ if ( !m_pImpl )
+ throw lang::DisposedException();
+
+ m_pData->m_aListenersContainer.removeInterface( ::getCppuType((const uno::Reference< embed::XTransactionListener >*)0),
+ aListener );
}
//____________________________________________________________________________________________________
// XModifiable
+// TODO: if there will be no demand on this interface it will be removed from implementation,
+// I do not want to remove it now since it is still possible that it will be inserted
+// to the service back.
//____________________________________________________________________________________________________
//-----------------------------------------------
@@ -2040,7 +2152,10 @@ void SAL_CALL OStorage::dispose()
if ( m_pImpl->m_bIsRoot )
delete m_pImpl;
else
- m_pImpl->DisposeChildren();
+ {
+ // the noncommited changes for the storage must be removed
+ m_pImpl->Revert();
+ }
m_pImpl = NULL;
}
@@ -2147,6 +2262,7 @@ void SAL_CALL OStorage::setPropertyValue( const ::rtl::OUString& aPropertyName,
if ( aPropertyName.equalsAscii( "MediaType" ) )
{
aValue >>= m_pImpl->m_aMediaType;
+ m_pImpl->m_bControlMediaType = sal_True;
}
else if ( m_pImpl->m_bIsRoot && ( aPropertyName.equalsAscii( "HasEncryptedEntries" )
|| aPropertyName.equalsAscii( "URL" )