diff options
Diffstat (limited to 'embeddedobj/source/msole/olepersist.cxx')
-rw-r--r-- | embeddedobj/source/msole/olepersist.cxx | 2161 |
1 files changed, 2161 insertions, 0 deletions
diff --git a/embeddedobj/source/msole/olepersist.cxx b/embeddedobj/source/msole/olepersist.cxx new file mode 100644 index 000000000000..541c9e9585d0 --- /dev/null +++ b/embeddedobj/source/msole/olepersist.cxx @@ -0,0 +1,2161 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" + +#include <oleembobj.hxx> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/EmbedVerbs.hpp> +#include <com/sun/star/embed/EntryInitModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/EmbedUpdateModes.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/embed/XOptimizedStorage.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> + +#include <rtl/logfile.hxx> + +#include <comphelper/storagehelper.hxx> +#include <comphelper/mimeconfighelper.hxx> +#include <comphelper/classids.hxx> + + +#include <olecomponent.hxx> +#include <closepreventer.hxx> + +using namespace ::com::sun::star; +using namespace ::comphelper; + +//------------------------------------------------------------------------- +sal_Bool KillFile_Impl( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +{ + if ( !xFactory.is() ) + return sal_False; + + sal_Bool bRet = sal_False; + + try + { + uno::Reference < ucb::XSimpleFileAccess > xAccess( + xFactory->createInstance ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.SimpleFileAccess" ) )), + uno::UNO_QUERY ); + + if ( xAccess.is() ) + { + xAccess->kill( aURL ); + bRet = sal_True; + } + } + catch( uno::Exception& ) + { + } + + return bRet; +} + +//---------------------------------------------- +::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +{ + OSL_ENSURE( xFactory.is(), "No factory is provided!\n" ); + + ::rtl::OUString aResult; + + uno::Reference < beans::XPropertySet > xTempFile( + xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) )), + uno::UNO_QUERY ); + + if ( !xTempFile.is() ) + throw uno::RuntimeException(); // TODO + + try { + xTempFile->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "RemoveFile" )), uno::makeAny( sal_False ) ); + uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Uri" ) )); + aUrl >>= aResult; + } + catch ( uno::Exception& ) + { + } + + if ( !aResult.getLength() ) + throw uno::RuntimeException(); // TODO: can not create tempfile + + return aResult; +} + +//----------------------------------------------- +::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) + throw ( io::IOException, + uno::RuntimeException ) +{ + OSL_ENSURE( xInStream.is() && xFactory.is(), "Wrong parameters are provided!\n" ); + + ::rtl::OUString aResult = GetNewTempFileURL_Impl( xFactory ); + + if ( aResult.getLength() ) + { + try { + uno::Reference < ucb::XSimpleFileAccess > xTempAccess( + xFactory->createInstance ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.SimpleFileAccess" ) )), + uno::UNO_QUERY ); + + if ( !xTempAccess.is() ) + throw uno::RuntimeException(); // TODO: + + uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aResult ); + if ( xTempOutStream.is() ) + { + // copy stream contents to the file + ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream ); + xTempOutStream->closeOutput(); + xTempOutStream = uno::Reference< io::XOutputStream >(); + } + else + throw io::IOException(); // TODO: + } + catch( packages::WrongPasswordException& ) + { + KillFile_Impl( aResult, xFactory ); + throw io::IOException(); //TODO: + } + catch( io::IOException& ) + { + KillFile_Impl( aResult, xFactory ); + throw; + } + catch( uno::RuntimeException& ) + { + KillFile_Impl( aResult, xFactory ); + throw; + } + catch( uno::Exception& ) + { + KillFile_Impl( aResult, xFactory ); + aResult = ::rtl::OUString(); + } + } + + return aResult; +} +#ifdef WNT +::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< embed::XOptimizedStorage >& xParentStorage, const ::rtl::OUString& aEntryName, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) + throw( io::IOException, uno::RuntimeException ) +{ + ::rtl::OUString aResult; + + try + { + uno::Reference < beans::XPropertySet > xTempFile( + xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) )), + uno::UNO_QUERY ); + uno::Reference < io::XStream > xTempStream( xTempFile, uno::UNO_QUERY_THROW ); + + xParentStorage->copyStreamElementData( aEntryName, xTempStream ); + + xTempFile->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "RemoveFile" )), uno::makeAny( sal_False ) ); + uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Uri" ) )); + aUrl >>= aResult; + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + } + + if ( !aResult.getLength() ) + throw io::IOException(); + + return aResult; +} + +//------------------------------------------------------ +void SetStreamMediaType_Impl( const uno::Reference< io::XStream >& xStream, const ::rtl::OUString& aMediaType ) +{ + uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY ); + if ( !xPropSet.is() ) + throw uno::RuntimeException(); // TODO: all the storage streams must support XPropertySet + + xPropSet->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "MediaType" )), uno::makeAny( aMediaType ) ); +} +#endif +//------------------------------------------------------ +void LetCommonStoragePassBeUsed_Impl( const uno::Reference< io::XStream >& xStream ) +{ + uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY ); + if ( !xPropSet.is() ) + throw uno::RuntimeException(); // Only StorageStreams must be provided here, they must implement the interface + + xPropSet->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" )), + uno::makeAny( (sal_Bool)sal_True ) ); +} +#ifdef WNT +//------------------------------------------------------ +void VerbExecutionController::StartControlExecution() +{ + osl::MutexGuard aGuard( m_aVerbExecutionMutex ); + + // the class is used to detect STAMPIT object, that can never be active + if ( !m_bVerbExecutionInProgress && !m_bWasEverActive ) + { + m_bVerbExecutionInProgress = sal_True; + m_nVerbExecutionThreadIdentifier = osl_getThreadIdentifier( NULL ); + m_bChangedOnVerbExecution = sal_False; + } +} + +//------------------------------------------------------ +sal_Bool VerbExecutionController::EndControlExecution_WasModified() +{ + osl::MutexGuard aGuard( m_aVerbExecutionMutex ); + + sal_Bool bResult = sal_False; + if ( m_bVerbExecutionInProgress && m_nVerbExecutionThreadIdentifier == osl_getThreadIdentifier( NULL ) ) + { + bResult = m_bChangedOnVerbExecution; + m_bVerbExecutionInProgress = sal_False; + } + + return bResult; +} + +//------------------------------------------------------ +void VerbExecutionController::ModificationNotificationIsDone() +{ + osl::MutexGuard aGuard( m_aVerbExecutionMutex ); + + if ( m_bVerbExecutionInProgress && osl_getThreadIdentifier( NULL ) == m_nVerbExecutionThreadIdentifier ) + m_bChangedOnVerbExecution = sal_True; +} +#endif +//----------------------------------------------- +void VerbExecutionController::LockNotification() +{ + osl::MutexGuard aGuard( m_aVerbExecutionMutex ); + if ( m_nNotificationLock < SAL_MAX_INT32 ) + m_nNotificationLock++; +} + +//----------------------------------------------- +void VerbExecutionController::UnlockNotification() +{ + osl::MutexGuard aGuard( m_aVerbExecutionMutex ); + if ( m_nNotificationLock > 0 ) + m_nNotificationLock--; +} + +//----------------------------------------------- +uno::Reference< io::XStream > OleEmbeddedObject::GetNewFilledTempStream_Impl( const uno::Reference< io::XInputStream >& xInStream ) + throw( io::IOException ) +{ + OSL_ENSURE( xInStream.is(), "Wrong parameter is provided!\n" ); + + uno::Reference < io::XStream > xTempFile( + m_xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) )), + uno::UNO_QUERY_THROW ); + + uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream(); + if ( xTempOutStream.is() ) + { + ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream ); + xTempOutStream->flush(); + } + else + throw io::IOException(); // TODO: + + return xTempFile; +} + +//------------------------------------------------------ +uno::Reference< io::XStream > OleEmbeddedObject::TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream ) + throw ( uno::Exception ) +{ + // TODO/LATER: Actually this should be done by a centralized component ( may be a graphical filter ) + if ( !m_xFactory.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XInputStream > xInStream = xStream->getInputStream(); + if ( !xInStream.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW ); + xSeek->seek( 0 ); + + uno::Sequence< sal_Int8 > aData( 8 ); + sal_Int32 nRead = xInStream->readBytes( aData, 8 ); + xSeek->seek( 0 ); + + if ( ( nRead >= 2 && aData[0] == 'B' && aData[1] == 'M' ) + || ( nRead >= 4 && aData[0] == 1 && aData[1] == 0 && aData[2] == 9 && aData[3] == 0 ) ) + { + // it should be a bitmap or a Metafile + return xStream; + } + +// sal_Bool bSetSizeToRepl = sal_False; +// awt::Size aSizeToSet; + + sal_uInt32 nHeaderOffset = 0; + if ( ( nRead >= 8 && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1 ) + && ( aData[4] == 2 || aData[4] == 3 || aData[4] == 14 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 ) + { + nHeaderOffset = 40; + xSeek->seek( 8 ); + + // TargetDevice might be used in future, currently the cache has specified NULL + uno::Sequence< sal_Int8 > aHeadData( 4 ); + nRead = xInStream->readBytes( aHeadData, 4 ); + sal_uInt32 nLen = 0; + if ( nRead == 4 && aHeadData.getLength() == 4 ) + nLen = ( ( ( (sal_uInt32)aHeadData[3] * 0x100 + (sal_uInt32)aHeadData[2] ) * 0x100 ) + (sal_uInt32)aHeadData[1] ) * 0x100 + (sal_uInt32)aHeadData[0]; + if ( nLen > 4 ) + { + xInStream->skipBytes( nLen - 4 ); + nHeaderOffset += nLen - 4; + } + +// if ( aData[4] == 3 ) +// { +// try +// { +// +// aSizeToSet = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); +// aSizeToSet.Width /= 364; //2540; // let the size be in inches, as wmf requires +// aSizeToSet.Height /= 364; //2540; // let the size be in inches, as wmf requires +// bSetSizeToRepl = sal_True; +// } +// catch( uno::Exception& ) +// {} +// } + } + else if ( nRead > 4 ) + { + // check whether the first bytes represent the size + sal_uInt32 nSize = 0; + for ( sal_Int32 nInd = 3; nInd >= 0; nInd-- ) + nSize = ( nSize << 8 ) + (sal_uInt8)aData[nInd]; + + if ( nSize == xSeek->getLength() - 4 ) + nHeaderOffset = 4; + } + + if ( nHeaderOffset ) + { + // this is either a bitmap or a metafile clipboard format, retrieve the pure stream + uno::Reference < io::XStream > xResult( + m_xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) )), + uno::UNO_QUERY_THROW ); + uno::Reference < io::XSeekable > xResultSeek( xResult, uno::UNO_QUERY_THROW ); + uno::Reference < io::XOutputStream > xResultOut = xResult->getOutputStream(); + uno::Reference < io::XInputStream > xResultIn = xResult->getInputStream(); + if ( !xResultOut.is() || !xResultIn.is() ) + throw uno::RuntimeException(); + + xSeek->seek( nHeaderOffset ); // header size for these formats + ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xResultOut ); + xResultOut->closeOutput(); + xResultSeek->seek( 0 ); + xSeek->seek( 0 ); + + return xResult; + } + + return uno::Reference< io::XStream >(); +} + +//------------------------------------------------------ +void OleEmbeddedObject::InsertVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream, + const uno::Reference< io::XStream >& xCachedVisualRepresentation ) + throw ( uno::Exception ) +{ + OSL_ENSURE( xTargetStream.is() && xCachedVisualRepresentation.is(), "Invalid argumants!\n" ); + + if ( !xTargetStream.is() || !xCachedVisualRepresentation.is() ) + throw uno::RuntimeException(); + + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xTargetStream; + aArgs[1] <<= (sal_Bool)sal_True; // do not create copy + + uno::Reference< container::XNameContainer > xNameContainer( + m_xFactory->createInstanceWithArguments( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.OLESimpleStorage" )), + aArgs ), + uno::UNO_QUERY ); + + if ( !xNameContainer.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY_THROW ); + if ( xCachedSeek.is() ) + xCachedSeek->seek( 0 ); + + uno::Reference < io::XStream > xTempFile( + m_xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) )), + uno::UNO_QUERY_THROW ); + + uno::Reference< io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW ); + uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream(); + if ( xTempOutStream.is() ) + { + // the OlePres stream must have additional header + // TODO/LATER: might need to be extended in future ( actually makes sence only for SO7 format ) + uno::Reference< io::XInputStream > xInCacheStream = xCachedVisualRepresentation->getInputStream(); + if ( !xInCacheStream.is() ) + throw uno::RuntimeException(); + + // write 0xFFFFFFFF at the beginning + uno::Sequence< sal_Int8 > aData( 4 ); + *( (sal_uInt32*)aData.getArray() ) = 0xFFFFFFFF; + + xTempOutStream->writeBytes( aData ); + + // write clipboard format + uno::Sequence< sal_Int8 > aSigData( 2 ); + xInCacheStream->readBytes( aSigData, 2 ); + if ( aSigData.getLength() < 2 ) + throw io::IOException(); + + if ( aSigData[0] == 'B' && aSigData[1] == 'M' ) + { + // it's a bitmap + aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0; + } + else + { + // treat it as a metafile + aData[0] = 0x03; aData[1] = 0; aData[2] = 0; aData[3] = 0; + } + xTempOutStream->writeBytes( aData ); + + // write job related information + aData[0] = 0x04; aData[1] = 0; aData[2] = 0; aData[3] = 0; + xTempOutStream->writeBytes( aData ); + + // write aspect + aData[0] = 0x01; aData[1] = 0; aData[2] = 0; aData[3] = 0; + xTempOutStream->writeBytes( aData ); + + // write l-index + *( (sal_uInt32*)aData.getArray() ) = 0xFFFFFFFF; + xTempOutStream->writeBytes( aData ); + + // write adv. flags + aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0; + xTempOutStream->writeBytes( aData ); + + // write compression + *( (sal_uInt32*)aData.getArray() ) = 0x0; + xTempOutStream->writeBytes( aData ); + + // get the size + awt::Size aSize = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); + sal_Int32 nIndex = 0; + + // write width + for ( nIndex = 0; nIndex < 4; nIndex++ ) + { + aData[nIndex] = (sal_Int8)( aSize.Width % 0x100 ); + aSize.Width /= 0x100; + } + xTempOutStream->writeBytes( aData ); + + // write height + for ( nIndex = 0; nIndex < 4; nIndex++ ) + { + aData[nIndex] = (sal_Int8)( aSize.Height % 0x100 ); + aSize.Height /= 0x100; + } + xTempOutStream->writeBytes( aData ); + + // write garbage, it will be overwritten by the size + xTempOutStream->writeBytes( aData ); + + // write first bytes that was used to detect the type + xTempOutStream->writeBytes( aSigData ); + + // write the rest of the stream + ::comphelper::OStorageHelper::CopyInputToOutput( xInCacheStream, xTempOutStream ); + + // write the size of the stream + sal_Int64 nLength = xTempSeek->getLength() - 40; + if ( nLength < 0 || nLength >= 0xFFFFFFFF ) + { + OSL_FAIL( "Length is not acceptable!" ); + return; + } + for ( sal_Int32 nInd = 0; nInd < 4; nInd++ ) + { + aData[nInd] = (sal_Int8)( ( (sal_uInt64) nLength ) % 0x100 ); + nLength /= 0x100; + } + xTempSeek->seek( 36 ); + xTempOutStream->writeBytes( aData ); + + xTempOutStream->flush(); + + xTempSeek->seek( 0 ); + if ( xCachedSeek.is() ) + xCachedSeek->seek( 0 ); + } + else + throw io::IOException(); // TODO: + + // insert the result file as replacement image + ::rtl::OUString aCacheName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "\002OlePres000" )); + if ( xNameContainer->hasByName( aCacheName ) ) + xNameContainer->replaceByName( aCacheName, uno::makeAny( xTempFile ) ); + else + xNameContainer->insertByName( aCacheName, uno::makeAny( xTempFile ) ); + + uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY ); + if ( !xTransacted.is() ) + throw uno::RuntimeException(); + + xTransacted->commit(); +} + +//------------------------------------------------------ +void OleEmbeddedObject::RemoveVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream ) + throw ( uno::Exception ) +{ + OSL_ENSURE( xTargetStream.is(), "Invalid argumant!\n" ); + if ( !xTargetStream.is() ) + throw uno::RuntimeException(); + + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xTargetStream; + aArgs[1] <<= (sal_Bool)sal_True; // do not create copy + uno::Reference< container::XNameContainer > xNameContainer( + m_xFactory->createInstanceWithArguments( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.OLESimpleStorage" )), + aArgs ), + uno::UNO_QUERY ); + + if ( !xNameContainer.is() ) + throw uno::RuntimeException(); + + for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ ) + { + ::rtl::OUString aStreamName(RTL_CONSTASCII_USTRINGPARAM( "\002OlePres00" )); + aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd ); + if ( xNameContainer->hasByName( aStreamName ) ) + xNameContainer->removeByName( aStreamName ); + } + + uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY ); + if ( !xTransacted.is() ) + throw uno::RuntimeException(); + + xTransacted->commit(); +} + +//------------------------------------------------------ +void OleEmbeddedObject::SetVisReplInStream( sal_Bool bExists ) +{ + m_bVisReplInitialized = sal_True; + m_bVisReplInStream = bExists; +} + +//------------------------------------------------------ +sal_Bool OleEmbeddedObject::HasVisReplInStream() +{ + if ( !m_bVisReplInitialized ) + { + if ( m_xCachedVisualRepresentation.is() ) + SetVisReplInStream( sal_True ); + else + { + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::HasVisualReplInStream, analizing" ); + + uno::Reference< io::XInputStream > xStream; + + OSL_ENSURE( !m_pOleComponent || m_aTempURL.getLength(), "The temporary file must exist if there is a component!\n" ); + if ( m_aTempURL.getLength() ) + { + try + { + // open temporary file for reading + uno::Reference < ucb::XSimpleFileAccess > xTempAccess( + m_xFactory->createInstance ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.SimpleFileAccess" ) )), + uno::UNO_QUERY ); + + if ( !xTempAccess.is() ) + throw uno::RuntimeException(); // TODO: + + xStream = xTempAccess->openFileRead( m_aTempURL ); + } + catch( uno::Exception& ) + {} + } + + if ( !xStream.is() ) + xStream = m_xObjectStream->getInputStream(); + + if ( xStream.is() ) + { + sal_Bool bExists = sal_False; + + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xStream; + aArgs[1] <<= (sal_Bool)sal_True; // do not create copy + uno::Reference< container::XNameContainer > xNameContainer( + m_xFactory->createInstanceWithArguments( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.OLESimpleStorage" )), + aArgs ), + uno::UNO_QUERY ); + + if ( xNameContainer.is() ) + { + for ( sal_uInt8 nInd = 0; nInd < 10 && !bExists; nInd++ ) + { + ::rtl::OUString aStreamName(RTL_CONSTASCII_USTRINGPARAM( "\002OlePres00" )); + aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd ); + try + { + bExists = xNameContainer->hasByName( aStreamName ); + } + catch( uno::Exception& ) + {} + } + } + + SetVisReplInStream( bExists ); + } + } + } + + return m_bVisReplInStream; +} + +//------------------------------------------------------ +uno::Reference< io::XStream > OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation_Impl( + const uno::Reference< io::XStream >& xStream, + sal_Bool bAllowToRepair50 ) + throw () +{ + uno::Reference< io::XStream > xResult; + + if ( xStream.is() ) + { + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation, retrieving" ); + + uno::Reference< container::XNameContainer > xNameContainer; + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xStream; + aArgs[1] <<= (sal_Bool)sal_True; // do not create copy + try + { + xNameContainer = uno::Reference< container::XNameContainer >( + m_xFactory->createInstanceWithArguments( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.OLESimpleStorage" )), + aArgs ), + uno::UNO_QUERY ); + } + catch( uno::Exception& ) + {} + + if ( xNameContainer.is() ) + { + for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ ) + { + ::rtl::OUString aStreamName(RTL_CONSTASCII_USTRINGPARAM( "\002OlePres00" )); + aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd ); + uno::Reference< io::XStream > xCachedCopyStream; + try + { + if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() ) + { + xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream ); + if ( xResult.is() ) + break; + } + } + catch( uno::Exception& ) + {} + + if ( nInd == 0 ) + { + // to be compatible with the old versions Ole10Native is checked after OlePress000 + aStreamName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\001Ole10Native" ) ); + try + { + if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() ) + { + xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream ); + if ( xResult.is() ) + break; + } + } + catch( uno::Exception& ) + {} + } + } + + try + { + if ( bAllowToRepair50 && !xResult.is() ) + { + ::rtl::OUString aOrigContName( RTL_CONSTASCII_USTRINGPARAM( "Ole-Object" ) ); + if ( xNameContainer->hasByName( aOrigContName ) ) + { + uno::Reference< embed::XClassifiedObject > xClassified( xNameContainer, uno::UNO_QUERY_THROW ); + uno::Sequence< sal_Int8 > aClassID; + if ( MimeConfigurationHelper::ClassIDsEqual( xClassified->getClassID(), MimeConfigurationHelper::GetSequenceClassID( SO3_OUT_CLASSID ) ) ) + { + // this is an OLE object wrongly stored in 5.0 format + // this object must be repaired since SO7 has done it + + uno::Reference< io::XOutputStream > xOutputStream = xStream->getOutputStream(); + uno::Reference< io::XTruncate > xTruncate( xOutputStream, uno::UNO_QUERY_THROW ); + + uno::Reference< io::XInputStream > xOrigInputStream; + if ( ( xNameContainer->getByName( aOrigContName ) >>= xOrigInputStream ) + && xOrigInputStream.is() ) + { + // the provided input stream must be based on temporary medium and must be independent + // from the stream the storage is based on + uno::Reference< io::XSeekable > xOrigSeekable( xOrigInputStream, uno::UNO_QUERY ); + if ( xOrigSeekable.is() ) + xOrigSeekable->seek( 0 ); + + uno::Reference< lang::XComponent > xNameContDisp( xNameContainer, uno::UNO_QUERY_THROW ); + xNameContDisp->dispose(); // free the original stream + + xTruncate->truncate(); + ::comphelper::OStorageHelper::CopyInputToOutput( xOrigInputStream, xOutputStream ); + xOutputStream->flush(); + + if ( xStream == m_xObjectStream ) + { + if ( m_aTempURL.getLength() ) + { + // this is the own stream, so the temporary URL must be cleaned if it exists + KillFile_Impl( m_aTempURL, m_xFactory ); + m_aTempURL = ::rtl::OUString(); + } + +#ifdef WNT + // retry to create the component after recovering + GetRidOfComponent(); + + try + { + CreateOleComponentAndLoad_Impl( NULL ); + m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction + } + catch( uno::Exception& ) + { + GetRidOfComponent(); + } +#endif + } + + xResult = TryToRetrieveCachedVisualRepresentation_Impl( xStream, sal_False ); + } + } + } + } + } + catch( uno::Exception& ) + {} + } + } + + return xResult; +} + +//------------------------------------------------------ +void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage, + const uno::Reference< io::XStream >& xNewObjectStream, + const ::rtl::OUString& aNewName ) +{ + if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) ) + { + OSL_ENSURE( xNewObjectStream == m_xObjectStream, "The streams must be the same!\n" ); + return; + } + + try { + uno::Reference< lang::XComponent > xComponent( m_xObjectStream, uno::UNO_QUERY ); + OSL_ENSURE( !m_xObjectStream.is() || xComponent.is(), "Wrong stream implementation!" ); + if ( xComponent.is() ) + xComponent->dispose(); + } + catch ( uno::Exception& ) + { + } + + m_xObjectStream = xNewObjectStream; + m_xParentStorage = xNewParentStorage; + m_aEntryName = aNewName; +} + +//------------------------------------------------------ +void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage, + const ::rtl::OUString& aNewName ) +{ + if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) ) + return; + + sal_Int32 nStreamMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE; + + uno::Reference< io::XStream > xNewOwnStream = xNewParentStorage->openStreamElement( aNewName, nStreamMode ); + OSL_ENSURE( xNewOwnStream.is(), "The method can not return empty reference!" ); + + SwitchOwnPersistence( xNewParentStorage, xNewOwnStream, aNewName ); +} + +#ifdef WNT +//---------------------------------------------- +sal_Bool OleEmbeddedObject::SaveObject_Impl() +{ + sal_Bool bResult = sal_False; + + if ( m_xClientSite.is() ) + { + try + { + m_xClientSite->saveObject(); + bResult = sal_True; + } + catch( uno::Exception& ) + { + } + } + + return bResult; +} + +//---------------------------------------------- +sal_Bool OleEmbeddedObject::OnShowWindow_Impl( sal_Bool bShow ) +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + + sal_Bool bResult = sal_False; + + OSL_ENSURE( m_nObjectState != -1, "The object has no persistence!\n" ); + OSL_ENSURE( m_nObjectState != embed::EmbedStates::LOADED, "The object get OnShowWindow in loaded state!\n" ); + if ( m_nObjectState == -1 || m_nObjectState == embed::EmbedStates::LOADED ) + return sal_False; + + // the object is either activated or deactivated + sal_Int32 nOldState = m_nObjectState; + if ( bShow && m_nObjectState == embed::EmbedStates::RUNNING ) + { + m_nObjectState = embed::EmbedStates::ACTIVE; + m_aVerbExecutionController.ObjectIsActive(); + + aGuard.clear(); + StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + } + else if ( !bShow && m_nObjectState == embed::EmbedStates::ACTIVE ) + { + m_nObjectState = embed::EmbedStates::RUNNING; + aGuard.clear(); + StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + } + + if ( m_xClientSite.is() ) + { + try + { + m_xClientSite->visibilityChanged( bShow ); + bResult = sal_True; + } + catch( uno::Exception& ) + { + } + } + + return bResult; +} + +//------------------------------------------------------ +void OleEmbeddedObject::OnIconChanged_Impl() +{ + // TODO/LATER: currently this notification seems to be impossible + // MakeEventListenerNotification_Impl( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "OnIconChanged" )) ); +} + +//------------------------------------------------------ +void OleEmbeddedObject::OnViewChanged_Impl() +{ + if ( m_bDisposed ) + throw lang::DisposedException(); + + // For performance reasons the notification currently is ignored, STAMPIT object is the exception, + // it can never be active and never call SaveObject, so it is the only way to detect that it is changed + + // ==== the STAMPIT related solution ============================= + // the following variable is used to detect whether the object was modified during verb execution + m_aVerbExecutionController.ModificationNotificationIsDone(); + + // The following things are controlled by VerbExecutionController: + // - if the verb execution is in progress and the view is changed the object will be stored + // after the execution, so there is no need to send the notification. + // - the STAMPIT object can never be active. + if ( m_aVerbExecutionController.CanDoNotification() + && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE ) + { + OSL_ENSURE( MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0x852ee1c9, 0x9058, 0x44ba, 0x8c,0x6c,0x0c,0x5f,0xc6,0x6b,0xdb,0x8d ) ) + || MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0xcf1b4491, 0xbea3, 0x4c9f, 0xa7,0x0f,0x22,0x1b,0x1e,0xca,0xef,0x3e ) ), + "Expected to be triggered for STAMPIT only! Please contact developers!\n" ); + + // The view is changed while the object is in running state, save the new object + m_xCachedVisualRepresentation = uno::Reference< io::XStream >(); + SaveObject_Impl(); + MakeEventListenerNotification_Impl( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "OnVisAreaChanged" )) ); + } + // =============================================================== +} + +//------------------------------------------------------ +void OleEmbeddedObject::OnClosed_Impl() +{ + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( m_nObjectState != embed::EmbedStates::LOADED ) + { + sal_Int32 nOldState = m_nObjectState; + m_nObjectState = embed::EmbedStates::LOADED; + StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + } +} + +//------------------------------------------------------ +::rtl::OUString OleEmbeddedObject::CreateTempURLEmpty_Impl() +{ + OSL_ENSURE( !m_aTempURL.getLength(), "The object has already the temporary file!" ); + m_aTempURL = GetNewTempFileURL_Impl( m_xFactory ); + + return m_aTempURL; +} + +//------------------------------------------------------ +::rtl::OUString OleEmbeddedObject::GetTempURL_Impl() +{ + if ( !m_aTempURL.getLength() ) + { + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::GetTempURL_Impl, tempfile creation" ); + + // if there is no temporary file, it will be created from the own entry + uno::Reference< embed::XOptimizedStorage > xOptParStorage( m_xParentStorage, uno::UNO_QUERY ); + if ( xOptParStorage.is() ) + { + m_aTempURL = GetNewFilledTempFile_Impl( xOptParStorage, m_aEntryName, m_xFactory ); + } + else if ( m_xObjectStream.is() ) + { + // load object from the stream + uno::Reference< io::XInputStream > xInStream = m_xObjectStream->getInputStream(); + if ( !xInStream.is() ) + throw io::IOException(); // TODO: access denied + + m_aTempURL = GetNewFilledTempFile_Impl( xInStream, m_xFactory ); + } + } + + return m_aTempURL; +} + +//------------------------------------------------------ +void OleEmbeddedObject::CreateOleComponent_Impl( OleComponent* pOleComponent ) +{ + if ( !m_pOleComponent ) + { + m_pOleComponent = pOleComponent ? pOleComponent : new OleComponent( m_xFactory, this ); + m_pOleComponent->acquire(); // TODO: needs holder? + + if ( !m_xClosePreventer.is() ) + m_xClosePreventer = uno::Reference< util::XCloseListener >( + static_cast< ::cppu::OWeakObject* >( new OClosePreventer ), + uno::UNO_QUERY ); + + m_pOleComponent->addCloseListener( m_xClosePreventer ); + } +} + +//------------------------------------------------------ +void OleEmbeddedObject::CreateOleComponentAndLoad_Impl( OleComponent* pOleComponent ) +{ + if ( !m_pOleComponent ) + { + if ( !m_xObjectStream.is() ) + throw uno::RuntimeException(); + + CreateOleComponent_Impl( pOleComponent ); + + // after the loading the object can appear as a link + // will be detected later by olecomponent + + GetTempURL_Impl(); + if ( !m_aTempURL.getLength() ) + throw uno::RuntimeException(); // TODO + + m_pOleComponent->LoadEmbeddedObject( m_aTempURL ); + } +} + +//------------------------------------------------------ +void OleEmbeddedObject::CreateOleComponentFromClipboard_Impl( OleComponent* pOleComponent ) +{ + if ( !m_pOleComponent ) + { + if ( !m_xObjectStream.is() ) + throw uno::RuntimeException(); + + CreateOleComponent_Impl( pOleComponent ); + + // after the loading the object can appear as a link + // will be detected later by olecomponent + m_pOleComponent->CreateObjectFromClipboard(); + } +} + +//------------------------------------------------------ +uno::Reference< io::XOutputStream > OleEmbeddedObject::GetStreamForSaving() +{ + if ( !m_xObjectStream.is() ) + throw uno::RuntimeException(); //TODO: + + uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream(); + if ( !xOutStream.is() ) + throw io::IOException(); //TODO: access denied + + uno::Reference< io::XTruncate > xTruncate( xOutStream, uno::UNO_QUERY ); + if ( !xTruncate.is() ) + throw uno::RuntimeException(); //TODO: + + xTruncate->truncate(); + + return xOutStream; +} + +//---------------------------------------------- +void OleEmbeddedObject::StoreObjectToStream( uno::Reference< io::XOutputStream > xOutStream ) + throw ( uno::Exception ) +{ + // this method should be used only on windows + if ( m_pOleComponent ) + m_pOleComponent->StoreOwnTmpIfNecessary(); + + // now all the changes should be in temporary location + if ( !m_aTempURL ) + throw uno::RuntimeException(); + + // open temporary file for reading + uno::Reference < ucb::XSimpleFileAccess > xTempAccess( + m_xFactory->createInstance ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.SimpleFileAccess" ) )), + uno::UNO_QUERY ); + + if ( !xTempAccess.is() ) + throw uno::RuntimeException(); // TODO: + + uno::Reference< io::XInputStream > xTempInStream = xTempAccess->openFileRead( m_aTempURL ); + OSL_ENSURE( xTempInStream.is(), "The object's temporary file can not be reopened for reading!\n" ); + + // TODO: use bStoreVisReplace + + if ( xTempInStream.is() ) + { + // write all the contents to XOutStream + uno::Reference< io::XTruncate > xTrunc( xOutStream, uno::UNO_QUERY ); + if ( !xTrunc.is() ) + throw uno::RuntimeException(); //TODO: + + xTrunc->truncate(); + + ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutStream ); + } + else + throw io::IOException(); // TODO: + + // TODO: should the view replacement be in the stream ??? + // probably it must be specified on storing +} +#endif +//------------------------------------------------------ +void OleEmbeddedObject::StoreToLocation_Impl( + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& /*lArguments*/, + const uno::Sequence< beans::PropertyValue >& lObjArgs, + sal_Bool bSaveAs ) + throw ( uno::Exception ) +{ + // TODO: use lObjArgs + // TODO: exchange StoreVisualReplacement by SO file format version? + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Can't store object without persistence!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object waits for saveCompleted() call!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" ); + + sal_Bool bVisReplIsStored = sal_False; + + sal_Bool bTryOptimization = sal_False; + sal_Bool bStoreVis = m_bStoreVisRepl; + uno::Reference< io::XStream > xCachedVisualRepresentation; + for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ ) + { + if ( lObjArgs[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StoreVisualReplacement" ) ) ) + lObjArgs[nInd].Value >>= bStoreVis; + else if ( lObjArgs[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "VisualReplacement" ) ) ) + lObjArgs[nInd].Value >>= xCachedVisualRepresentation; + else if ( lObjArgs[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CanTryOptimization" ) ) ) + lObjArgs[nInd].Value >>= bTryOptimization; + } + + // ignore visual representation provided from outside if it should not be stored + if ( !bStoreVis ) + xCachedVisualRepresentation = uno::Reference< io::XStream >(); + + if ( bStoreVis && !HasVisReplInStream() && !xCachedVisualRepresentation.is() ) + throw io::IOException(); // TODO: there is no cached visual representation and nothing is provided from outside + + // if the representation is provided from outside it should be copied to a local stream + sal_Bool bNeedLocalCache = xCachedVisualRepresentation.is(); + + uno::Reference< io::XStream > xTargetStream; + + sal_Bool bStoreLoaded = sal_False; + if ( m_nObjectState == embed::EmbedStates::LOADED +#ifdef WNT + // if the object was NOT modified after storing it can be just copied + // as if it was in loaded state + || ( m_pOleComponent && !m_pOleComponent->IsDirty() ) +#endif + ) + { + sal_Bool bOptimizedCopyingDone = sal_False; + + if ( bTryOptimization && bStoreVis == HasVisReplInStream() ) + { + try + { + uno::Reference< embed::XOptimizedStorage > xSourceOptStor( m_xParentStorage, uno::UNO_QUERY_THROW ); + uno::Reference< embed::XOptimizedStorage > xTargetOptStor( xStorage, uno::UNO_QUERY_THROW ); + xSourceOptStor->copyElementDirectlyTo( m_aEntryName, xTargetOptStor, sEntName ); + bOptimizedCopyingDone = sal_True; + } + catch( uno::Exception& ) + { + } + } + + if ( !bOptimizedCopyingDone ) + { + // if optimized copying fails a normal one should be tried + m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName ); + } + + // the locally retrieved representation is always preferable + // since the object is in loaded state the representation is unchanged + if ( m_xCachedVisualRepresentation.is() ) + { + xCachedVisualRepresentation = m_xCachedVisualRepresentation; + bNeedLocalCache = sal_False; + } + + bVisReplIsStored = HasVisReplInStream(); + bStoreLoaded = sal_True; + } +#ifdef WNT + else if ( m_pOleComponent ) + { + xTargetStream = + xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE ); + if ( !xTargetStream.is() ) + throw io::IOException(); //TODO: access denied + + SetStreamMediaType_Impl( xTargetStream, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) )); + uno::Reference< io::XOutputStream > xOutStream = xTargetStream->getOutputStream(); + if ( !xOutStream.is() ) + throw io::IOException(); //TODO: access denied + + StoreObjectToStream( xOutStream ); + bVisReplIsStored = sal_True; + + if ( bSaveAs ) + { + // no need to do it on StoreTo since in this case the replacement is in the stream + // and there is no need to cache it even if it is thrown away because the object + // is not changed by StoreTo action + + uno::Reference< io::XStream > xTmpCVRepresentation = + TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream ); + + // the locally retrieved representation is always preferable + if ( xTmpCVRepresentation.is() ) + { + xCachedVisualRepresentation = xTmpCVRepresentation; + bNeedLocalCache = sal_False; + } + } + } +#endif + else + { + throw io::IOException(); // TODO + } + + if ( !xTargetStream.is() ) + { + xTargetStream = + xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE ); + if ( !xTargetStream.is() ) + throw io::IOException(); //TODO: access denied + } + + LetCommonStoragePassBeUsed_Impl( xTargetStream ); + + if ( bStoreVis != bVisReplIsStored ) + { + if ( bStoreVis ) + { + if ( !xCachedVisualRepresentation.is() ) + xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream ); + + OSL_ENSURE( xCachedVisualRepresentation.is(), "No representation is available!" ); + + // the following copying will be done in case it is SaveAs anyway + // if it is not SaveAs the seekable access is not required currently + // TODO/LATER: may be required in future + if ( bSaveAs ) + { + uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY ); + if ( !xCachedSeek.is() ) + { + xCachedVisualRepresentation + = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() ); + bNeedLocalCache = sal_False; + } + } + + InsertVisualCache_Impl( xTargetStream, xCachedVisualRepresentation ); + } + else + { + // the removed representation could be cached by this method + if ( !xCachedVisualRepresentation.is() ) + xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream ); + + RemoveVisualCache_Impl( xTargetStream ); + } + } + + if ( bSaveAs ) + { + m_bWaitSaveCompleted = sal_True; + m_xNewObjectStream = xTargetStream; + m_xNewParentStorage = xStorage; + m_aNewEntryName = sEntName; + m_bNewVisReplInStream = bStoreVis; + m_bStoreLoaded = bStoreLoaded; + + if ( xCachedVisualRepresentation.is() ) + { + if ( bNeedLocalCache ) + m_xNewCachedVisRepl = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() ); + else + m_xNewCachedVisRepl = xCachedVisualRepresentation; + } + + // TODO: register listeners for storages above, in case they are disposed + // an exception will be thrown on saveCompleted( true ) + } + else + { + uno::Reference< lang::XComponent > xComp( xTargetStream, uno::UNO_QUERY ); + if ( xComp.is() ) + { + try { + xComp->dispose(); + } catch( uno::Exception& ) + { + } + } + } +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::setPersistentEntry( + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + sal_Int32 nEntryConnectionMode, + const uno::Sequence< beans::PropertyValue >& lArguments, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::setPersistentEntry" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->setPersistentEntry( xStorage, sEntName, nEntryConnectionMode, lArguments, lObjArgs ); + return; + } + // end wrapping related part ==================== + + // TODO: use lObjArgs + + // the type of the object must be already set + // a kind of typedetection should be done in the factory; + // the only exception is object initialized from a stream, + // the class ID will be detected from the stream + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "No parent storage is provided!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + if ( !sEntName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Empty element name is provided!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 2 ); + + // May be LOADED should be forbidden here ??? + if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) + && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) ) + { + // if the object is not loaded + // it can not get persistant representation without initialization + + // if the object is loaded + // it can switch persistant representation only without initialization + + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Can't change persistant representation of activated object!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + { + if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) + saveCompleted( ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ) ); + else + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object waits for saveCompleted() call!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY ); + if ( !xNameAccess.is() ) + throw uno::RuntimeException(); //TODO + + // detect entry existence + sal_Bool bElExists = xNameAccess->hasByName( sEntName ); + + m_bReadOnly = sal_False; + sal_Int32 nInd = 0; + for ( nInd = 0; nInd < lArguments.getLength(); nInd++ ) + if ( lArguments[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ReadOnly" ) ) ) + lArguments[nInd].Value >>= m_bReadOnly; + +#ifdef WNT + sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE; +#endif + + SwitchOwnPersistence( xStorage, sEntName ); + + for ( nInd = 0; nInd < lObjArgs.getLength(); nInd++ ) + if ( lObjArgs[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StoreVisualReplacement" ) ) ) + lObjArgs[nInd].Value >>= m_bStoreVisRepl; + +#ifdef WNT + if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT ) + { + if ( m_bFromClipboard ) + { + // the object should be initialized from clipboard + // inpossibility to initialize the object means error here + CreateOleComponentFromClipboard_Impl( NULL ); + m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction + m_pOleComponent->RunObject(); + m_nObjectState = embed::EmbedStates::RUNNING; + } + else if ( bElExists ) + { + // load object from the stream + // after the loading the object can appear as a link + // will be detected by olecomponent + try + { + CreateOleComponentAndLoad_Impl( NULL ); + m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction + } + catch( uno::Exception& ) + { + // TODO/LATER: detect classID of the object if possible + // means that the object inprocess server could not be successfuly instantiated + GetRidOfComponent(); + } + + m_nObjectState = embed::EmbedStates::LOADED; + } + else + { + // create a new object + CreateOleComponent_Impl(); + m_pOleComponent->CreateNewEmbeddedObject( m_aClassID ); + m_pOleComponent->RunObject(); + m_nObjectState = embed::EmbedStates::RUNNING; + } + } + else + { + if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE ) + throw io::IOException(); + + if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) + { + // the document just already changed its stream to store to; + // the links to OLE documents switch their persistence in the same way + // as normal embedded objects + } + else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT ) + { + // create a new object, that will be stored in specified stream + CreateOleComponent_Impl(); + + m_pOleComponent->CreateNewEmbeddedObject( m_aClassID ); + m_pOleComponent->RunObject(); + m_nObjectState = embed::EmbedStates::RUNNING; + } + else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT ) + { + // use URL ( may be content or stream later ) from MediaDescriptor to initialize object + ::rtl::OUString aURL; + for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ ) + if ( lArguments[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "URL" ) ) ) + lArguments[nInd].Value >>= aURL; + + if ( !aURL.getLength() ) + throw lang::IllegalArgumentException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Empty URL is provided in the media descriptor!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 4 ); + + CreateOleComponent_Impl(); + + // TODO: the m_bIsLink value must be set already + if ( !m_bIsLink ) + m_pOleComponent->CreateObjectFromFile( aURL ); + else + m_pOleComponent->CreateLinkFromFile( aURL ); + + m_pOleComponent->RunObject(); + m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction + + m_nObjectState = embed::EmbedStates::RUNNING; + } + //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT ) + //{ + //TODO: + //} + else + throw lang::IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Wrong connection mode is provided!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 3 ); + } +#else + // On unix the ole object can not do anything except storing itself somewere + if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT && bElExists ) + { + // TODO/LATER: detect classID of the object + // can be a real problem for the links + + m_nObjectState = embed::EmbedStates::LOADED; + } + else if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) + { + // do nothing, the object has already switched it's persistence + } + else + throw lang::IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Wrong connection mode is provided!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 3 ); + +#endif +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& lArguments, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeToEntry" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->storeToEntry( xStorage, sEntName, lArguments, lObjArgs ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); + + StoreToLocation_Impl( xStorage, sEntName, lArguments, lObjArgs, sal_False ); + + // TODO: should the listener notification be done? +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& lArguments, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeAsEntry" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->storeAsEntry( xStorage, sEntName, lArguments, lObjArgs ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); + + StoreToLocation_Impl( xStorage, sEntName, lArguments, lObjArgs, sal_True ); + + // TODO: should the listener notification be done here or in saveCompleted? +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::saveCompleted( sal_Bool bUseNew ) + throw ( embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::saveCompleted" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->saveCompleted( bUseNew ); + return; + } + // end wrapping related part ==================== + + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Can't store object without persistence!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + // it is allowed to call saveCompleted( false ) for nonstored objects + if ( !m_bWaitSaveCompleted && !bUseNew ) + return; + + OSL_ENSURE( m_bWaitSaveCompleted, "Unexpected saveCompleted() call!\n" ); + if ( !m_bWaitSaveCompleted ) + throw io::IOException(); // TODO: illegal call + + OSL_ENSURE( m_xNewObjectStream.is() && m_xNewParentStorage.is() , "Internal object information is broken!\n" ); + if ( !m_xNewObjectStream.is() || !m_xNewParentStorage.is() ) + throw uno::RuntimeException(); // TODO: broken internal information + + if ( bUseNew ) + { + SwitchOwnPersistence( m_xNewParentStorage, m_xNewObjectStream, m_aNewEntryName ); + m_bStoreVisRepl = m_bNewVisReplInStream; + SetVisReplInStream( m_bNewVisReplInStream ); + m_xCachedVisualRepresentation = m_xNewCachedVisRepl; + } + else + { + // close remembered stream + try { + uno::Reference< lang::XComponent > xComponent( m_xNewObjectStream, uno::UNO_QUERY ); + OSL_ENSURE( xComponent.is(), "Wrong storage implementation!" ); + if ( xComponent.is() ) + xComponent->dispose(); + } + catch ( uno::Exception& ) + { + } + } + + sal_Bool bStoreLoaded = m_bStoreLoaded; + + m_xNewObjectStream = uno::Reference< io::XStream >(); + m_xNewParentStorage = uno::Reference< embed::XStorage >(); + m_aNewEntryName = ::rtl::OUString(); + m_bWaitSaveCompleted = sal_False; + m_bNewVisReplInStream = sal_False; + m_xNewCachedVisRepl = uno::Reference< io::XStream >(); + m_bStoreLoaded = sal_False; + + if ( bUseNew && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded + && m_nObjectState != embed::EmbedStates::LOADED ) + { + // the object replacement image should be updated, so the cached size as well + m_bHasCachedSize = sal_False; + try + { + // the call will cache the size in case of success + // probably it might need to be done earlier, while the object is in active state + getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); + } + catch( uno::Exception& ) + {} + } + + aGuard.clear(); + if ( bUseNew ) + { + MakeEventListenerNotification_Impl( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "OnSaveAsDone" ) )); + + // the object can be changed only on windows + // the notification should be done only if the object is not in loaded state + if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded ) + { + MakeEventListenerNotification_Impl( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "OnVisAreaChanged" ) )); + } + } +} + +//------------------------------------------------------ +sal_Bool SAL_CALL OleEmbeddedObject::hasEntry() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->hasEntry(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object waits for saveCompleted() call!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( m_xObjectStream.is() ) + return sal_True; + + return sal_False; +} + +//------------------------------------------------------ +::rtl::OUString SAL_CALL OleEmbeddedObject::getEntryName() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getEntryName(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object persistence is not initialized!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object waits for saveCompleted() call!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + return m_aEntryName; +} + + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::storeOwn() + throw ( embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeOwn" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->storeOwn(); + return; + } + // end wrapping related part ==================== + + // during switching from Activated to Running and from Running to Loaded states the object will + // ask container to store the object, the container has to make decision + // to do so or not + + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Can't store object without persistence!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object waits for saveCompleted() call!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( m_bReadOnly ) + throw io::IOException(); // TODO: access denied + + LetCommonStoragePassBeUsed_Impl( m_xObjectStream ); + + sal_Bool bStoreLoaded = sal_True; + +#ifdef WNT + if ( m_nObjectState != embed::EmbedStates::LOADED && m_pOleComponent && m_pOleComponent->IsDirty() ) + { + bStoreLoaded = sal_False; + + OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" ); + + if ( !m_xObjectStream.is() ) + throw io::IOException(); //TODO: access denied + + SetStreamMediaType_Impl( m_xObjectStream, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) )); + uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream(); + if ( !xOutStream.is() ) + throw io::IOException(); //TODO: access denied + + if ( m_bIsLink ) + { + // just let the link store itself + // in case visual repersentation must be stored also + // the procedure should be the same as for embedded objects + + uno::Reference< io::XOutputStream > xOutStream = GetStreamForSaving(); + + // should the component detect that it is a link??? + StoreObjectToStream( xOutStream ); + } + else + { + uno::Reference< io::XOutputStream > xOutStream = GetStreamForSaving(); + StoreObjectToStream( xOutStream ); + } + + // the replacement is changed probably, and it must be in the object stream + if ( !m_pOleComponent->IsWorkaroundActive() ) + m_xCachedVisualRepresentation = uno::Reference< io::XStream >(); + SetVisReplInStream( sal_True ); + } +#endif + + if ( m_bStoreVisRepl != HasVisReplInStream() ) + { + if ( m_bStoreVisRepl ) + { + // the m_xCachedVisualRepresentation must be set or it should be already stored + if ( m_xCachedVisualRepresentation.is() ) + InsertVisualCache_Impl( m_xObjectStream, m_xCachedVisualRepresentation ); + else + { + m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream ); + OSL_ENSURE( m_xCachedVisualRepresentation.is(), "No representation is available!" ); + } + } + else + { + if ( !m_xCachedVisualRepresentation.is() ) + m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream ); + RemoveVisualCache_Impl( m_xObjectStream ); + } + + SetVisReplInStream( m_bStoreVisRepl ); + } + + if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded ) + { + // the object replacement image should be updated, so the cached size as well + m_bHasCachedSize = sal_False; + try + { + // the call will cache the size in case of success + // probably it might need to be done earlier, while the object is in active state + getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); + } + catch( uno::Exception& ) + {} + } + + aGuard.clear(); + + MakeEventListenerNotification_Impl( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "OnSaveDone" ) )); + + // the object can be changed only on Windows + // the notification should be done only if the object is not in loaded state + if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded ) + MakeEventListenerNotification_Impl( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "OnVisAreaChanged" ) )); +} + +//------------------------------------------------------ +sal_Bool SAL_CALL OleEmbeddedObject::isReadonly() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->isReadonly(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object persistence is not initialized!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object waits for saveCompleted() call!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + return m_bReadOnly; +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::reload( + const uno::Sequence< beans::PropertyValue >& lArguments, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->reload( lArguments, lObjArgs ); + return; + } + // end wrapping related part ==================== + + // TODO: use lObjArgs + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object persistence is not initialized!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object waits for saveCompleted() call!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + // TODO: + // throw away current document + // load new document from current storage + // use meaningfull part of lArguments +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->breakLink( xStorage, sEntName ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "No parent storage is provided!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + if ( !sEntName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Empty element name is provided!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 2 ); + + // TODO: The object must be at least in Running state; + if ( !m_bIsLink || m_nObjectState == -1 || !m_pOleComponent ) + { + // it must be a linked initialized object + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object is not a valid linked object!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bReadOnly ) + throw io::IOException(); // TODO: Access denied + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object waits for saveCompleted() call!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + +#ifdef WNT + if ( m_pOleComponent ) + { + // TODO: create an object based on the link + + // disconnect the old temporary URL + ::rtl::OUString aOldTempURL = m_aTempURL; + m_aTempURL = ::rtl::OUString(); + + OleComponent* pNewOleComponent = new OleComponent( m_xFactory, this ); + try { + pNewOleComponent->InitEmbeddedCopyOfLink( m_pOleComponent ); + } + catch ( uno::Exception& ) + { + delete pNewOleComponent; + if ( m_aTempURL ) + KillFile_Impl( m_aTempURL, m_xFactory ); + m_aTempURL = aOldTempURL; + throw; + } + + try { + GetRidOfComponent(); + } + catch( uno::Exception& ) + { + delete pNewOleComponent; + if ( m_aTempURL ) + KillFile_Impl( m_aTempURL, m_xFactory ); + m_aTempURL = aOldTempURL; + throw; + } + + KillFile_Impl( aOldTempURL, m_xFactory ); + + CreateOleComponent_Impl( pNewOleComponent ); + + if ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ) + SwitchOwnPersistence( xStorage, sEntName ); + + if ( m_nObjectState != embed::EmbedStates::LOADED ) + { + // TODO: should we activate the new object if the link was activated? + + sal_Int32 nTargetState = m_nObjectState; + m_nObjectState = embed::EmbedStates::LOADED; + + if ( m_nObjectState == embed::EmbedStates::RUNNING ) + m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed + else // m_nObjectState == embed::EmbedStates::ACTIVE + { + m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed + m_pOleComponent->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN ); + } + + m_nObjectState = nTargetState; + } + + m_bIsLink = sal_False; + m_aLinkURL = ::rtl::OUString(); + } + else +#endif + { + throw io::IOException(); //TODO: + } +} + +//------------------------------------------------------ +sal_Bool SAL_CALL OleEmbeddedObject::isLink() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->isLink(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + return m_bIsLink; +} + +//------------------------------------------------------ +::rtl::OUString SAL_CALL OleEmbeddedObject::getLinkURL() + throw ( embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getLinkURL(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object waits for saveCompleted() call!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( !m_bIsLink ) + throw embed::WrongStateException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "The object is not a link object!\n" )), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + // TODO: probably the link URL can be retrieved from OLE + + return m_aLinkURL; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |