Files
loongoffice/comphelper/source/container/embeddedobjectcontainer.cxx
Thomas Arnhold ba0a57702c remove OUString wrap for string literals
For some functions and all kinds of Exceptions.

CannotConvertException
CloseVetoException
DisposedException
EmptyUndoStackException
ErrorCodeIOException
Exception
GridInvalidDataException
GridInvalidModelException
IOException
IllegalAccessException
IllegalArgumentException
IllegalTypeException
IndexOutOfBoundsException
NoMasterException
NoSuchElementException
NoSupportException
PropertyVetoException
RuntimeException
SAXException
ScannerException
StorageWrappedTargetException
UnsupportedFlavorException
VetoException
WrappedTargetException
ZipIOException
throwGenericSQLException
throwIllegallArgumentException

createInstance
createInstanceWithContext
forName
getByName
getPackageManager
getPropertyValue
getUnpackedValueOrDefault
getValueByName
hasPropertyByName
openKey
setName
setPropertyValue
supportsService

bash command:

for i in `cat list`; do git grep "$i\s*(\s*OUString(\s*\"" -- '*.[hc]xx'
	| cut -d ':' -f1 | sort -u
	| xargs sed -i
		-e "s/\(\<$i\s*(\)\s*OUString(\s*\(\"[^\")\\]*\"\)\s*)\s*/\1\2/g"
		-e "s/\($i.*\)\"+ /\1\" + /g";
done

Change-Id: Iaf8e641b0abf28c082906014f87a183517630535
Reviewed-on: https://gerrit.libreoffice.org/4624
Tested-by: LibreOffice gerrit bot <gerrit@libreoffice.org>
Reviewed-by: Thomas Arnhold <thomas@arnhold.org>
Tested-by: Thomas Arnhold <thomas@arnhold.org>
2013-06-29 21:52:54 +00:00

