1346 lines
51 KiB
C++
1346 lines
51 KiB
C++
/*************************************************************************
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: embeddedobjectcontainer.cxx,v $
|
|
*
|
|
* $Revision: 1.22 $
|
|
*
|
|
* last change: $Author: ihi $ $Date: 2007-07-11 14:09:53 $
|
|
*
|
|
* The Contents of this file are made available subject to
|
|
* the terms of GNU Lesser General Public License Version 2.1.
|
|
*
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2005 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_comphelper.hxx"
|
|
|
|
#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
|
|
#include <com/sun/star/container/XChild.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
|
|
#include <com/sun/star/container/XNameAccess.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_EMBED_XEMBEDOBJECTCREATOR_HPP_
|
|
#include <com/sun/star/embed/XEmbedObjectCreator.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_EMBED_XLINKCREATOR_HPP_
|
|
#include <com/sun/star/embed/XLinkCreator.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_EMBED_XEMBEDPERSIST_HPP_
|
|
#include <com/sun/star/embed/XEmbedPersist.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_EMBED_XLINKAGESUPPORT_HPP_
|
|
#include <com/sun/star/embed/XLinkageSupport.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_EMBED_XTRANSACTEDOBJECT_HPP_
|
|
#include <com/sun/star/embed/XTransactedObject.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_EMBED_XOPTIMIZEDSTORAGE_HPP_
|
|
#include <com/sun/star/embed/XOptimizedStorage.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_UTIL_XCLOSEABLE_HPP_
|
|
#include <com/sun/star/util/XCloseable.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_EMBED_EMBEDSTATES_HPP_
|
|
#include <com/sun/star/embed/EmbedStates.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_DATATRANSFER_XTRANSFERABLE_HPP_
|
|
#include <com/sun/star/datatransfer/XTransferable.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HPP_
|
|
#include <com/sun/star/beans/XPropertySetInfo.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_EMBED_ASPECTS_HPP_
|
|
#include <com/sun/star/embed/Aspects.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_EMBED_EMBEDMISC_HPP_
|
|
#include <com/sun/star/embed/EmbedMisc.hpp>
|
|
#endif
|
|
|
|
#include <comphelper/seqstream.hxx>
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <comphelper/storagehelper.hxx>
|
|
#include <comphelper/embeddedobjectcontainer.hxx>
|
|
#include <cppuhelper/weakref.hxx>
|
|
#include <hash_map>
|
|
#include <algorithm>
|
|
|
|
#include <rtl/logfile.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
namespace comphelper
|
|
{
|
|
|
|
struct hashObjectName_Impl
|
|
{
|
|
size_t operator()(const ::rtl::OUString Str) const
|
|
{
|
|
return (size_t)Str.hashCode();
|
|
}
|
|
};
|
|
|
|
struct eqObjectName_Impl
|
|
{
|
|
sal_Bool operator()(const ::rtl::OUString Str1, const ::rtl::OUString Str2) const
|
|
{
|
|
return ( Str1 == Str2 );
|
|
}
|
|
};
|
|
|
|
typedef std::hash_map
|
|
<
|
|
::rtl::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;
|
|
sal_Bool bOwnsStorage;
|
|
|
|
const uno::Reference < embed::XStorage >& GetReplacements();
|
|
};
|
|
|
|
const uno::Reference < embed::XStorage >& EmbedImpl::GetReplacements()
|
|
{
|
|
if ( !mxImageStorage.is() )
|
|
{
|
|
try
|
|
{
|
|
mxImageStorage = mxStorage->openStorageElement(
|
|
::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READWRITE );
|
|
}
|
|
catch ( uno::Exception& )
|
|
{
|
|
mxImageStorage = mxStorage->openStorageElement(
|
|
::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READ );
|
|
}
|
|
}
|
|
|
|
if ( !mxImageStorage.is() )
|
|
throw io::IOException();
|
|
|
|
return mxImageStorage;
|
|
}
|
|
|
|
EmbeddedObjectContainer::EmbeddedObjectContainer()
|
|
{
|
|
pImpl = new EmbedImpl;
|
|
pImpl->mxStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
|
|
pImpl->bOwnsStorage = sal_True;
|
|
pImpl->mpTempObjectContainer = 0;
|
|
}
|
|
|
|
EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor )
|
|
{
|
|
pImpl = new EmbedImpl;
|
|
pImpl->mxStorage = rStor;
|
|
pImpl->bOwnsStorage = sal_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 = sal_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 = sal_False;
|
|
}
|
|
|
|
sal_Bool EmbeddedObjectContainer::CommitImageSubStorage()
|
|
{
|
|
if ( pImpl->mxImageStorage.is() )
|
|
{
|
|
try
|
|
{
|
|
uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW );
|
|
xTransact->commit();
|
|
}
|
|
catch( 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( uno::Exception& )
|
|
{
|
|
OSL_ASSERT( "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 ( uno::Exception& )
|
|
{
|
|
}
|
|
}
|
|
|
|
aIt++;
|
|
}
|
|
}
|
|
|
|
::rtl::OUString EmbeddedObjectContainer::CreateUniqueObjectName()
|
|
{
|
|
::rtl::OUString aPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
|
|
::rtl::OUString aStr;
|
|
sal_Int32 i=1;
|
|
do
|
|
{
|
|
aStr = aPersistName;
|
|
aStr += ::rtl::OUString::valueOf( i++ );
|
|
}
|
|
while( HasEmbeddedObject( aStr ) );
|
|
// TODO/LATER: should we consider deleted objects?
|
|
|
|
return aStr;
|
|
}
|
|
|
|
uno::Sequence < ::rtl::OUString > EmbeddedObjectContainer::GetObjectNames()
|
|
{
|
|
uno::Sequence < ::rtl::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 ::rtl::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;
|
|
}
|
|
|
|
::rtl::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++;
|
|
}
|
|
|
|
OSL_ENSURE( 0, "Unknown object!" );
|
|
return ::rtl::OUString();
|
|
}
|
|
|
|
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::GetEmbeddedObject( const ::rtl::OUString& rName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetEmbeddedObject" );
|
|
|
|
OSL_ENSURE( rName.getLength(), "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 );
|
|
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 ::rtl::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( ::rtl::OUString::createFromAscii("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::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
|
|
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
|
|
uno::Sequence< beans::PropertyValue > aObjDescr( xCopy.is() ? 2 : 1 );
|
|
aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
|
|
aObjDescr[0].Value <<= pImpl->m_xModel.get();
|
|
if ( xCopy.is() )
|
|
{
|
|
aObjDescr[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CloneFrom" ) );
|
|
aObjDescr[1].Value <<= xCopy;
|
|
}
|
|
|
|
xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromEntry(
|
|
pImpl->mxStorage, rName,
|
|
bReadOnlyMode, aObjDescr ), uno::UNO_QUERY );
|
|
|
|
// insert object into my list
|
|
AddEmbeddedObject( xObj, rName );
|
|
}
|
|
catch ( uno::Exception& )
|
|
{
|
|
}
|
|
|
|
return xObj;
|
|
}
|
|
|
|
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId,
|
|
const uno::Sequence < beans::PropertyValue >& rArgs, ::rtl::OUString& rNewName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CreateEmbeddedObject" );
|
|
|
|
if ( !rNewName.getLength() )
|
|
rNewName = CreateUniqueObjectName();
|
|
|
|
OSL_ENSURE( !HasEmbeddedObject(rNewName), "Object to create already exists!");
|
|
|
|
// create object from classid by inserting it into storage
|
|
uno::Reference < embed::XEmbeddedObject > xObj;
|
|
try
|
|
{
|
|
uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
|
|
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
|
|
|
|
uno::Sequence< beans::PropertyValue > aObjDescr( rArgs.getLength() + 1 );
|
|
aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "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, ::rtl::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& )
|
|
{
|
|
}
|
|
|
|
return xObj;
|
|
}
|
|
|
|
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId, ::rtl::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 ::rtl::OUString& rName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::AddEmbeddedObject" );
|
|
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
OSL_ENSURE( rName.getLength(), "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)
|
|
::rtl::OUString aTempName = (*aIt).first;
|
|
::rtl::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 ( 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, ::rtl::OUString& rName, sal_Bool bCopy )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::StoreEmbeddedObject" );
|
|
|
|
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
|
|
if ( !rName.getLength() )
|
|
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& )
|
|
{
|
|
// 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, ::rtl::OUString& rName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "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, ::rtl::OUString& rNewName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( InputStream )" );
|
|
|
|
if ( !rNewName.getLength() )
|
|
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 ( 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(
|
|
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
|
|
uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) ) ) );
|
|
}
|
|
catch ( uno::Exception& )
|
|
{
|
|
// complete disaster!
|
|
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 ( uno::Exception& )
|
|
{
|
|
}
|
|
|
|
return xRet;
|
|
}
|
|
|
|
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, ::rtl::OUString& rNewName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( MediaDescriptor )" );
|
|
|
|
if ( !rNewName.getLength() )
|
|
rNewName = CreateUniqueObjectName();
|
|
|
|
uno::Reference < embed::XEmbeddedObject > xObj;
|
|
try
|
|
{
|
|
uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
|
|
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
|
|
uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
|
|
aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "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 ( uno::Exception& )
|
|
{
|
|
}
|
|
|
|
return xObj;
|
|
}
|
|
|
|
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedLink( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, ::rtl::OUString& rNewName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedLink" );
|
|
|
|
if ( !rNewName.getLength() )
|
|
rNewName = CreateUniqueObjectName();
|
|
|
|
uno::Reference < embed::XEmbeddedObject > xObj;
|
|
try
|
|
{
|
|
uno::Reference < embed::XLinkCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
|
|
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
|
|
uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
|
|
aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "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& )
|
|
{
|
|
}
|
|
|
|
return xObj;
|
|
}
|
|
|
|
sal_Bool EmbeddedObjectContainer::TryToCopyGraphReplacement( EmbeddedObjectContainer& rSrc,
|
|
const ::rtl::OUString& aOrigName,
|
|
const ::rtl::OUString& aTargetName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::TryToCopyGraphReplacement" );
|
|
|
|
sal_Bool bResult = sal_False;
|
|
|
|
if ( ( &rSrc != this || !aOrigName.equals( aTargetName ) ) && aOrigName.getLength() && aTargetName.getLength() )
|
|
{
|
|
::rtl::OUString aMediaType;
|
|
uno::Reference < io::XInputStream > xGrStream = rSrc.GetGraphicStream( aOrigName, &aMediaType );
|
|
if ( xGrStream.is() )
|
|
bResult = InsertGraphicStream( xGrStream, aTargetName, aMediaType );
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
sal_Bool EmbeddedObjectContainer::CopyEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyEmbeddedObject" );
|
|
|
|
OSL_ENSURE( sal_False,
|
|
"This method is depricated! Use EmbeddedObjectContainer::CopyAndGetEmbeddedObject() to copy object!\n" );
|
|
|
|
// get the object name before(!) it is assigned to a new storage
|
|
::rtl::OUString aOrigName;
|
|
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
|
|
if ( xPersist.is() )
|
|
aOrigName = xPersist->getEntryName();
|
|
|
|
if ( !rName.getLength() )
|
|
rName = CreateUniqueObjectName();
|
|
|
|
if ( StoreEmbeddedObject( xObj, rName, sal_True ) )
|
|
{
|
|
TryToCopyGraphReplacement( rSrc, aOrigName, rName );
|
|
return sal_True;
|
|
}
|
|
|
|
return sal_False;
|
|
}
|
|
|
|
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CopyAndGetEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "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
|
|
::rtl::OUString aOrigName;
|
|
try
|
|
{
|
|
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY_THROW );
|
|
aOrigName = xPersist->getEntryName();
|
|
}
|
|
catch( uno::Exception& )
|
|
{}
|
|
|
|
if ( !rName.getLength() )
|
|
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
|
|
::rtl::OUString aURL = xOrigLinkage->getLinkURL();
|
|
if ( !aURL.getLength() )
|
|
throw uno::RuntimeException();
|
|
|
|
// create new linked object from the URL the link is based on
|
|
uno::Reference < embed::XLinkCreator > xCreator(
|
|
::comphelper::getProcessServiceFactory()->createInstance(
|
|
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
|
|
uno::UNO_QUERY_THROW );
|
|
|
|
uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
|
|
aMediaDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
|
|
aMediaDescr[0].Value <<= aURL;
|
|
uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
|
|
aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "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::XEmbedObjectCreator > xCreator(
|
|
::comphelper::getProcessServiceFactory()->createInstance(
|
|
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
|
|
uno::UNO_QUERY_THROW );
|
|
|
|
uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
|
|
aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "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( 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
|
|
OSL_ENSURE( sal_False, "Could not copy readonly property!\n" );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( xResult.is() )
|
|
AddEmbeddedObject( xResult, rName );
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
if ( xResult.is() )
|
|
{
|
|
try
|
|
{
|
|
xResult->close( sal_True );
|
|
}
|
|
catch( uno::Exception& )
|
|
{}
|
|
xResult = uno::Reference< embed::XEmbeddedObject >();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
OSL_ENSURE( xResult.is(), "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.getLength() )
|
|
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( uno::Exception& )
|
|
{}
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "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 );
|
|
::rtl::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 ( uno::Exception& e )
|
|
{
|
|
(void)e;
|
|
OSL_ENSURE( sal_False, "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++;
|
|
}
|
|
|
|
OSL_ENSURE( bRet, "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 ( uno::Exception& )
|
|
{
|
|
OSL_ENSURE( sal_False, "Failed to remove object from storage!" );
|
|
bRet = sal_False;
|
|
}
|
|
}
|
|
|
|
// rSrc.RemoveGraphicStream( aName );
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const ::rtl::OUString& rName, sal_Bool bClose )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Name )" );
|
|
|
|
uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( rName );
|
|
if ( xObj.is() )
|
|
return RemoveEmbeddedObject( xObj, bClose );
|
|
else
|
|
return sal_False;
|
|
}
|
|
|
|
sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( const ::rtl::OUString& rName, EmbeddedObjectContainer& rCnt )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "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
|
|
::rtl::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 ( uno::Exception& )
|
|
{
|
|
OSL_ENSURE(0,"Could not move object!");
|
|
return sal_False;
|
|
}
|
|
|
|
}
|
|
else
|
|
OSL_ENSURE(0,"Unknown object!");
|
|
return sal_False;
|
|
}
|
|
|
|
sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Bool bClose )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Object )" );
|
|
|
|
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
|
|
::rtl::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 ( util::CloseVetoException& )
|
|
{
|
|
bClose = sal_False;
|
|
}
|
|
}
|
|
|
|
if ( !bClose )
|
|
{
|
|
// somebody still needs the object, so we must assign a temporary persistence
|
|
try
|
|
{
|
|
if ( xPersist.is() )
|
|
{
|
|
/*
|
|
//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;
|
|
|
|
::rtl::OUString aTmpPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
|
|
aTmpPersistName += ::rtl::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
|
|
::rtl::OUString aOrigStorMediaType;
|
|
uno::Reference< beans::XPropertySet > xStorProps( pImpl->mxStorage, uno::UNO_QUERY_THROW );
|
|
xStorProps->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) )
|
|
>>= aOrigStorMediaType;
|
|
|
|
OSL_ENSURE( aOrigStorMediaType.getLength(), "No valuable media type in the storage!\n" );
|
|
|
|
uno::Reference< beans::XPropertySet > xTargetStorProps(
|
|
pImpl->mpTempObjectContainer->pImpl->mxStorage,
|
|
uno::UNO_QUERY_THROW );
|
|
xTargetStorProps->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ),
|
|
uno::makeAny( aOrigStorMediaType ) );
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
OSL_ENSURE( sal_False, "Can not set the new media type to a storage!\n" );
|
|
}
|
|
}
|
|
|
|
::rtl::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 ( 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++;
|
|
}
|
|
|
|
OSL_ENSURE( bFound, "Object not found for removal!" );
|
|
if ( xPersist.is() )
|
|
{
|
|
// 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 ( uno::Exception& )
|
|
{
|
|
OSL_ENSURE( sal_False, "Failed to remove object from storage!" );
|
|
return sal_False;
|
|
}
|
|
}
|
|
|
|
return sal_True;
|
|
}
|
|
|
|
sal_Bool EmbeddedObjectContainer::CloseEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "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 ( 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 ::rtl::OUString& aName, rtl::OUString* pMediaType )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Name )" );
|
|
|
|
uno::Reference < io::XInputStream > xStream;
|
|
|
|
OSL_ENSURE( aName.getLength(), "Retrieving graphic for unknown object!" );
|
|
if ( aName.getLength() )
|
|
{
|
|
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( ::rtl::OUString::createFromAscii("MediaType") );
|
|
aAny >>= *pMediaType;
|
|
}
|
|
}
|
|
}
|
|
catch ( uno::Exception& )
|
|
{
|
|
}
|
|
}
|
|
|
|
return xStream;
|
|
}
|
|
|
|
uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, rtl::OUString* pMediaType )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Object )" );
|
|
|
|
// get the object name
|
|
::rtl::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 ::rtl::OUString& rObjectName, const rtl::OUString& rMediaType )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "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( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ),
|
|
uno::makeAny( (sal_Bool)sal_True ) );
|
|
uno::Any aAny;
|
|
aAny <<= rMediaType;
|
|
xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii("MediaType"), aAny );
|
|
|
|
xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "Compressed" ),
|
|
uno::makeAny( (sal_Bool)sal_True ) );
|
|
}
|
|
catch( 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 ::rtl::OUString& rObjectName, const rtl::OUString& rMediaType )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "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 = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
|
|
aProps[0].Value <<= rMediaType;
|
|
aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" ) );
|
|
aProps[1].Value <<= (sal_Bool)sal_True;
|
|
aProps[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
|
|
aProps[2].Value <<= (sal_Bool)sal_True;
|
|
|
|
if ( xReplacement->hasByName( rObjectName ) )
|
|
xReplacement->removeElement( rObjectName );
|
|
|
|
xOptRepl->insertStreamElementDirect( rObjectName, rStream, aProps );
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
return sal_False;
|
|
}
|
|
|
|
return sal_True;
|
|
}
|
|
|
|
|
|
sal_Bool EmbeddedObjectContainer::RemoveGraphicStream( const ::rtl::OUString& rObjectName )
|
|
{
|
|
RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveGraphicStream" );
|
|
|
|
try
|
|
{
|
|
uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
|
|
xReplacements->removeElement( rObjectName );
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
return sal_False;
|
|
}
|
|
|
|
return sal_True;
|
|
}
|
|
|
|
}
|