1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: embeddedobjectcontainer.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_comphelper.hxx"
33 #include <com/sun/star/container/XChild.hpp>
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
36 #include <com/sun/star/embed/XLinkCreator.hpp>
37 #include <com/sun/star/embed/XEmbedPersist.hpp>
38 #include <com/sun/star/embed/XLinkageSupport.hpp>
39 #include <com/sun/star/embed/XTransactedObject.hpp>
40 #include <com/sun/star/embed/XOptimizedStorage.hpp>
41 #include <com/sun/star/embed/EntryInitModes.hpp>
42 #include <com/sun/star/util/XCloseable.hpp>
43 #include <com/sun/star/util/XModifiable.hpp>
44 #include <com/sun/star/embed/EmbedStates.hpp>
45 #include <com/sun/star/datatransfer/XTransferable.hpp>
46 #include <com/sun/star/beans/XPropertySetInfo.hpp>
47 #include <com/sun/star/beans/XPropertySet.hpp>
48 #include <com/sun/star/embed/Aspects.hpp>
49 #include <com/sun/star/embed/EmbedMisc.hpp>
51 #include <comphelper/seqstream.hxx>
52 #include <comphelper/processfactory.hxx>
53 #include <comphelper/storagehelper.hxx>
54 #include <comphelper/embeddedobjectcontainer.hxx>
55 #include <comphelper/sequence.hxx>
56 #include <cppuhelper/weakref.hxx>
60 #include <rtl/logfile.hxx>
62 using namespace ::com::sun::star
;
67 struct hashObjectName_Impl
69 size_t operator()(const ::rtl::OUString Str
) const
71 return (size_t)Str
.hashCode();
75 struct eqObjectName_Impl
77 sal_Bool
operator()(const ::rtl::OUString Str1
, const ::rtl::OUString Str2
) const
79 return ( Str1
== Str2
);
86 ::com::sun::star::uno::Reference
< com::sun::star::embed::XEmbeddedObject
>,
90 EmbeddedObjectContainerNameMap
;
94 // TODO/LATER: remove objects from temp. Container storage when object is disposed
95 EmbeddedObjectContainerNameMap maObjectContainer
;
96 uno::Reference
< embed::XStorage
> mxStorage
;
97 EmbeddedObjectContainer
* mpTempObjectContainer
;
98 uno::Reference
< embed::XStorage
> mxImageStorage
;
99 uno::WeakReference
< uno::XInterface
> m_xModel
;
100 //EmbeddedObjectContainerNameMap maTempObjectContainer;
101 //uno::Reference < embed::XStorage > mxTempStorage;
102 sal_Bool bOwnsStorage
;
104 const uno::Reference
< embed::XStorage
>& GetReplacements();
107 const uno::Reference
< embed::XStorage
>& EmbedImpl::GetReplacements()
109 if ( !mxImageStorage
.is() )
113 mxImageStorage
= mxStorage
->openStorageElement(
114 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READWRITE
);
116 catch ( uno::Exception
& )
118 mxImageStorage
= mxStorage
->openStorageElement(
119 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READ
);
123 if ( !mxImageStorage
.is() )
124 throw io::IOException();
126 return mxImageStorage
;
129 EmbeddedObjectContainer::EmbeddedObjectContainer()
131 pImpl
= new EmbedImpl
;
132 pImpl
->mxStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
133 pImpl
->bOwnsStorage
= sal_True
;
134 pImpl
->mpTempObjectContainer
= 0;
137 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference
< embed::XStorage
>& rStor
)
139 pImpl
= new EmbedImpl
;
140 pImpl
->mxStorage
= rStor
;
141 pImpl
->bOwnsStorage
= sal_False
;
142 pImpl
->mpTempObjectContainer
= 0;
145 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference
< embed::XStorage
>& rStor
, const uno::Reference
< uno::XInterface
>& xModel
)
147 pImpl
= new EmbedImpl
;
148 pImpl
->mxStorage
= rStor
;
149 pImpl
->bOwnsStorage
= sal_False
;
150 pImpl
->mpTempObjectContainer
= 0;
151 pImpl
->m_xModel
= xModel
;
154 void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference
< embed::XStorage
>& rStor
)
156 ReleaseImageSubStorage();
158 if ( pImpl
->bOwnsStorage
)
159 pImpl
->mxStorage
->dispose();
161 pImpl
->mxStorage
= rStor
;
162 pImpl
->bOwnsStorage
= sal_False
;
165 sal_Bool
EmbeddedObjectContainer::CommitImageSubStorage()
167 if ( pImpl
->mxImageStorage
.is() )
171 sal_Bool bReadOnlyMode
= sal_True
;
172 uno::Reference
< beans::XPropertySet
> xSet(pImpl
->mxImageStorage
,uno::UNO_QUERY
);
175 // get the open mode from the parent storage
177 uno::Any aAny
= xSet
->getPropertyValue( ::rtl::OUString::createFromAscii("OpenMode") );
178 if ( aAny
>>= nMode
)
179 bReadOnlyMode
= !(nMode
& embed::ElementModes::WRITE
);
180 } // if ( xSet.is() )
181 if ( !bReadOnlyMode
)
183 uno::Reference
< embed::XTransactedObject
> xTransact( pImpl
->mxImageStorage
, uno::UNO_QUERY_THROW
);
187 catch( uno::Exception
& )
196 void EmbeddedObjectContainer::ReleaseImageSubStorage()
198 CommitImageSubStorage();
200 if ( pImpl
->mxImageStorage
.is() )
204 pImpl
->mxImageStorage
->dispose();
205 pImpl
->mxImageStorage
= uno::Reference
< embed::XStorage
>();
207 catch( uno::Exception
& )
209 OSL_ASSERT( "Problems releasing image substorage!\n" );
214 EmbeddedObjectContainer::~EmbeddedObjectContainer()
216 ReleaseImageSubStorage();
218 if ( pImpl
->bOwnsStorage
)
219 pImpl
->mxStorage
->dispose();
221 delete pImpl
->mpTempObjectContainer
;
225 void EmbeddedObjectContainer::CloseEmbeddedObjects()
227 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
228 while ( aIt
!= pImpl
->maObjectContainer
.end() )
230 uno::Reference
< util::XCloseable
> xClose( (*aIt
).second
, uno::UNO_QUERY
);
235 xClose
->close( sal_True
);
237 catch ( uno::Exception
& )
246 ::rtl::OUString
EmbeddedObjectContainer::CreateUniqueObjectName()
248 ::rtl::OUString aPersistName
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
249 ::rtl::OUString aStr
;
254 aStr
+= ::rtl::OUString::valueOf( i
++ );
256 while( HasEmbeddedObject( aStr
) );
257 // TODO/LATER: should we consider deleted objects?
262 uno::Sequence
< ::rtl::OUString
> EmbeddedObjectContainer::GetObjectNames()
264 uno::Sequence
< ::rtl::OUString
> aSeq( pImpl
->maObjectContainer
.size() );
265 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
267 while ( aIt
!= pImpl
->maObjectContainer
.end() )
268 aSeq
[nIdx
++] = (*aIt
++).first
;
272 sal_Bool
EmbeddedObjectContainer::HasEmbeddedObjects()
274 return pImpl
->maObjectContainer
.size() != 0;
277 sal_Bool
EmbeddedObjectContainer::HasEmbeddedObject( const ::rtl::OUString
& rName
)
279 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
280 if ( aIt
== pImpl
->maObjectContainer
.end() )
282 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
283 return xAccess
->hasByName(rName
);
289 sal_Bool
EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
)
291 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
292 while ( aIt
!= pImpl
->maObjectContainer
.end() )
294 if ( (*aIt
).second
== xObj
)
303 sal_Bool
EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const ::rtl::OUString
& rName
)
305 // allows to detect whether the object was already instantiated
306 // currently the filter instantiate it on loading, so this method allows
307 // to avoid objects pointing to the same persistence
308 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
309 return ( aIt
!= pImpl
->maObjectContainer
.end() );
312 ::rtl::OUString
EmbeddedObjectContainer::GetEmbeddedObjectName( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XEmbeddedObject
>& xObj
)
314 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
315 while ( aIt
!= pImpl
->maObjectContainer
.end() )
317 if ( (*aIt
).second
== xObj
)
323 OSL_ENSURE( 0, "Unknown object!" );
324 return ::rtl::OUString();
327 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::GetEmbeddedObject( const ::rtl::OUString
& rName
)
329 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetEmbeddedObject" );
331 OSL_ENSURE( rName
.getLength(), "Empty object name!");
333 uno::Reference
< embed::XEmbeddedObject
> xObj
;
334 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
336 #if OSL_DEBUG_LEVEL > 1
337 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
338 uno::Sequence
< ::rtl::OUString
> aSeq
= xAccess
->getElementNames();
339 const ::rtl::OUString
* pIter
= aSeq
.getConstArray();
340 const ::rtl::OUString
* pEnd
= pIter
+ aSeq
.getLength();
341 for(;pIter
!= pEnd
;++pIter
)
345 OSL_ENSURE( aIt
!= pImpl
->maObjectContainer
.end() || xAccess
->hasByName(rName
), "Could not return object!" );
348 // check if object was already created
349 if ( aIt
!= pImpl
->maObjectContainer
.end() )
350 xObj
= (*aIt
).second
;
352 xObj
= Get_Impl( rName
, uno::Reference
< embed::XEmbeddedObject
>() );
357 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::Get_Impl( const ::rtl::OUString
& rName
, const uno::Reference
< embed::XEmbeddedObject
>& xCopy
)
359 uno::Reference
< embed::XEmbeddedObject
> xObj
;
362 // create the object from the storage
363 uno::Reference
< beans::XPropertySet
> xSet( pImpl
->mxStorage
, uno::UNO_QUERY
);
364 sal_Bool bReadOnlyMode
= sal_True
;
367 // get the open mode from the parent storage
369 uno::Any aAny
= xSet
->getPropertyValue( ::rtl::OUString::createFromAscii("OpenMode") );
370 if ( aAny
>>= nMode
)
371 bReadOnlyMode
= !(nMode
& embed::ElementModes::WRITE
);
374 // object was not added until now - should happen only by calling this method from "inside"
375 //TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call)
376 uno::Reference
< embed::XEmbedObjectCreator
> xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
377 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY
);
378 uno::Sequence
< beans::PropertyValue
> aObjDescr( xCopy
.is() ? 2 : 1 );
379 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
380 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
383 aObjDescr
[1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CloneFrom" ) );
384 aObjDescr
[1].Value
<<= xCopy
;
387 uno::Sequence
< beans::PropertyValue
> aMediaDescr( 1 );
388 aMediaDescr
[0].Name
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly"));
389 aMediaDescr
[0].Value
<<= bReadOnlyMode
;
390 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceInitFromEntry(
391 pImpl
->mxStorage
, rName
,
392 aMediaDescr
, aObjDescr
), uno::UNO_QUERY
);
394 // insert object into my list
395 AddEmbeddedObject( xObj
, rName
);
397 catch ( uno::Exception
& )
404 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence
< sal_Int8
>& rClassId
,
405 const uno::Sequence
< beans::PropertyValue
>& rArgs
, ::rtl::OUString
& rNewName
)
407 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CreateEmbeddedObject" );
409 if ( !rNewName
.getLength() )
410 rNewName
= CreateUniqueObjectName();
412 OSL_ENSURE( !HasEmbeddedObject(rNewName
), "Object to create already exists!");
414 // create object from classid by inserting it into storage
415 uno::Reference
< embed::XEmbeddedObject
> xObj
;
418 uno::Reference
< embed::XEmbedObjectCreator
> xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
419 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY
);
421 uno::Sequence
< beans::PropertyValue
> aObjDescr( rArgs
.getLength() + 1 );
422 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
423 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
424 ::std::copy( rArgs
.getConstArray(), rArgs
.getConstArray() + rArgs
.getLength(), aObjDescr
.getArray() + 1 );
425 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceInitNew(
426 rClassId
, ::rtl::OUString(), pImpl
->mxStorage
, rNewName
,
427 aObjDescr
), uno::UNO_QUERY
);
429 AddEmbeddedObject( xObj
, rNewName
);
431 OSL_ENSURE( !xObj
.is() || xObj
->getCurrentState() != embed::EmbedStates::LOADED
,
432 "A freshly create object should be running always!\n" );
434 catch ( uno::Exception
& )
441 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence
< sal_Int8
>& rClassId
, ::rtl::OUString
& rNewName
)
443 return CreateEmbeddedObject( rClassId
, uno::Sequence
< beans::PropertyValue
>(), rNewName
);
446 void EmbeddedObjectContainer::AddEmbeddedObject( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XEmbeddedObject
>& xObj
, const ::rtl::OUString
& rName
)
448 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::AddEmbeddedObject" );
450 #if OSL_DEBUG_LEVEL > 1
451 OSL_ENSURE( rName
.getLength(), "Added object doesn't have a name!");
452 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
453 uno::Reference
< embed::XEmbedPersist
> xEmb( xObj
, uno::UNO_QUERY
);
454 uno::Reference
< embed::XLinkageSupport
> xLink( xEmb
, uno::UNO_QUERY
);
455 // if the object has a persistance and the object is not a link than it must have persistence entry in the storage
456 OSL_ENSURE( !( xEmb
.is() && ( !xLink
.is() || !xLink
->isLink() ) ) || xAccess
->hasByName(rName
),
457 "Added element not in storage!" );
460 // remember object - it needs to be in storage already
461 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
462 OSL_ENSURE( aIt
== pImpl
->maObjectContainer
.end(), "Element already inserted!" );
463 pImpl
->maObjectContainer
[ rName
] = xObj
;
464 uno::Reference
< container::XChild
> xChild( xObj
, uno::UNO_QUERY
);
465 if ( xChild
.is() && xChild
->getParent() != pImpl
->m_xModel
.get() )
466 xChild
->setParent( pImpl
->m_xModel
.get() );
468 // look for object in temorary container
469 if ( pImpl
->mpTempObjectContainer
)
471 aIt
= pImpl
->mpTempObjectContainer
->pImpl
->maObjectContainer
.begin();
472 while ( aIt
!= pImpl
->mpTempObjectContainer
->pImpl
->maObjectContainer
.end() )
474 if ( (*aIt
).second
== xObj
)
476 // copy replacement image from temporary container (if there is any)
477 ::rtl::OUString aTempName
= (*aIt
).first
;
478 ::rtl::OUString aMediaType
;
479 uno::Reference
< io::XInputStream
> xStream
= pImpl
->mpTempObjectContainer
->GetGraphicStream( xObj
, &aMediaType
);
482 InsertGraphicStream( xStream
, rName
, aMediaType
);
484 pImpl
->mpTempObjectContainer
->RemoveGraphicStream( aTempName
);
487 // remove object from storage of temporary container
488 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
493 pImpl
->mpTempObjectContainer
->pImpl
->mxStorage
->removeElement( aTempName
);
495 catch ( uno::Exception
& )
500 // temp. container needs to forget the object
501 pImpl
->mpTempObjectContainer
->pImpl
->maObjectContainer
.erase( aIt
);
510 sal_Bool
EmbeddedObjectContainer::StoreEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
, ::rtl::OUString
& rName
, sal_Bool bCopy
)
512 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::StoreEmbeddedObject" );
514 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
515 if ( !rName
.getLength() )
516 rName
= CreateUniqueObjectName();
518 #if OSL_DEBUG_LEVEL > 1
519 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
520 OSL_ENSURE( !xPersist
.is() || !xAccess
->hasByName(rName
), "Inserting element already present in storage!" );
521 OSL_ENSURE( xPersist
.is() || xObj
->getCurrentState() == embed::EmbedStates::RUNNING
, "Non persistent object inserted!");
524 // insert objects' storage into the container storage (if object has one)
529 uno::Sequence
< beans::PropertyValue
> aSeq
;
531 xPersist
->storeToEntry( pImpl
->mxStorage
, rName
, aSeq
, aSeq
);
534 //TODO/LATER: possible optimisation, don't store immediately
535 //xPersist->setPersistentEntry( pImpl->mxStorage, rName, embed::EntryInitModes::ENTRY_NO_INIT, aSeq, aSeq );
536 xPersist
->storeAsEntry( pImpl
->mxStorage
, rName
, aSeq
, aSeq
);
537 xPersist
->saveCompleted( sal_True
);
541 catch ( uno::Exception
& )
543 // TODO/LATER: better error recovery should keep storage intact
550 sal_Bool
EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
, ::rtl::OUString
& rName
)
552 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( Object )" );
553 // store it into the container storage
554 if ( StoreEmbeddedObject( xObj
, rName
, sal_False
) )
557 AddEmbeddedObject( xObj
, rName
);
564 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference
< io::XInputStream
>& xStm
, ::rtl::OUString
& rNewName
)
566 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( InputStream )" );
568 if ( !rNewName
.getLength() )
569 rNewName
= CreateUniqueObjectName();
571 // store it into the container storage
572 sal_Bool bIsStorage
= sal_False
;
575 // first try storage persistence
576 uno::Reference
< embed::XStorage
> xStore
= ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm
);
578 // storage was created from stream successfully
579 bIsStorage
= sal_True
;
581 uno::Reference
< embed::XStorage
> xNewStore
= pImpl
->mxStorage
->openStorageElement( rNewName
, embed::ElementModes::READWRITE
);
582 xStore
->copyToStorage( xNewStore
);
584 catch ( uno::Exception
& )
587 // it is storage persistence, but opening of new substorage or copying to it failed
588 return uno::Reference
< embed::XEmbeddedObject
>();
590 // stream didn't contain a storage, now try stream persistence
593 uno::Reference
< io::XStream
> xNewStream
= pImpl
->mxStorage
->openStreamElement( rNewName
, embed::ElementModes::READWRITE
);
594 ::comphelper::OStorageHelper::CopyInputToOutput( xStm
, xNewStream
->getOutputStream() );
596 // No mediatype is provided so the default for OLE objects value is used
597 // it is correct so for now, but what if somebody introduces a new stream based embedded object?
598 // Probably introducing of such an object must be restricted ( a storage must be used! ).
599 uno::Reference
< beans::XPropertySet
> xProps( xNewStream
, uno::UNO_QUERY_THROW
);
600 xProps
->setPropertyValue(
601 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
602 uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) ) ) );
604 catch ( uno::Exception
& )
606 // complete disaster!
607 return uno::Reference
< embed::XEmbeddedObject
>();
611 // stream was copied into the container storage in either way, now try to open something form it
612 uno::Reference
< embed::XEmbeddedObject
> xRet
= GetEmbeddedObject( rNewName
);
616 // no object could be created, so withdraw insertion
617 pImpl
->mxStorage
->removeElement( rNewName
);
619 catch ( uno::Exception
& )
626 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::InsertEmbeddedObject( const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& aMedium
, ::rtl::OUString
& rNewName
)
628 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( MediaDescriptor )" );
630 if ( !rNewName
.getLength() )
631 rNewName
= CreateUniqueObjectName();
633 uno::Reference
< embed::XEmbeddedObject
> xObj
;
636 uno::Reference
< embed::XEmbedObjectCreator
> xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
637 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY
);
638 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
639 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
640 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
641 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceInitFromMediaDescriptor(
642 pImpl
->mxStorage
, rNewName
, aMedium
, aObjDescr
), uno::UNO_QUERY
);
643 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
645 OSL_ENSURE( !xObj
.is() || xObj
->getCurrentState() != embed::EmbedStates::LOADED
,
646 "A freshly create object should be running always!\n" );
648 // possible optimization: store later!
650 xPersist
->storeOwn();
652 AddEmbeddedObject( xObj
, rNewName
);
654 catch ( uno::Exception
& )
661 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::InsertEmbeddedLink( const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& aMedium
, ::rtl::OUString
& rNewName
)
663 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedLink" );
665 if ( !rNewName
.getLength() )
666 rNewName
= CreateUniqueObjectName();
668 uno::Reference
< embed::XEmbeddedObject
> xObj
;
671 uno::Reference
< embed::XLinkCreator
> xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
672 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY
);
673 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
674 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
675 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
676 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceLink(
677 pImpl
->mxStorage
, rNewName
, aMedium
, aObjDescr
), uno::UNO_QUERY
);
679 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
681 OSL_ENSURE( !xObj
.is() || xObj
->getCurrentState() != embed::EmbedStates::LOADED
,
682 "A freshly create object should be running always!\n" );
684 // possible optimization: store later!
686 xPersist
->storeOwn();
688 AddEmbeddedObject( xObj
, rNewName
);
690 catch ( uno::Exception
& )
697 sal_Bool
EmbeddedObjectContainer::TryToCopyGraphReplacement( EmbeddedObjectContainer
& rSrc
,
698 const ::rtl::OUString
& aOrigName
,
699 const ::rtl::OUString
& aTargetName
)
701 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::TryToCopyGraphReplacement" );
703 sal_Bool bResult
= sal_False
;
705 if ( ( &rSrc
!= this || !aOrigName
.equals( aTargetName
) ) && aOrigName
.getLength() && aTargetName
.getLength() )
707 ::rtl::OUString aMediaType
;
708 uno::Reference
< io::XInputStream
> xGrStream
= rSrc
.GetGraphicStream( aOrigName
, &aMediaType
);
709 if ( xGrStream
.is() )
710 bResult
= InsertGraphicStream( xGrStream
, aTargetName
, aMediaType
);
716 sal_Bool
EmbeddedObjectContainer::CopyEmbeddedObject( EmbeddedObjectContainer
& rSrc
, const uno::Reference
< embed::XEmbeddedObject
>& xObj
, ::rtl::OUString
& rName
)
718 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyEmbeddedObject" );
720 OSL_ENSURE( sal_False
,
721 "This method is depricated! Use EmbeddedObjectContainer::CopyAndGetEmbeddedObject() to copy object!\n" );
723 // get the object name before(!) it is assigned to a new storage
724 ::rtl::OUString aOrigName
;
725 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
727 aOrigName
= xPersist
->getEntryName();
729 if ( !rName
.getLength() )
730 rName
= CreateUniqueObjectName();
732 if ( StoreEmbeddedObject( xObj
, rName
, sal_True
) )
734 TryToCopyGraphReplacement( rSrc
, aOrigName
, rName
);
741 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::CopyAndGetEmbeddedObject( EmbeddedObjectContainer
& rSrc
, const uno::Reference
< embed::XEmbeddedObject
>& xObj
, ::rtl::OUString
& rName
)
743 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyAndGetEmbeddedObject" );
745 uno::Reference
< embed::XEmbeddedObject
> xResult
;
747 // TODO/LATER: For now only objects that implement XEmbedPersist have a replacement image, it might change in future
748 // do an incompatible change so that object name is provided in all the move and copy methods
749 ::rtl::OUString aOrigName
;
752 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY_THROW
);
753 aOrigName
= xPersist
->getEntryName();
755 catch( uno::Exception
& )
758 if ( !rName
.getLength() )
759 rName
= CreateUniqueObjectName();
761 // objects without persistance are not really stored by the method
762 if ( xObj
.is() && StoreEmbeddedObject( xObj
, rName
, sal_True
) )
764 xResult
= Get_Impl( rName
, xObj
);
767 // this is a case when object has no real persistence
768 // in such cases a new object should be explicitly created and initialized with the data of the old one
771 uno::Reference
< embed::XLinkageSupport
> xOrigLinkage( xObj
, uno::UNO_QUERY
);
772 if ( xOrigLinkage
.is() && xOrigLinkage
->isLink() )
774 // this is a OOo link, it has no persistence
775 ::rtl::OUString aURL
= xOrigLinkage
->getLinkURL();
776 if ( !aURL
.getLength() )
777 throw uno::RuntimeException();
779 // create new linked object from the URL the link is based on
780 uno::Reference
< embed::XLinkCreator
> xCreator(
781 ::comphelper::getProcessServiceFactory()->createInstance(
782 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
783 uno::UNO_QUERY_THROW
);
785 uno::Sequence
< beans::PropertyValue
> aMediaDescr( 1 );
786 aMediaDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
787 aMediaDescr
[0].Value
<<= aURL
;
788 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
789 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
790 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
791 xResult
= uno::Reference
< embed::XEmbeddedObject
>(
792 xCreator
->createInstanceLink(
797 uno::UNO_QUERY_THROW
);
801 // the component is required for copying of this object
802 if ( xObj
->getCurrentState() == embed::EmbedStates::LOADED
)
803 xObj
->changeState( embed::EmbedStates::RUNNING
);
805 // this must be an object based on properties, otherwise we can not copy it currently
806 uno::Reference
< beans::XPropertySet
> xOrigProps( xObj
->getComponent(), uno::UNO_QUERY_THROW
);
808 // use object class ID to create a new one and tranfer all the properties
809 uno::Reference
< embed::XEmbedObjectCreator
> xCreator(
810 ::comphelper::getProcessServiceFactory()->createInstance(
811 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
812 uno::UNO_QUERY_THROW
);
814 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
815 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
816 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
817 xResult
= uno::Reference
< embed::XEmbeddedObject
>(
818 xCreator
->createInstanceInitNew(
820 xObj
->getClassName(),
824 uno::UNO_QUERY_THROW
);
826 if ( xResult
->getCurrentState() == embed::EmbedStates::LOADED
)
827 xResult
->changeState( embed::EmbedStates::RUNNING
);
829 uno::Reference
< beans::XPropertySet
> xTargetProps( xResult
->getComponent(), uno::UNO_QUERY_THROW
);
831 // copy all the properties from xOrigProps to xTargetProps
832 uno::Reference
< beans::XPropertySetInfo
> xOrigInfo
= xOrigProps
->getPropertySetInfo();
833 if ( !xOrigInfo
.is() )
834 throw uno::RuntimeException();
836 uno::Sequence
< beans::Property
> aPropertiesList
= xOrigInfo
->getProperties();
837 for ( sal_Int32 nInd
= 0; nInd
< aPropertiesList
.getLength(); nInd
++ )
841 xTargetProps
->setPropertyValue(
842 aPropertiesList
[nInd
].Name
,
843 xOrigProps
->getPropertyValue( aPropertiesList
[nInd
].Name
) );
845 catch( beans::PropertyVetoException
& )
847 // impossibility to copy readonly property is not treated as an error for now
848 // but the assertion is helpful to detect such scenarios and review them
849 OSL_ENSURE( sal_False
, "Could not copy readonly property!\n" );
855 AddEmbeddedObject( xResult
, rName
);
857 catch( uno::Exception
& )
863 xResult
->close( sal_True
);
865 catch( uno::Exception
& )
867 xResult
= uno::Reference
< embed::XEmbeddedObject
>();
873 OSL_ENSURE( xResult
.is(), "Can not copy embedded object that has no persistance!\n" );
877 // the object is successfully copied, try to copy graphical replacement
878 if ( aOrigName
.getLength() )
879 TryToCopyGraphReplacement( rSrc
, aOrigName
, rName
);
881 // the object might need the size to be set
884 if ( xResult
->getStatus( embed::Aspects::MSOLE_CONTENT
) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD
)
885 xResult
->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT
,
886 xObj
->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
) );
888 catch( uno::Exception
& )
895 sal_Bool
EmbeddedObjectContainer::MoveEmbeddedObject( EmbeddedObjectContainer
& rSrc
, const uno::Reference
< embed::XEmbeddedObject
>& xObj
, ::rtl::OUString
& rName
)
897 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Object )" );
899 // get the object name before(!) it is assigned to a new storage
900 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
901 ::rtl::OUString aName
;
903 aName
= xPersist
->getEntryName();
905 // now move the object to the new container; the returned name is the new persist name in this container
910 bRet
= InsertEmbeddedObject( xObj
, rName
);
912 TryToCopyGraphReplacement( rSrc
, aName
, rName
);
914 catch ( uno::Exception
& e
)
917 OSL_ENSURE( sal_False
, "Failed to insert embedded object into storage!" );
923 // now remove the object from the former container
925 EmbeddedObjectContainerNameMap::iterator aIt
= rSrc
.pImpl
->maObjectContainer
.begin();
926 while ( aIt
!= rSrc
.pImpl
->maObjectContainer
.end() )
928 if ( (*aIt
).second
== xObj
)
930 rSrc
.pImpl
->maObjectContainer
.erase( aIt
);
938 OSL_ENSURE( bRet
, "Object not found for removal!" );
941 // now it's time to remove the storage from the container storage
945 rSrc
.pImpl
->mxStorage
->removeElement( aName
);
947 catch ( uno::Exception
& )
949 OSL_ENSURE( sal_False
, "Failed to remove object from storage!" );
954 // rSrc.RemoveGraphicStream( aName );
960 sal_Bool
EmbeddedObjectContainer::RemoveEmbeddedObject( const ::rtl::OUString
& rName
, sal_Bool bClose
)
962 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Name )" );
964 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( rName
);
966 return RemoveEmbeddedObject( xObj
, bClose
);
971 sal_Bool
EmbeddedObjectContainer::MoveEmbeddedObject( const ::rtl::OUString
& rName
, EmbeddedObjectContainer
& rCnt
)
973 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Name )" );
976 EmbeddedObjectContainerNameMap::iterator aIt2
= rCnt
.pImpl
->maObjectContainer
.find( rName
);
977 OSL_ENSURE( aIt2
== rCnt
.pImpl
->maObjectContainer
.end(), "Object does already exist in target container!" );
979 if ( aIt2
!= rCnt
.pImpl
->maObjectContainer
.end() )
982 uno::Reference
< embed::XEmbeddedObject
> xObj
;
983 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
984 if ( aIt
!= pImpl
->maObjectContainer
.end() )
986 xObj
= (*aIt
).second
;
992 ::rtl::OUString
aName( rName
);
993 rCnt
.InsertEmbeddedObject( xObj
, aName
);
994 pImpl
->maObjectContainer
.erase( aIt
);
995 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
997 pImpl
->mxStorage
->removeElement( rName
);
1001 // copy storages; object *must* have persistence!
1002 uno::Reference
< embed::XStorage
> xOld
= pImpl
->mxStorage
->openStorageElement( rName
, embed::ElementModes::READ
);
1003 uno::Reference
< embed::XStorage
> xNew
= rCnt
.pImpl
->mxStorage
->openStorageElement( rName
, embed::ElementModes::READWRITE
);
1004 xOld
->copyToStorage( xNew
);
1007 rCnt
.TryToCopyGraphReplacement( *this, rName
, rName
);
1008 // RemoveGraphicStream( rName );
1012 catch ( uno::Exception
& )
1014 OSL_ENSURE(0,"Could not move object!");
1020 OSL_ENSURE(0,"Unknown object!");
1024 sal_Bool
EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
, sal_Bool bClose
)
1026 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Object )" );
1028 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1029 ::rtl::OUString aName
;
1030 if ( xPersist
.is() )
1031 aName
= xPersist
->getEntryName();
1033 #if OSL_DEBUG_LEVEL > 1
1034 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
1035 uno::Reference
< embed::XLinkageSupport
> xLink( xPersist
, uno::UNO_QUERY
);
1036 sal_Bool bIsNotEmbedded
= !xPersist
.is() || xLink
.is() && xLink
->isLink();
1038 // if the object has a persistance and the object is not a link than it must have persistence entry in the storage
1039 OSL_ENSURE( bIsNotEmbedded
|| xAccess
->hasByName(aName
), "Removing element not present in storage!" );
1042 // try to close it if permitted
1045 uno::Reference
< ::util::XCloseable
> xClose( xObj
, uno::UNO_QUERY
);
1048 xClose
->close( sal_True
);
1050 catch ( util::CloseVetoException
& )
1058 // somebody still needs the object, so we must assign a temporary persistence
1061 if ( xPersist
.is() )
1064 //TODO/LATER: needs storage handling! Why not letting the object do it?!
1065 if ( !pImpl->mxTempStorage.is() )
1066 pImpl->mxTempStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
1067 uno::Sequence < beans::PropertyValue > aSeq;
1069 ::rtl::OUString aTmpPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
1070 aTmpPersistName += ::rtl::OUString::valueOf( (sal_Int32) pImpl->maTempObjectContainer.size() );
1072 xPersist->storeAsEntry( pImpl->mxTempStorage, aTmpPersistName, aSeq, aSeq );
1073 xPersist->saveCompleted( sal_True );
1075 pImpl->maTempObjectContainer[ aTmpPersistName ] = uno::Reference < embed::XEmbeddedObject >();
1078 if ( !pImpl
->mpTempObjectContainer
)
1080 pImpl
->mpTempObjectContainer
= new EmbeddedObjectContainer();
1083 // TODO/LATER: in future probably the temporary container will have two storages ( of two formats )
1084 // the media type will be provided with object insertion
1085 ::rtl::OUString aOrigStorMediaType
;
1086 uno::Reference
< beans::XPropertySet
> xStorProps( pImpl
->mxStorage
, uno::UNO_QUERY_THROW
);
1087 static const ::rtl::OUString
s_sMediaType(RTL_CONSTASCII_USTRINGPARAM("MediaType"));
1088 xStorProps
->getPropertyValue( s_sMediaType
) >>= aOrigStorMediaType
;
1090 OSL_ENSURE( aOrigStorMediaType
.getLength(), "No valuable media type in the storage!\n" );
1092 uno::Reference
< beans::XPropertySet
> xTargetStorProps(
1093 pImpl
->mpTempObjectContainer
->pImpl
->mxStorage
,
1094 uno::UNO_QUERY_THROW
);
1095 xTargetStorProps
->setPropertyValue( s_sMediaType
,uno::makeAny( aOrigStorMediaType
) );
1097 catch( uno::Exception
& )
1099 OSL_ENSURE( sal_False
, "Can not set the new media type to a storage!\n" );
1103 ::rtl::OUString aTempName
, aMediaType
;
1104 pImpl
->mpTempObjectContainer
->InsertEmbeddedObject( xObj
, aTempName
);
1106 uno::Reference
< io::XInputStream
> xStream
= GetGraphicStream( xObj
, &aMediaType
);
1108 pImpl
->mpTempObjectContainer
->InsertGraphicStream( xStream
, aTempName
, aMediaType
);
1110 // object is stored, so at least it can be set to loaded state
1111 xObj
->changeState( embed::EmbedStates::LOADED
);
1114 // objects without persistence need to stay in running state if they shall not be closed
1115 xObj
->changeState( embed::EmbedStates::RUNNING
);
1117 catch ( uno::Exception
& )
1123 sal_Bool bFound
= sal_False
;
1124 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
1125 while ( aIt
!= pImpl
->maObjectContainer
.end() )
1127 if ( (*aIt
).second
== xObj
)
1129 pImpl
->maObjectContainer
.erase( aIt
);
1131 uno::Reference
< container::XChild
> xChild( xObj
, uno::UNO_QUERY
);
1133 xChild
->setParent( uno::Reference
< uno::XInterface
>() );
1140 OSL_ENSURE( bFound
, "Object not found for removal!" );
1141 if ( xPersist
.is() )
1143 // remove replacement image (if there is one)
1144 RemoveGraphicStream( aName
);
1146 // now it's time to remove the storage from the container storage
1149 #if OSL_DEBUG_LEVEL > 1
1150 // if the object has a persistance and the object is not a link than it must have persistence entry in storage
1151 OSL_ENSURE( bIsNotEmbedded
|| pImpl
->mxStorage
->hasByName( aName
), "The object has no persistence entry in the storage!" );
1153 if ( xPersist
.is() && pImpl
->mxStorage
->hasByName( aName
) )
1154 pImpl
->mxStorage
->removeElement( aName
);
1156 catch ( uno::Exception
& )
1158 OSL_ENSURE( sal_False
, "Failed to remove object from storage!" );
1166 sal_Bool
EmbeddedObjectContainer::CloseEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
)
1168 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CloseEmbeddedObject" );
1170 // disconnect the object from the container and close it if possible
1172 sal_Bool bFound
= sal_False
;
1173 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
1174 while ( aIt
!= pImpl
->maObjectContainer
.end() )
1176 if ( (*aIt
).second
== xObj
)
1178 pImpl
->maObjectContainer
.erase( aIt
);
1188 uno::Reference
< ::util::XCloseable
> xClose( xObj
, uno::UNO_QUERY
);
1191 xClose
->close( sal_True
);
1193 catch ( uno::Exception
& )
1195 // it is no problem if the object is already closed
1196 // TODO/LATER: what if the object can not be closed?
1203 uno::Reference
< io::XInputStream
> EmbeddedObjectContainer::GetGraphicStream( const ::rtl::OUString
& aName
, rtl::OUString
* pMediaType
)
1205 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Name )" );
1207 uno::Reference
< io::XInputStream
> xStream
;
1209 OSL_ENSURE( aName
.getLength(), "Retrieving graphic for unknown object!" );
1210 if ( aName
.getLength() )
1214 uno::Reference
< embed::XStorage
> xReplacements
= pImpl
->GetReplacements();
1215 uno::Reference
< io::XStream
> xGraphicStream
= xReplacements
->openStreamElement( aName
, embed::ElementModes::READ
);
1216 xStream
= xGraphicStream
->getInputStream();
1219 uno::Reference
< beans::XPropertySet
> xSet( xStream
, uno::UNO_QUERY
);
1222 uno::Any aAny
= xSet
->getPropertyValue( ::rtl::OUString::createFromAscii("MediaType") );
1223 aAny
>>= *pMediaType
;
1227 catch ( uno::Exception
& )
1235 uno::Reference
< io::XInputStream
> EmbeddedObjectContainer::GetGraphicStream( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XEmbeddedObject
>& xObj
, rtl::OUString
* pMediaType
)
1237 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Object )" );
1239 // get the object name
1240 ::rtl::OUString aName
;
1241 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
1242 while ( aIt
!= pImpl
->maObjectContainer
.end() )
1244 if ( (*aIt
).second
== xObj
)
1246 aName
= (*aIt
).first
;
1253 // try to load it from the container storage
1254 return GetGraphicStream( aName
, pMediaType
);
1257 sal_Bool
EmbeddedObjectContainer::InsertGraphicStream( const com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
>& rStream
, const ::rtl::OUString
& rObjectName
, const rtl::OUString
& rMediaType
)
1259 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStream" );
1263 uno::Reference
< embed::XStorage
> xReplacements
= pImpl
->GetReplacements();
1265 // store it into the subfolder
1266 uno::Reference
< io::XOutputStream
> xOutStream
;
1267 uno::Reference
< io::XStream
> xGraphicStream
= xReplacements
->openStreamElement( rObjectName
,
1268 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
1269 xOutStream
= xGraphicStream
->getOutputStream();
1270 ::comphelper::OStorageHelper::CopyInputToOutput( rStream
, xOutStream
);
1271 xOutStream
->flush();
1273 uno::Reference
< beans::XPropertySet
> xPropSet( xGraphicStream
, uno::UNO_QUERY
);
1274 if ( !xPropSet
.is() )
1275 throw uno::RuntimeException();
1277 xPropSet
->setPropertyValue( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ),
1278 uno::makeAny( (sal_Bool
)sal_True
) );
1280 aAny
<<= rMediaType
;
1281 xPropSet
->setPropertyValue( ::rtl::OUString::createFromAscii("MediaType"), aAny
);
1283 xPropSet
->setPropertyValue( ::rtl::OUString::createFromAscii( "Compressed" ),
1284 uno::makeAny( (sal_Bool
)sal_True
) );
1286 catch( uno::Exception
& )
1294 sal_Bool
EmbeddedObjectContainer::InsertGraphicStreamDirectly( const com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
>& rStream
, const ::rtl::OUString
& rObjectName
, const rtl::OUString
& rMediaType
)
1296 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStreamDirectly" );
1300 uno::Reference
< embed::XStorage
> xReplacement
= pImpl
->GetReplacements();
1301 uno::Reference
< embed::XOptimizedStorage
> xOptRepl( xReplacement
, uno::UNO_QUERY_THROW
);
1303 // store it into the subfolder
1304 uno::Sequence
< beans::PropertyValue
> aProps( 3 );
1305 aProps
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
1306 aProps
[0].Value
<<= rMediaType
;
1307 aProps
[1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" ) );
1308 aProps
[1].Value
<<= (sal_Bool
)sal_True
;
1309 aProps
[2].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
1310 aProps
[2].Value
<<= (sal_Bool
)sal_True
;
1312 if ( xReplacement
->hasByName( rObjectName
) )
1313 xReplacement
->removeElement( rObjectName
);
1315 xOptRepl
->insertStreamElementDirect( rObjectName
, rStream
, aProps
);
1317 catch( uno::Exception
& )
1326 sal_Bool
EmbeddedObjectContainer::RemoveGraphicStream( const ::rtl::OUString
& rObjectName
)
1328 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveGraphicStream" );
1332 uno::Reference
< embed::XStorage
> xReplacements
= pImpl
->GetReplacements();
1333 xReplacements
->removeElement( rObjectName
);
1335 catch( uno::Exception
& )
1343 void InsertStreamIntoPicturesStorage_Impl( const uno::Reference
< embed::XStorage
>& xDocStor
,
1344 const uno::Reference
< io::XInputStream
>& xInStream
,
1345 const ::rtl::OUString
& aStreamName
)
1347 OSL_ENSURE( aStreamName
.getLength() && xInStream
.is() && xDocStor
.is(), "Misuse of the method!\n" );
1351 uno::Reference
< embed::XStorage
> xPictures
= xDocStor
->openStorageElement(
1352 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pictures" ) ),
1353 embed::ElementModes::READWRITE
);
1354 uno::Reference
< io::XStream
> xObjReplStr
= xPictures
->openStreamElement(
1356 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
1357 uno::Reference
< io::XOutputStream
> xOutStream(
1358 xObjReplStr
->getInputStream(), uno::UNO_QUERY_THROW
);
1360 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream
, xOutStream
);
1361 xOutStream
->closeOutput();
1363 uno::Reference
< embed::XTransactedObject
> xTransact( xPictures
, uno::UNO_QUERY
);
1364 if ( xTransact
.is() )
1365 xTransact
->commit();
1367 catch( uno::Exception
& )
1369 OSL_ENSURE( sal_False
, "The pictures storage is not available!\n" );
1374 // -----------------------------------------------------------------------------
1375 sal_Bool
EmbeddedObjectContainer::StoreAsChildren(sal_Bool _bOasisFormat
,sal_Bool _bCreateEmbedded
,const uno::Reference
< embed::XStorage
>& _xStorage
)
1377 sal_Bool bResult
= sal_False
;
1380 comphelper::EmbeddedObjectContainer
aCnt( _xStorage
);
1381 const uno::Sequence
< ::rtl::OUString
> aNames
= GetObjectNames();
1382 const ::rtl::OUString
* pIter
= aNames
.getConstArray();
1383 const ::rtl::OUString
* pEnd
= pIter
+ aNames
.getLength();
1384 for(;pIter
!= pEnd
;++pIter
)
1386 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( *pIter
);
1387 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
1390 sal_Bool bSwitchBackToLoaded
= sal_False
;
1391 uno::Reference
< embed::XLinkageSupport
> xLink( xObj
, uno::UNO_QUERY
);
1393 uno::Reference
< io::XInputStream
> xStream
;
1394 ::rtl::OUString aMediaType
;
1396 sal_Int32 nCurState
= xObj
->getCurrentState();
1397 if ( nCurState
== embed::EmbedStates::LOADED
|| nCurState
== embed::EmbedStates::RUNNING
)
1399 // means that the object is not active
1400 // copy replacement image from old to new container
1401 xStream
= GetGraphicStream( xObj
, &aMediaType
);
1404 if ( !xStream
.is() )
1406 // the image must be regenerated
1407 // TODO/LATER: another aspect could be used
1408 if ( xObj
->getCurrentState() == embed::EmbedStates::LOADED
)
1409 bSwitchBackToLoaded
= sal_True
;
1411 xStream
= GetGraphicReplacementStream(
1412 embed::Aspects::MSOLE_CONTENT
,
1417 if ( _bOasisFormat
|| (xLink
.is() && xLink
->isLink()) )
1421 if ( _bOasisFormat
)
1423 // if it is an embedded object or the optimized inserting fails the normal inserting should be done
1424 if ( _bCreateEmbedded
1425 || !aCnt
.InsertGraphicStreamDirectly( xStream
, *pIter
, aMediaType
) )
1426 aCnt
.InsertGraphicStream( xStream
, *pIter
, aMediaType
);
1430 // it is a linked object exported into SO7 format
1431 InsertStreamIntoPicturesStorage_Impl( _xStorage
, xStream
, *pIter
);
1436 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1437 if ( xPersist
.is() )
1439 uno::Sequence
< beans::PropertyValue
> aArgs( _bOasisFormat
? 2 : 3 );
1440 aArgs
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StoreVisualReplacement" ) );
1441 aArgs
[0].Value
<<= (sal_Bool
)( !_bOasisFormat
);
1443 // if it is an embedded object or the optimized inserting fails the normal inserting should be done
1444 aArgs
[1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanTryOptimization" ) );
1445 aArgs
[1].Value
<<= !_bCreateEmbedded
;
1446 if ( !_bOasisFormat
)
1448 // if object has no cached replacement it will use this one
1449 aArgs
[2].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VisualReplacement" ) );
1450 aArgs
[2].Value
<<= xStream
;
1453 xPersist
->storeAsEntry( _xStorage
,
1454 xPersist
->getEntryName(),
1455 uno::Sequence
< beans::PropertyValue
>(),
1459 if ( bSwitchBackToLoaded
)
1460 // switch back to loaded state; that way we have a minimum cache confusion
1461 xObj
->changeState( embed::EmbedStates::LOADED
);
1465 bResult
= aCnt
.CommitImageSubStorage();
1468 catch ( uno::Exception
& )
1470 // TODO/LATER: error handling
1471 bResult
= sal_False
;
1474 // the old SO6 format does not store graphical replacements
1475 if ( !_bOasisFormat
&& bResult
)
1479 // the substorage still can not be locked by the embedded object conteiner
1480 ::rtl::OUString
aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
1481 if ( _xStorage
->hasByName( aObjReplElement
) && _xStorage
->isStorageElement( aObjReplElement
) )
1482 _xStorage
->removeElement( aObjReplElement
);
1484 catch ( uno::Exception
& )
1486 // TODO/LATER: error handling;
1487 bResult
= sal_False
;
1492 // -----------------------------------------------------------------------------
1493 sal_Bool
EmbeddedObjectContainer::StoreChildren(sal_Bool _bOasisFormat
,sal_Bool _bObjectsOnly
)
1495 sal_Bool bResult
= sal_True
;
1496 const uno::Sequence
< ::rtl::OUString
> aNames
= GetObjectNames();
1497 const ::rtl::OUString
* pIter
= aNames
.getConstArray();
1498 const ::rtl::OUString
* pEnd
= pIter
+ aNames
.getLength();
1499 for(;pIter
!= pEnd
;++pIter
)
1501 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( *pIter
);
1502 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
1505 sal_Int32 nCurState
= xObj
->getCurrentState();
1506 if ( _bOasisFormat
&& nCurState
!= embed::EmbedStates::LOADED
&& nCurState
!= embed::EmbedStates::RUNNING
)
1508 // means that the object is active
1509 // the image must be regenerated
1510 ::rtl::OUString aMediaType
;
1512 // TODO/LATER: another aspect could be used
1513 uno::Reference
< io::XInputStream
> xStream
=
1514 GetGraphicReplacementStream(
1515 embed::Aspects::MSOLE_CONTENT
,
1520 if ( !InsertGraphicStreamDirectly( xStream
, *pIter
, aMediaType
) )
1521 InsertGraphicStream( xStream
, *pIter
, aMediaType
);
1525 // TODO/LATER: currently the object by default does not cache replacement image
1526 // that means that if somebody loads SO7 document and store its objects using
1527 // this method the images might be lost.
1528 // Currently this method is only used on storing to alien formats, that means
1529 // that SO7 documents storing does not use it, and all other filters are
1530 // based on OASIS format. But if it changes the method must be fixed. The fix
1531 // must be done only on demand since it can affect performance.
1533 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1534 if ( xPersist
.is() )
1538 //TODO/LATER: only storing if changed!
1539 xPersist
->storeOwn();
1541 catch( uno::Exception
& )
1543 // TODO/LATER: error handling
1544 bResult
= sal_False
;
1549 if ( !_bOasisFormat
&& !_bObjectsOnly
)
1551 // copy replacement images for linked objects
1554 uno::Reference
< embed::XLinkageSupport
> xLink( xObj
, uno::UNO_QUERY
);
1555 if ( xLink
.is() && xLink
->isLink() )
1557 ::rtl::OUString aMediaType
;
1558 uno::Reference
< io::XInputStream
> xInStream
= GetGraphicStream( xObj
, &aMediaType
);
1559 if ( xInStream
.is() )
1560 InsertStreamIntoPicturesStorage_Impl( pImpl
->mxStorage
, xInStream
, *pIter
);
1563 catch( uno::Exception
& )
1570 if ( bResult
&& _bOasisFormat
)
1571 bResult
= CommitImageSubStorage();
1573 if ( bResult
&& !_bObjectsOnly
)
1577 ReleaseImageSubStorage();
1578 ::rtl::OUString
aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
1579 if ( !_bOasisFormat
&& pImpl
->mxStorage
->hasByName( aObjReplElement
) && pImpl
->mxStorage
->isStorageElement( aObjReplElement
) )
1580 pImpl
->mxStorage
->removeElement( aObjReplElement
);
1582 catch( uno::Exception
& )
1584 // TODO/LATER: error handling
1585 bResult
= sal_False
;
1590 // -----------------------------------------------------------------------------
1591 uno::Reference
< io::XInputStream
> EmbeddedObjectContainer::GetGraphicReplacementStream(
1592 sal_Int64 nViewAspect
,
1593 const uno::Reference
< embed::XEmbeddedObject
>& xObj
,
1594 ::rtl::OUString
* pMediaType
)
1596 uno::Reference
< io::XInputStream
> xInStream
;
1601 // retrieving of the visual representation can switch object to running state
1602 embed::VisualRepresentation aRep
= xObj
->getPreferredVisualRepresentation( nViewAspect
);
1604 *pMediaType
= aRep
.Flavor
.MimeType
;
1606 uno::Sequence
< sal_Int8
> aSeq
;
1608 xInStream
= new ::comphelper::SequenceInputStream( aSeq
);
1610 catch ( uno::Exception
& )
1617 // -----------------------------------------------------------------------------
1618 sal_Bool
EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference
< embed::XStorage
>& _xStorage
,bool _bClearModifedFlag
)
1620 sal_Bool bError
= sal_False
;
1621 const uno::Sequence
< ::rtl::OUString
> aNames
= GetObjectNames();
1622 const ::rtl::OUString
* pIter
= aNames
.getConstArray();
1623 const ::rtl::OUString
* pEnd
= pIter
+ aNames
.getLength();
1624 for(;pIter
!= pEnd
;++pIter
)
1626 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( *pIter
);
1627 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
1630 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1631 if ( xPersist
.is() )
1635 xPersist
->setPersistentEntry( _xStorage
,
1637 embed::EntryInitModes::NO_INIT
,
1638 uno::Sequence
< beans::PropertyValue
>(),
1639 uno::Sequence
< beans::PropertyValue
>() );
1642 catch( uno::Exception
& )
1644 // TODO/LATER: error handling
1649 if ( _bClearModifedFlag
)
1651 // if this method is used as part of SaveCompleted the object must stay unmodified after execution
1654 uno::Reference
< util::XModifiable
> xModif( xObj
->getComponent(), uno::UNO_QUERY_THROW
);
1655 if ( xModif
->isModified() )
1656 xModif
->setModified( sal_False
);
1658 catch( uno::Exception
& )