1662 lines
65 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/embed/EmbeddedObjectCreator.hpp>
#include <com/sun/star/embed/XLinkCreator.hpp>
#include <com/sun/star/embed/XEmbedPersist.hpp>
#include <com/sun/star/embed/XLinkageSupport.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/embed/XOptimizedStorage.hpp>
#include <com/sun/star/embed/EntryInitModes.hpp>
#include <com/sun/star/util/XCloseable.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <com/sun/star/embed/EmbedStates.hpp>
#include <com/sun/star/datatransfer/XTransferable.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/embed/Aspects.hpp>
#include <com/sun/star/embed/EmbedMisc.hpp>
#include <comphelper/seqstream.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/storagehelper.hxx>
#include <comphelper/embeddedobjectcontainer.hxx>
#include <comphelper/sequence.hxx>
#include <cppuhelper/weakref.hxx>
#include <boost/unordered_map.hpp>
#include <algorithm>
using namespace ::com::sun::star;
namespace comphelper
{
struct hashObjectName_Impl
{
size_t operator()(const OUString Str) const
{
return (size_t)Str.hashCode();
}
};
struct eqObjectName_Impl
{
sal_Bool operator()(const OUString Str1, const OUString Str2) const
{
return ( Str1 == Str2 );
}
};
typedef boost::unordered_map
<
OUString,
::com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >,
hashObjectName_Impl,
eqObjectName_Impl
>
EmbeddedObjectContainerNameMap;
struct EmbedImpl
{
// TODO/LATER: remove objects from temp. Container storage when object is disposed
EmbeddedObjectContainerNameMap maObjectContainer;
uno::Reference < embed::XStorage > mxStorage;
EmbeddedObjectContainer* mpTempObjectContainer;
uno::Reference < embed::XStorage > mxImageStorage;
uno::WeakReference < uno::XInterface > m_xModel;
//EmbeddedObjectContainerNameMap maTempObjectContainer;
//uno::Reference < embed::XStorage > mxTempStorage;
bool bOwnsStorage;
const uno::Reference < embed::XStorage >& GetReplacements();
};
const uno::Reference < embed::XStorage >& EmbedImpl::GetReplacements()
{
if ( !mxImageStorage.is() )
{
try
{
mxImageStorage = mxStorage->openStorageElement(
OUString("ObjectReplacements"), embed::ElementModes::READWRITE );
}
catch (const uno::Exception&)
{
mxImageStorage = mxStorage->openStorageElement(
OUString("ObjectReplacements"), embed::ElementModes::READ );
}
}
if ( !mxImageStorage.is() )
throw io::IOException();
return mxImageStorage;
}
EmbeddedObjectContainer::EmbeddedObjectContainer()
{
pImpl = new EmbedImpl;
pImpl->mxStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
pImpl->bOwnsStorage = true;
pImpl->mpTempObjectContainer = 0;
}
EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor )
{
pImpl = new EmbedImpl;
pImpl->mxStorage = rStor;
pImpl->bOwnsStorage = false;
pImpl->mpTempObjectContainer = 0;
}
EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor, const uno::Reference < uno::XInterface >& xModel )
{
pImpl = new EmbedImpl;
pImpl->mxStorage = rStor;
pImpl->bOwnsStorage = false;
pImpl->mpTempObjectContainer = 0;
pImpl->m_xModel = xModel;
}
void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference < embed::XStorage >& rStor )
{
ReleaseImageSubStorage();
if ( pImpl->bOwnsStorage )
pImpl->mxStorage->dispose();
pImpl->mxStorage = rStor;
pImpl->bOwnsStorage = false;
}
sal_Bool EmbeddedObjectContainer::CommitImageSubStorage()
{
if ( pImpl->mxImageStorage.is() )
{
try
{
sal_Bool bReadOnlyMode = sal_True;
uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY);
if ( xSet.is() )
{
// get the open mode from the parent storage
sal_Int32 nMode = 0;
uno::Any aAny = xSet->getPropertyValue("OpenMode");
if ( aAny >>= nMode )
bReadOnlyMode = !(nMode & embed::ElementModes::WRITE );
} // if ( xSet.is() )
if ( !bReadOnlyMode )
{
uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW );
xTransact->commit();
}
}
catch (const uno::Exception&)
{
return sal_False;
}
}
return sal_True;
}
void EmbeddedObjectContainer::ReleaseImageSubStorage()
{
CommitImageSubStorage();
if ( pImpl->mxImageStorage.is() )
{
try
{
pImpl->mxImageStorage->dispose();
pImpl->mxImageStorage = uno::Reference< embed::XStorage >();
}
catch (const uno::Exception&)
{
SAL_WARN( "comphelper.container", "Problems releasing image substorage!\n" );
}
}
}
EmbeddedObjectContainer::~EmbeddedObjectContainer()
{
ReleaseImageSubStorage();
if ( pImpl->bOwnsStorage )
pImpl->mxStorage->dispose();
delete pImpl->mpTempObjectContainer;
delete pImpl;
}
void EmbeddedObjectContainer::CloseEmbeddedObjects()
{
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
while ( aIt != pImpl->maObjectContainer.end() )
{
uno::Reference < util::XCloseable > xClose( (*aIt).second, uno::UNO_QUERY );
if ( xClose.is() )
{
try
{
xClose->close( sal_True );
}
catch (const uno::Exception&)
{
}
}
++aIt;
}
}
OUString EmbeddedObjectContainer::CreateUniqueObjectName()
{
OUString aPersistName("Object ");
OUString aStr;
sal_Int32 i=1;
do
{
aStr = aPersistName;
aStr += OUString::valueOf( i++ );
}
while( HasEmbeddedObject( aStr ) );
// TODO/LATER: should we consider deleted objects?
return aStr;
}
uno::Sequence < OUString > EmbeddedObjectContainer::GetObjectNames()
{
uno::Sequence < OUString > aSeq( pImpl->maObjectContainer.size() );
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
sal_Int32 nIdx=0;
while ( aIt != pImpl->maObjectContainer.end() )
aSeq[nIdx++] = (*aIt++).first;
return aSeq;
}
sal_Bool EmbeddedObjectContainer::HasEmbeddedObjects()
{
return pImpl->maObjectContainer.size() != 0;
}
sal_Bool EmbeddedObjectContainer::HasEmbeddedObject( const OUString& rName )
{
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
if ( aIt == pImpl->maObjectContainer.end() )
{
uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
return xAccess->hasByName(rName);
}
else
return sal_True;
}
sal_Bool EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj )
{
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
while ( aIt != pImpl->maObjectContainer.end() )
{
if ( (*aIt).second == xObj )
return sal_True;
else
++aIt;
}
return sal_False;
}
sal_Bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString& rName )
{
// allows to detect whether the object was already instantiated
// currently the filter instantiate it on loading, so this method allows
// to avoid objects pointing to the same persistence
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
return ( aIt != pImpl->maObjectContainer.end() );
}
OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj )
{
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
while ( aIt != pImpl->maObjectContainer.end() )
{
if ( (*aIt).second == xObj )
return (*aIt).first;
else
++aIt;
}
SAL_WARN( "comphelper.container", "Unknown object!" );
return OUString();
}
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::GetEmbeddedObject( const OUString& rName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetEmbeddedObject" );
SAL_WARN_IF( rName.isEmpty(), "comphelper.container", "Empty object name!");
uno::Reference < embed::XEmbeddedObject > xObj;
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
#if OSL_DEBUG_LEVEL > 1
uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
uno::Sequence< OUString> aSeq = xAccess->getElementNames();
const OUString* pIter = aSeq.getConstArray();
const OUString* pEnd = pIter + aSeq.getLength();
for(;pIter != pEnd;++pIter)
{
(void)*pIter;
}
OSL_ENSURE( aIt != pImpl->maObjectContainer.end() || xAccess->hasByName(rName), "Could not return object!" );
#endif
// check if object was already created
if ( aIt != pImpl->maObjectContainer.end() )
xObj = (*aIt).second;
else
xObj = Get_Impl( rName, uno::Reference < embed::XEmbeddedObject >() );
return xObj;
}
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::Get_Impl( const OUString& rName, const uno::Reference < embed::XEmbeddedObject >& xCopy )
{
uno::Reference < embed::XEmbeddedObject > xObj;
try
{
// create the object from the storage
uno::Reference < beans::XPropertySet > xSet( pImpl->mxStorage, uno::UNO_QUERY );
sal_Bool bReadOnlyMode = sal_True;
if ( xSet.is() )
{
// get the open mode from the parent storage
sal_Int32 nMode = 0;
uno::Any aAny = xSet->getPropertyValue("OpenMode");
if ( aAny >>= nMode )
bReadOnlyMode = !(nMode & embed::ElementModes::WRITE );
}
// object was not added until now - should happen only by calling this method from "inside"
//TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call)
uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
uno::Sequence< beans::PropertyValue > aObjDescr( xCopy.is() ? 2 : 1 );
aObjDescr[0].Name = "Parent";
aObjDescr[0].Value <<= pImpl->m_xModel.get();
if ( xCopy.is() )
{
aObjDescr[1].Name = "CloneFrom";
aObjDescr[1].Value <<= xCopy;
}
uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
aMediaDescr[0].Name = "ReadOnly";
aMediaDescr[0].Value <<= bReadOnlyMode;
xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromEntry(
pImpl->mxStorage, rName,
aMediaDescr, aObjDescr ), uno::UNO_QUERY );
// insert object into my list
AddEmbeddedObject( xObj, rName );
}
catch (uno::Exception const& e)
{
SAL_WARN("comphelper.container", "EmbeddedObjectContainer::Get_Impl: exception caught: " << e.Message);
}
return xObj;
}
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId,
const uno::Sequence < beans::PropertyValue >& rArgs, OUString& rNewName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CreateEmbeddedObject" );
if ( rNewName.isEmpty() )
rNewName = CreateUniqueObjectName();
SAL_WARN_IF( HasEmbeddedObject(rNewName), "comphelper.container", "Object to create already exists!");
// create object from classid by inserting it into storage
uno::Reference < embed::XEmbeddedObject > xObj;
try
{
uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
uno::Sequence< beans::PropertyValue > aObjDescr( rArgs.getLength() + 1 );
aObjDescr[0].Name = "Parent";
aObjDescr[0].Value <<= pImpl->m_xModel.get();
::std::copy( rArgs.getConstArray(), rArgs.getConstArray() + rArgs.getLength(), aObjDescr.getArray() + 1 );
xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitNew(
rClassId, OUString(), pImpl->mxStorage, rNewName,
aObjDescr ), uno::UNO_QUERY );
AddEmbeddedObject( xObj, rNewName );
OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
"A freshly create object should be running always!\n" );
}
catch (uno::Exception const& e)
{
SAL_WARN("comphelper.container", "EmbeddedObjectContainer::CreateEmbeddedObject: exception caught: " << e.Message);
}
return xObj;
}
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId, OUString& rNewName )
{
return CreateEmbeddedObject( rClassId, uno::Sequence < beans::PropertyValue >(), rNewName );
}
void EmbeddedObjectContainer::AddEmbeddedObject( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, const OUString& rName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::AddEmbeddedObject" );
#if OSL_DEBUG_LEVEL > 1
SAL_WARN_IF( rName.isEmpty(), "comphelper.container", "Added object doesn't have a name!");
uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
uno::Reference < embed::XEmbedPersist > xEmb( xObj, uno::UNO_QUERY );
uno::Reference < embed::XLinkageSupport > xLink( xEmb, uno::UNO_QUERY );
// if the object has a persistance and the object is not a link than it must have persistence entry in the storage
OSL_ENSURE( !( xEmb.is() && ( !xLink.is() || !xLink->isLink() ) ) || xAccess->hasByName(rName),
"Added element not in storage!" );
#endif
// remember object - it needs to be in storage already
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
OSL_ENSURE( aIt == pImpl->maObjectContainer.end(), "Element already inserted!" );
pImpl->maObjectContainer[ rName ] = xObj;
uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
if ( xChild.is() && xChild->getParent() != pImpl->m_xModel.get() )
xChild->setParent( pImpl->m_xModel.get() );
// look for object in temorary container
if ( pImpl->mpTempObjectContainer )
{
aIt = pImpl->mpTempObjectContainer->pImpl->maObjectContainer.begin();
while ( aIt != pImpl->mpTempObjectContainer->pImpl->maObjectContainer.end() )
{
if ( (*aIt).second == xObj )
{
// copy replacement image from temporary container (if there is any)
OUString aTempName = (*aIt).first;
OUString aMediaType;
uno::Reference < io::XInputStream > xStream = pImpl->mpTempObjectContainer->GetGraphicStream( xObj, &aMediaType );
if ( xStream.is() )
{
InsertGraphicStream( xStream, rName, aMediaType );
xStream = 0;
pImpl->mpTempObjectContainer->RemoveGraphicStream( aTempName );
}
// remove object from storage of temporary container
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
if ( xPersist.is() )
{
try
{
pImpl->mpTempObjectContainer->pImpl->mxStorage->removeElement( aTempName );
}
catch (const uno::Exception&)
{
}
}
// temp. container needs to forget the object
pImpl->mpTempObjectContainer->pImpl->maObjectContainer.erase( aIt );
break;
}
else
++aIt;
}
}
}
sal_Bool EmbeddedObjectContainer::StoreEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, OUString& rName, sal_Bool bCopy )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::StoreEmbeddedObject" );
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
if ( rName.isEmpty() )
rName = CreateUniqueObjectName();
#if OSL_DEBUG_LEVEL > 1
uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
OSL_ENSURE( !xPersist.is() || !xAccess->hasByName(rName), "Inserting element already present in storage!" );
OSL_ENSURE( xPersist.is() || xObj->getCurrentState() == embed::EmbedStates::RUNNING, "Non persistent object inserted!");
#endif
// insert objects' storage into the container storage (if object has one)
try
{
if ( xPersist.is() )
{
uno::Sequence < beans::PropertyValue > aSeq;
if ( bCopy )
xPersist->storeToEntry( pImpl->mxStorage, rName, aSeq, aSeq );
else
{
//TODO/LATER: possible optimisation, don't store immediately
//xPersist->setPersistentEntry( pImpl->mxStorage, rName, embed::EntryInitModes::ENTRY_NO_INIT, aSeq, aSeq );
xPersist->storeAsEntry( pImpl->mxStorage, rName, aSeq, aSeq );
xPersist->saveCompleted( sal_True );
}
}
}
catch (uno::Exception const& e)
{
SAL_WARN("comphelper.container", "EmbeddedObjectContainer::StoreEmbeddedObject: exception caught: " << e.Message);
// TODO/LATER: better error recovery should keep storage intact
return sal_False;
}
return sal_True;
}
sal_Bool EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, OUString& rName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( Object )" );
// store it into the container storage
if ( StoreEmbeddedObject( xObj, rName, sal_False ) )
{
// remember object
AddEmbeddedObject( xObj, rName );
return sal_True;
}
else
return sal_False;
}
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference < io::XInputStream >& xStm, OUString& rNewName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( InputStream )" );
if ( rNewName.isEmpty() )
rNewName = CreateUniqueObjectName();
// store it into the container storage
sal_Bool bIsStorage = sal_False;
try
{
// first try storage persistence
uno::Reference < embed::XStorage > xStore = ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm );
// storage was created from stream successfully
bIsStorage = sal_True;
uno::Reference < embed::XStorage > xNewStore = pImpl->mxStorage->openStorageElement( rNewName, embed::ElementModes::READWRITE );
xStore->copyToStorage( xNewStore );
}
catch (const uno::Exception&)
{
if ( bIsStorage )
// it is storage persistence, but opening of new substorage or copying to it failed
return uno::Reference < embed::XEmbeddedObject >();
// stream didn't contain a storage, now try stream persistence
try
{
uno::Reference < io::XStream > xNewStream = pImpl->mxStorage->openStreamElement( rNewName, embed::ElementModes::READWRITE );
::comphelper::OStorageHelper::CopyInputToOutput( xStm, xNewStream->getOutputStream() );
// No mediatype is provided so the default for OLE objects value is used
// it is correct so for now, but what if somebody introduces a new stream based embedded object?
// Probably introducing of such an object must be restricted ( a storage must be used! ).
uno::Reference< beans::XPropertySet > xProps( xNewStream, uno::UNO_QUERY_THROW );
xProps->setPropertyValue("MediaType",
uno::makeAny( OUString( "application/vnd.sun.star.oleobject" ) ) );
}
catch (uno::Exception const& e)
{
// complete disaster!
SAL_WARN("comphelper.container", "EmbeddedObjectContainer::InsertEmbeddedObject: exception caught: " << e.Message);
return uno::Reference < embed::XEmbeddedObject >();
}
}
// stream was copied into the container storage in either way, now try to open something form it
uno::Reference < embed::XEmbeddedObject > xRet = GetEmbeddedObject( rNewName );
try
{
if ( !xRet.is() )
// no object could be created, so withdraw insertion
pImpl->mxStorage->removeElement( rNewName );
}
catch (const uno::Exception&)
{
}
return xRet;
}
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, OUString& rNewName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( MediaDescriptor )" );
if ( rNewName.isEmpty() )
rNewName = CreateUniqueObjectName();
uno::Reference < embed::XEmbeddedObject > xObj;
try
{
uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
aObjDescr[0].Name = "Parent";
aObjDescr[0].Value <<= pImpl->m_xModel.get();
xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromMediaDescriptor(
pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY );
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
"A freshly create object should be running always!\n" );
// possible optimization: store later!
if ( xPersist.is())
xPersist->storeOwn();
AddEmbeddedObject( xObj, rNewName );
}
catch (const uno::Exception&)
{
}
return xObj;
}
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedLink( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, OUString& rNewName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedLink" );
if ( rNewName.isEmpty() )
rNewName = CreateUniqueObjectName();
uno::Reference < embed::XEmbeddedObject > xObj;
try
{
uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create(::comphelper::getProcessComponentContext());
uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
aObjDescr[0].Name = "Parent";
aObjDescr[0].Value <<= pImpl->m_xModel.get();
xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceLink(
pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY );
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
"A freshly create object should be running always!\n" );
// possible optimization: store later!
if ( xPersist.is())
xPersist->storeOwn();
AddEmbeddedObject( xObj, rNewName );
}
catch (uno::Exception const& e)
{
SAL_WARN("comphelper", "EmbeddedObjectContainer::InsertEmbeddedLink: "
"exception caught: " << e.Message);
}
return xObj;
}
sal_Bool EmbeddedObjectContainer::TryToCopyGraphReplacement( EmbeddedObjectContainer& rSrc,
const OUString& aOrigName,
const OUString& aTargetName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::TryToCopyGraphReplacement" );
sal_Bool bResult = sal_False;
if ( ( &rSrc != this || !aOrigName.equals( aTargetName ) ) && !aOrigName.isEmpty() && !aTargetName.isEmpty() )
{
OUString aMediaType;
uno::Reference < io::XInputStream > xGrStream = rSrc.GetGraphicStream( aOrigName, &aMediaType );
if ( xGrStream.is() )
bResult = InsertGraphicStream( xGrStream, aTargetName, aMediaType );
}
return bResult;
}
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CopyAndGetEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, OUString& rName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyAndGetEmbeddedObject" );
uno::Reference< embed::XEmbeddedObject > xResult;
// TODO/LATER: For now only objects that implement XEmbedPersist have a replacement image, it might change in future
// do an incompatible change so that object name is provided in all the move and copy methods
OUString aOrigName;
try
{
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY_THROW );
aOrigName = xPersist->getEntryName();
}
catch (const uno::Exception&)
{
}
if ( rName.isEmpty() )
rName = CreateUniqueObjectName();
// objects without persistance are not really stored by the method
if ( xObj.is() && StoreEmbeddedObject( xObj, rName, sal_True ) )
{
xResult = Get_Impl( rName, xObj);
if ( !xResult.is() )
{
// this is a case when object has no real persistence
// in such cases a new object should be explicitly created and initialized with the data of the old one
try
{
uno::Reference< embed::XLinkageSupport > xOrigLinkage( xObj, uno::UNO_QUERY );
if ( xOrigLinkage.is() && xOrigLinkage->isLink() )
{
// this is a OOo link, it has no persistence
OUString aURL = xOrigLinkage->getLinkURL();
if ( aURL.isEmpty() )
throw uno::RuntimeException();
// create new linked object from the URL the link is based on
uno::Reference < embed::XEmbeddedObjectCreator > xCreator =
embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
aMediaDescr[0].Name = "URL";
aMediaDescr[0].Value <<= aURL;
uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
aObjDescr[0].Name = "Parent";
aObjDescr[0].Value <<= pImpl->m_xModel.get();
xResult = uno::Reference < embed::XEmbeddedObject >(
xCreator->createInstanceLink(
pImpl->mxStorage,
rName,
aMediaDescr,
aObjDescr ),
uno::UNO_QUERY_THROW );
}
else
{
// the component is required for copying of this object
if ( xObj->getCurrentState() == embed::EmbedStates::LOADED )
xObj->changeState( embed::EmbedStates::RUNNING );
// this must be an object based on properties, otherwise we can not copy it currently
uno::Reference< beans::XPropertySet > xOrigProps( xObj->getComponent(), uno::UNO_QUERY_THROW );
// use object class ID to create a new one and tranfer all the properties
uno::Reference < embed::XEmbeddedObjectCreator > xCreator =
embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
aObjDescr[0].Name = "Parent";
aObjDescr[0].Value <<= pImpl->m_xModel.get();
xResult = uno::Reference < embed::XEmbeddedObject >(
xCreator->createInstanceInitNew(
xObj->getClassID(),
xObj->getClassName(),
pImpl->mxStorage,
rName,
aObjDescr ),
uno::UNO_QUERY_THROW );
if ( xResult->getCurrentState() == embed::EmbedStates::LOADED )
xResult->changeState( embed::EmbedStates::RUNNING );
uno::Reference< beans::XPropertySet > xTargetProps( xResult->getComponent(), uno::UNO_QUERY_THROW );
// copy all the properties from xOrigProps to xTargetProps
uno::Reference< beans::XPropertySetInfo > xOrigInfo = xOrigProps->getPropertySetInfo();
if ( !xOrigInfo.is() )
throw uno::RuntimeException();
uno::Sequence< beans::Property > aPropertiesList = xOrigInfo->getProperties();
for ( sal_Int32 nInd = 0; nInd < aPropertiesList.getLength(); nInd++ )
{
try
{
xTargetProps->setPropertyValue(
aPropertiesList[nInd].Name,
xOrigProps->getPropertyValue( aPropertiesList[nInd].Name ) );
}
catch (const beans::PropertyVetoException&)
{
// impossibility to copy readonly property is not treated as an error for now
// but the assertion is helpful to detect such scenarios and review them
SAL_WARN( "comphelper.container", "Could not copy readonly property!\n" );
}
}
}
if ( xResult.is() )
AddEmbeddedObject( xResult, rName );
}
catch (const uno::Exception&)
{
if ( xResult.is() )
{
try
{
xResult->close( sal_True );
}
catch (const uno::Exception&)
{
}
xResult = uno::Reference< embed::XEmbeddedObject >();
}
}
}
}
SAL_WARN_IF( !xResult.is(), "comphelper.container", "Can not copy embedded object that has no persistance!\n" );
if ( xResult.is() )
{
// the object is successfully copied, try to copy graphical replacement
if ( !aOrigName.isEmpty() )
TryToCopyGraphReplacement( rSrc, aOrigName, rName );
// the object might need the size to be set
try
{
if ( xResult->getStatus( embed::Aspects::MSOLE_CONTENT ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD )
xResult->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT,
xObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ) );
}
catch (const uno::Exception&)
{
}
}
return xResult;
}
sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, OUString& rName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Object )" );
// get the object name before(!) it is assigned to a new storage
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
OUString aName;
if ( xPersist.is() )
aName = xPersist->getEntryName();
// now move the object to the new container; the returned name is the new persist name in this container
sal_Bool bRet;
try
{
bRet = InsertEmbeddedObject( xObj, rName );
if ( bRet )
TryToCopyGraphReplacement( rSrc, aName, rName );
}
catch (const uno::Exception&)
{
SAL_WARN( "comphelper.container", "Failed to insert embedded object into storage!" );
bRet = sal_False;
}
if ( bRet )
{
// now remove the object from the former container
bRet = sal_False;
EmbeddedObjectContainerNameMap::iterator aIt = rSrc.pImpl->maObjectContainer.begin();
while ( aIt != rSrc.pImpl->maObjectContainer.end() )
{
if ( (*aIt).second == xObj )
{
rSrc.pImpl->maObjectContainer.erase( aIt );
bRet = sal_True;
break;
}
++aIt;
}
SAL_WARN_IF( !bRet, "comphelper.container", "Object not found for removal!" );
if ( xPersist.is() )
{
// now it's time to remove the storage from the container storage
try
{
if ( xPersist.is() )
rSrc.pImpl->mxStorage->removeElement( aName );
}
catch (const uno::Exception&)
{
SAL_WARN( "comphelper.container", "Failed to remove object from storage!" );
bRet = sal_False;
}
}
// rSrc.RemoveGraphicStream( aName );
}
return bRet;
}
// #i119941, bKeepToTempStorage: use to specify whether store the removed object to temporary storage+
sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const OUString& rName, sal_Bool bClose, sal_Bool bKeepToTempStorage )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Name )" );
uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( rName );
if ( xObj.is() )
//return RemoveEmbeddedObject( xObj, bClose );
return RemoveEmbeddedObject( xObj, bClose, bKeepToTempStorage );
else
return sal_False;
}
sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( const OUString& rName, EmbeddedObjectContainer& rCnt )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Name )" );
// find object entry
EmbeddedObjectContainerNameMap::iterator aIt2 = rCnt.pImpl->maObjectContainer.find( rName );
OSL_ENSURE( aIt2 == rCnt.pImpl->maObjectContainer.end(), "Object does already exist in target container!" );
if ( aIt2 != rCnt.pImpl->maObjectContainer.end() )
return sal_False;
uno::Reference < embed::XEmbeddedObject > xObj;
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
if ( aIt != pImpl->maObjectContainer.end() )
{
xObj = (*aIt).second;
try
{
if ( xObj.is() )
{
// move object
OUString aName( rName );
rCnt.InsertEmbeddedObject( xObj, aName );
pImpl->maObjectContainer.erase( aIt );
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
if ( xPersist.is() )
pImpl->mxStorage->removeElement( rName );
}
else
{
// copy storages; object *must* have persistence!
uno::Reference < embed::XStorage > xOld = pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READ );
uno::Reference < embed::XStorage > xNew = rCnt.pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READWRITE );
xOld->copyToStorage( xNew );
}
rCnt.TryToCopyGraphReplacement( *this, rName, rName );
// RemoveGraphicStream( rName );
return sal_True;
}
catch (const uno::Exception&)
{
SAL_WARN( "comphelper.container", "Could not move object!");
return sal_False;
}
}
else
SAL_WARN( "comphelper.container", "Unknown object!");
return sal_False;
}
//sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Bool bClose )
// #i119941, bKeepToTempStorage: use to specify whether store the removed object to temporary storage+
sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Bool bClose, sal_Bool bKeepToTempStorage )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Object )" );
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
OUString aName;
if ( xPersist.is() )
aName = xPersist->getEntryName();
#if OSL_DEBUG_LEVEL > 1
uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
uno::Reference < embed::XLinkageSupport > xLink( xPersist, uno::UNO_QUERY );
sal_Bool bIsNotEmbedded = !xPersist.is() || ( xLink.is() && xLink->isLink() );
// if the object has a persistance and the object is not a link than it must have persistence entry in the storage
OSL_ENSURE( bIsNotEmbedded || xAccess->hasByName(aName), "Removing element not present in storage!" );
#endif
// try to close it if permitted
if ( bClose )
{
uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
try
{
xClose->close( sal_True );
}
catch (const util::CloseVetoException&)
{
bClose = sal_False;
}
}
if ( !bClose )
{
// somebody still needs the object, so we must assign a temporary persistence
try
{
// if ( xPersist.is() )
if ( xPersist.is() && bKeepToTempStorage ) // #i119941
{
/*
//TODO/LATER: needs storage handling! Why not letting the object do it?!
if ( !pImpl->mxTempStorage.is() )
pImpl->mxTempStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
uno::Sequence < beans::PropertyValue > aSeq;
OUString aTmpPersistName = "Object ";
aTmpPersistName += OUString::valueOf( (sal_Int32) pImpl->maTempObjectContainer.size() );
xPersist->storeAsEntry( pImpl->mxTempStorage, aTmpPersistName, aSeq, aSeq );
xPersist->saveCompleted( sal_True );
pImpl->maTempObjectContainer[ aTmpPersistName ] = uno::Reference < embed::XEmbeddedObject >();
*/
if ( !pImpl->mpTempObjectContainer )
{
pImpl->mpTempObjectContainer = new EmbeddedObjectContainer();
try
{
// TODO/LATER: in future probably the temporary container will have two storages ( of two formats )
// the media type will be provided with object insertion
OUString aOrigStorMediaType;
uno::Reference< beans::XPropertySet > xStorProps( pImpl->mxStorage, uno::UNO_QUERY_THROW );
static const OUString s_sMediaType("MediaType");
xStorProps->getPropertyValue( s_sMediaType ) >>= aOrigStorMediaType;
SAL_WARN_IF( aOrigStorMediaType.isEmpty(), "comphelper.container", "No valuable media type in the storage!\n" );
uno::Reference< beans::XPropertySet > xTargetStorProps(
pImpl->mpTempObjectContainer->pImpl->mxStorage,
uno::UNO_QUERY_THROW );
xTargetStorProps->setPropertyValue( s_sMediaType,uno::makeAny( aOrigStorMediaType ) );
}
catch (const uno::Exception&)
{
SAL_WARN( "comphelper.container", "Can not set the new media type to a storage!\n" );
}
}
OUString aTempName, aMediaType;
pImpl->mpTempObjectContainer->InsertEmbeddedObject( xObj, aTempName );
uno::Reference < io::XInputStream > xStream = GetGraphicStream( xObj, &aMediaType );
if ( xStream.is() )
pImpl->mpTempObjectContainer->InsertGraphicStream( xStream, aTempName, aMediaType );
// object is stored, so at least it can be set to loaded state
xObj->changeState( embed::EmbedStates::LOADED );
}
else
// objects without persistence need to stay in running state if they shall not be closed
xObj->changeState( embed::EmbedStates::RUNNING );
}
catch (const uno::Exception&)
{
return sal_False;
}
}
sal_Bool bFound = sal_False;
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
while ( aIt != pImpl->maObjectContainer.end() )
{
if ( (*aIt).second == xObj )
{
pImpl->maObjectContainer.erase( aIt );
bFound = sal_True;
uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
if ( xChild.is() )
xChild->setParent( uno::Reference < uno::XInterface >() );
break;
}
++aIt;
}
SAL_WARN_IF( !bFound,"comphelper.container", "Object not found for removal!" );
(void)bFound;
if ( xPersist.is() && bKeepToTempStorage ) // #i119941#
{
// remove replacement image (if there is one)
RemoveGraphicStream( aName );
// now it's time to remove the storage from the container storage
try
{
#if OSL_DEBUG_LEVEL > 1
// if the object has a persistance and the object is not a link than it must have persistence entry in storage
OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" );
#endif
if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) )
pImpl->mxStorage->removeElement( aName );
}
catch (const uno::Exception&)
{
SAL_WARN( "comphelper.container", "Failed to remove object from storage!" );
return sal_False;
}
}
return sal_True;
}
sal_Bool EmbeddedObjectContainer::CloseEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CloseEmbeddedObject" );
// disconnect the object from the container and close it if possible
sal_Bool bFound = sal_False;
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
while ( aIt != pImpl->maObjectContainer.end() )
{
if ( (*aIt).second == xObj )
{
pImpl->maObjectContainer.erase( aIt );
bFound = sal_True;
break;
}
++aIt;
}
if ( bFound )
{
uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
try
{
xClose->close( sal_True );
}
catch (const uno::Exception&)
{
// it is no problem if the object is already closed
// TODO/LATER: what if the object can not be closed?
}
}
return bFound;
}
uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const OUString& aName, OUString* pMediaType )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Name )" );
uno::Reference < io::XInputStream > xStream;
SAL_WARN_IF( aName.isEmpty(), "comphelper.container", "Retrieving graphic for unknown object!" );
if ( !aName.isEmpty() )
{
try
{
uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( aName, embed::ElementModes::READ );
xStream = xGraphicStream->getInputStream();
if ( pMediaType )
{
uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
if ( xSet.is() )
{
uno::Any aAny = xSet->getPropertyValue("MediaType");
aAny >>= *pMediaType;
}
}
}
catch (const uno::Exception&)
{
}
}
return xStream;
}
uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, OUString* pMediaType )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Object )" );
// get the object name
OUString aName;
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
while ( aIt != pImpl->maObjectContainer.end() )
{
if ( (*aIt).second == xObj )
{
aName = (*aIt).first;
break;
}
++aIt;
}
// try to load it from the container storage
return GetGraphicStream( aName, pMediaType );
}
sal_Bool EmbeddedObjectContainer::InsertGraphicStream( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const OUString& rObjectName, const OUString& rMediaType )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStream" );
try
{
uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
// store it into the subfolder
uno::Reference < io::XOutputStream > xOutStream;
uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( rObjectName,
embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
xOutStream = xGraphicStream->getOutputStream();
::comphelper::OStorageHelper::CopyInputToOutput( rStream, xOutStream );
xOutStream->flush();
uno::Reference< beans::XPropertySet > xPropSet( xGraphicStream, uno::UNO_QUERY );
if ( !xPropSet.is() )
throw uno::RuntimeException();
xPropSet->setPropertyValue("UseCommonStoragePasswordEncryption",
uno::makeAny( (sal_Bool)sal_True ) );
uno::Any aAny;
aAny <<= rMediaType;
xPropSet->setPropertyValue("MediaType", aAny );
xPropSet->setPropertyValue("Compressed",
uno::makeAny( (sal_Bool)sal_True ) );
}
catch (const uno::Exception&)
{
return sal_False;
}
return sal_True;
}
sal_Bool EmbeddedObjectContainer::InsertGraphicStreamDirectly( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const OUString& rObjectName, const OUString& rMediaType )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStreamDirectly" );
try
{
uno::Reference < embed::XStorage > xReplacement = pImpl->GetReplacements();
uno::Reference < embed::XOptimizedStorage > xOptRepl( xReplacement, uno::UNO_QUERY_THROW );
// store it into the subfolder
uno::Sequence< beans::PropertyValue > aProps( 3 );
aProps[0].Name = "MediaType";
aProps[0].Value <<= rMediaType;
aProps[1].Name = "UseCommonStoragePasswordEncryption";
aProps[1].Value <<= (sal_Bool)sal_True;
aProps[2].Name = "Compressed";
aProps[2].Value <<= (sal_Bool)sal_True;
if ( xReplacement->hasByName( rObjectName ) )
xReplacement->removeElement( rObjectName );
xOptRepl->insertStreamElementDirect( rObjectName, rStream, aProps );
}
catch (const uno::Exception&)
{
return sal_False;
}
return sal_True;
}
sal_Bool EmbeddedObjectContainer::RemoveGraphicStream( const OUString& rObjectName )
{
SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveGraphicStream" );
try
{
uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
xReplacements->removeElement( rObjectName );
}
catch (const uno::Exception&)
{
return sal_False;
}
return sal_True;
}
namespace {
void InsertStreamIntoPicturesStorage_Impl( const uno::Reference< embed::XStorage >& xDocStor,
const uno::Reference< io::XInputStream >& xInStream,
const OUString& aStreamName )
{
OSL_ENSURE( !aStreamName.isEmpty() && xInStream.is() && xDocStor.is(), "Misuse of the method!\n" );
try
{
uno::Reference< embed::XStorage > xPictures = xDocStor->openStorageElement(
OUString( "Pictures" ),
embed::ElementModes::READWRITE );
uno::Reference< io::XStream > xObjReplStr = xPictures->openStreamElement(
aStreamName,
embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
uno::Reference< io::XOutputStream > xOutStream(
xObjReplStr->getInputStream(), uno::UNO_QUERY_THROW );
::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xOutStream );
xOutStream->closeOutput();
uno::Reference< embed::XTransactedObject > xTransact( xPictures, uno::UNO_QUERY );
if ( xTransact.is() )
xTransact->commit();
}
catch (const uno::Exception&)
{
SAL_WARN( "comphelper.container", "The pictures storage is not available!\n" );
}
}
}
// -----------------------------------------------------------------------------
sal_Bool EmbeddedObjectContainer::StoreAsChildren(sal_Bool _bOasisFormat,sal_Bool _bCreateEmbedded,const uno::Reference < embed::XStorage >& _xStorage)
{
sal_Bool bResult = sal_False;
try
{
comphelper::EmbeddedObjectContainer aCnt( _xStorage );
const uno::Sequence < OUString > aNames = GetObjectNames();
const OUString* pIter = aNames.getConstArray();
const OUString* pEnd = pIter + aNames.getLength();
for(;pIter != pEnd;++pIter)
{
uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
SAL_WARN_IF( !xObj.is(), "comphelper.container", "An empty entry in the embedded objects list!\n" );
if ( xObj.is() )
{
sal_Bool bSwitchBackToLoaded = sal_False;
uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY );
uno::Reference < io::XInputStream > xStream;
OUString aMediaType;
sal_Int32 nCurState = xObj->getCurrentState();
if ( nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING )
{
// means that the object is not active
// copy replacement image from old to new container
xStream = GetGraphicStream( xObj, &aMediaType );
}
if ( !xStream.is() )
{
// the image must be regenerated
// TODO/LATER: another aspect could be used
if ( xObj->getCurrentState() == embed::EmbedStates::LOADED )
bSwitchBackToLoaded = sal_True;
xStream = GetGraphicReplacementStream(
embed::Aspects::MSOLE_CONTENT,
xObj,
&aMediaType );
}
if ( _bOasisFormat || (xLink.is() && xLink->isLink()) )
{
if ( xStream.is() )
{
if ( _bOasisFormat )
{
// if it is an embedded object or the optimized inserting fails the normal inserting should be done
if ( _bCreateEmbedded
|| !aCnt.InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) )
aCnt.InsertGraphicStream( xStream, *pIter, aMediaType );
}
else
{
// it is a linked object exported into SO7 format
InsertStreamIntoPicturesStorage_Impl( _xStorage, xStream, *pIter );
}
}
}
uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
if ( xPersist.is() )
{
uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 );
aArgs[0].Name = "StoreVisualReplacement";
aArgs[0].Value <<= (sal_Bool)( !_bOasisFormat );
// if it is an embedded object or the optimized inserting fails the normal inserting should be done
aArgs[1].Name = "CanTryOptimization";
aArgs[1].Value <<= !_bCreateEmbedded;
if ( !_bOasisFormat )
{
// if object has no cached replacement it will use this one
aArgs[2].Name = "VisualReplacement";
aArgs[2].Value <<= xStream;
}
try
{
xPersist->storeAsEntry( _xStorage, xPersist->getEntryName(), uno::Sequence< beans::PropertyValue >(), aArgs );
}
catch (const embed::WrongStateException&)
{
SAL_WARN("comphelper.container", "failed to store '" << *pIter << "'");
}
}
if ( bSwitchBackToLoaded )
// switch back to loaded state; that way we have a minimum cache confusion
xObj->changeState( embed::EmbedStates::LOADED );
}
}
bResult = aCnt.CommitImageSubStorage();
}
catch (const uno::Exception& e)
{
// TODO/LATER: error handling
bResult = sal_False;
SAL_WARN("comphelper.container", "failed. Message: " << e.Message);
}
// the old SO6 format does not store graphical replacements
if ( !_bOasisFormat && bResult )
{
try
{
// the substorage still can not be locked by the embedded object conteiner
OUString aObjReplElement( "ObjectReplacements" );
if ( _xStorage->hasByName( aObjReplElement ) && _xStorage->isStorageElement( aObjReplElement ) )
_xStorage->removeElement( aObjReplElement );
}
catch (const uno::Exception&)
{
// TODO/LATER: error handling;
bResult = sal_False;
}
}
return bResult;
}
// -----------------------------------------------------------------------------
sal_Bool EmbeddedObjectContainer::StoreChildren(sal_Bool _bOasisFormat,sal_Bool _bObjectsOnly)
{
sal_Bool bResult = sal_True;
const uno::Sequence < OUString > aNames = GetObjectNames();
const OUString* pIter = aNames.getConstArray();
const OUString* pEnd = pIter + aNames.getLength();
for(;pIter != pEnd;++pIter)
{
uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
SAL_WARN_IF( !xObj.is(), "comphelper.container", "An empty entry in the embedded objects list!\n" );
if ( xObj.is() )
{
sal_Int32 nCurState = xObj->getCurrentState();
if ( _bOasisFormat && nCurState != embed::EmbedStates::LOADED && nCurState != embed::EmbedStates::RUNNING )
{
// means that the object is active
// the image must be regenerated
OUString aMediaType;
// TODO/LATER: another aspect could be used
uno::Reference < io::XInputStream > xStream =
GetGraphicReplacementStream(
embed::Aspects::MSOLE_CONTENT,
xObj,
&aMediaType );
if ( xStream.is() )
{
if ( !InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) )
InsertGraphicStream( xStream, *pIter, aMediaType );
}
}
// TODO/LATER: currently the object by default does not cache replacement image
// that means that if somebody loads SO7 document and store its objects using
// this method the images might be lost.
// Currently this method is only used on storing to alien formats, that means
// that SO7 documents storing does not use it, and all other filters are
// based on OASIS format. But if it changes the method must be fixed. The fix
// must be done only on demand since it can affect performance.
uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
if ( xPersist.is() )
{
try
{
//TODO/LATER: only storing if changed!
//xPersist->storeOwn(); //commented, i120168
// begin:all charts will be persited as xml format on disk when saving, which is time consuming.
// '_bObjectsOnly' mean we are storing to alien formats.
// 'isStorageElement' mean current object is NOT an MS OLE format. (may also include in future), i120168
if (_bObjectsOnly && (nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING)
&& (pImpl->mxStorage->isStorageElement( *pIter ) ))
{
uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
if ( xModifiable.is() && xModifiable->isModified())
{
xPersist->storeOwn();
}
else
{
//do nothing.embeded model is not modified, no need to persist.
}
}
else //the embeded object is in active status, always store back it.
{
xPersist->storeOwn();
}
//end i120168
}
catch (const uno::Exception&)
{
// TODO/LATER: error handling
bResult = sal_False;
break;
}
}
if ( !_bOasisFormat && !_bObjectsOnly )
{
// copy replacement images for linked objects
try
{
uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY );
if ( xLink.is() && xLink->isLink() )
{
OUString aMediaType;
uno::Reference < io::XInputStream > xInStream = GetGraphicStream( xObj, &aMediaType );
if ( xInStream.is() )
InsertStreamIntoPicturesStorage_Impl( pImpl->mxStorage, xInStream, *pIter );
}
}
catch (const uno::Exception&)
{
}
}
}
}
if ( bResult && _bOasisFormat )
bResult = CommitImageSubStorage();
if ( bResult && !_bObjectsOnly )
{
try
{
ReleaseImageSubStorage();
OUString aObjReplElement( "ObjectReplacements" );
if ( !_bOasisFormat && pImpl->mxStorage->hasByName( aObjReplElement ) && pImpl->mxStorage->isStorageElement( aObjReplElement ) )
pImpl->mxStorage->removeElement( aObjReplElement );
}
catch (const uno::Exception&)
{
// TODO/LATER: error handling
bResult = sal_False;
}
}
return bResult;
}
// -----------------------------------------------------------------------------
uno::Reference< io::XInputStream > EmbeddedObjectContainer::GetGraphicReplacementStream(
sal_Int64 nViewAspect,
const uno::Reference< embed::XEmbeddedObject >& xObj,
OUString* pMediaType )
{
uno::Reference< io::XInputStream > xInStream;
if ( xObj.is() )
{
try
{
// retrieving of the visual representation can switch object to running state
embed::VisualRepresentation aRep = xObj->getPreferredVisualRepresentation( nViewAspect );
if ( pMediaType )
*pMediaType = aRep.Flavor.MimeType;
uno::Sequence < sal_Int8 > aSeq;
aRep.Data >>= aSeq;
xInStream = new ::comphelper::SequenceInputStream( aSeq );
}
catch (const uno::Exception&)
{
}
}
return xInStream;
}
// -----------------------------------------------------------------------------
sal_Bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed::XStorage >& _xStorage,bool _bClearModifedFlag)
{
sal_Bool bError = sal_False;
const uno::Sequence < OUString > aNames = GetObjectNames();
const OUString* pIter = aNames.getConstArray();
const OUString* pEnd = pIter + aNames.getLength();
for(;pIter != pEnd;++pIter)
{
uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
SAL_WARN_IF( !xObj.is(), "comphelper.container", "An empty entry in the embedded objects list!\n" );
if ( xObj.is() )
{
uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
if ( xPersist.is() )
{
try
{
xPersist->setPersistentEntry( _xStorage,
*pIter,
embed::EntryInitModes::NO_INIT,
uno::Sequence< beans::PropertyValue >(),
uno::Sequence< beans::PropertyValue >() );
}
catch (const uno::Exception&)
{
// TODO/LATER: error handling
bError = sal_True;
break;
}
}
if ( _bClearModifedFlag )
{
// if this method is used as part of SaveCompleted the object must stay unmodified after execution
try
{
uno::Reference< util::XModifiable > xModif( xObj->getComponent(), uno::UNO_QUERY_THROW );
if ( xModif->isModified() )
xModif->setModified( sal_False );
}
catch (const uno::Exception&)
{
}
}
}
}
return bError;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */