1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 #include <com/sun/star/container/XChild.hpp>
31 #include <com/sun/star/container/XNameAccess.hpp>
32 #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
33 #include <com/sun/star/embed/XLinkCreator.hpp>
34 #include <com/sun/star/embed/XEmbedPersist.hpp>
35 #include <com/sun/star/embed/XLinkageSupport.hpp>
36 #include <com/sun/star/embed/XTransactedObject.hpp>
37 #include <com/sun/star/embed/XOptimizedStorage.hpp>
38 #include <com/sun/star/embed/EntryInitModes.hpp>
39 #include <com/sun/star/util/XCloseable.hpp>
40 #include <com/sun/star/util/XModifiable.hpp>
41 #include <com/sun/star/embed/EmbedStates.hpp>
42 #include <com/sun/star/datatransfer/XTransferable.hpp>
43 #include <com/sun/star/beans/XPropertySetInfo.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/embed/Aspects.hpp>
46 #include <com/sun/star/embed/EmbedMisc.hpp>
48 #include <comphelper/seqstream.hxx>
49 #include <comphelper/processfactory.hxx>
50 #include <comphelper/storagehelper.hxx>
51 #include <comphelper/embeddedobjectcontainer.hxx>
52 #include <comphelper/sequence.hxx>
53 #include <cppuhelper/weakref.hxx>
57 #include <rtl/logfile.hxx>
59 using namespace ::com::sun::star
;
64 struct hashObjectName_Impl
66 size_t operator()(const ::rtl::OUString Str
) const
68 return (size_t)Str
.hashCode();
72 struct eqObjectName_Impl
74 sal_Bool
operator()(const ::rtl::OUString Str1
, const ::rtl::OUString Str2
) const
76 return ( Str1
== Str2
);
83 ::com::sun::star::uno::Reference
< com::sun::star::embed::XEmbeddedObject
>,
87 EmbeddedObjectContainerNameMap
;
91 // TODO/LATER: remove objects from temp. Container storage when object is disposed
92 EmbeddedObjectContainerNameMap maObjectContainer
;
93 uno::Reference
< embed::XStorage
> mxStorage
;
94 EmbeddedObjectContainer
* mpTempObjectContainer
;
95 uno::Reference
< embed::XStorage
> mxImageStorage
;
96 uno::WeakReference
< uno::XInterface
> m_xModel
;
97 //EmbeddedObjectContainerNameMap maTempObjectContainer;
98 //uno::Reference < embed::XStorage > mxTempStorage;
99 sal_Bool bOwnsStorage
;
101 const uno::Reference
< embed::XStorage
>& GetReplacements();
104 const uno::Reference
< embed::XStorage
>& EmbedImpl::GetReplacements()
106 if ( !mxImageStorage
.is() )
110 mxImageStorage
= mxStorage
->openStorageElement(
111 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READWRITE
);
113 catch ( uno::Exception
& )
115 mxImageStorage
= mxStorage
->openStorageElement(
116 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READ
);
120 if ( !mxImageStorage
.is() )
121 throw io::IOException();
123 return mxImageStorage
;
126 EmbeddedObjectContainer::EmbeddedObjectContainer()
128 pImpl
= new EmbedImpl
;
129 pImpl
->mxStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
130 pImpl
->bOwnsStorage
= sal_True
;
131 pImpl
->mpTempObjectContainer
= 0;
134 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference
< embed::XStorage
>& rStor
)
136 pImpl
= new EmbedImpl
;
137 pImpl
->mxStorage
= rStor
;
138 pImpl
->bOwnsStorage
= sal_False
;
139 pImpl
->mpTempObjectContainer
= 0;
142 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference
< embed::XStorage
>& rStor
, const uno::Reference
< uno::XInterface
>& xModel
)
144 pImpl
= new EmbedImpl
;
145 pImpl
->mxStorage
= rStor
;
146 pImpl
->bOwnsStorage
= sal_False
;
147 pImpl
->mpTempObjectContainer
= 0;
148 pImpl
->m_xModel
= xModel
;
151 void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference
< embed::XStorage
>& rStor
)
153 ReleaseImageSubStorage();
155 if ( pImpl
->bOwnsStorage
)
156 pImpl
->mxStorage
->dispose();
158 pImpl
->mxStorage
= rStor
;
159 pImpl
->bOwnsStorage
= sal_False
;
162 sal_Bool
EmbeddedObjectContainer::CommitImageSubStorage()
164 if ( pImpl
->mxImageStorage
.is() )
168 sal_Bool bReadOnlyMode
= sal_True
;
169 uno::Reference
< beans::XPropertySet
> xSet(pImpl
->mxImageStorage
,uno::UNO_QUERY
);
172 // get the open mode from the parent storage
174 uno::Any aAny
= xSet
->getPropertyValue( ::rtl::OUString::createFromAscii("OpenMode") );
175 if ( aAny
>>= nMode
)
176 bReadOnlyMode
= !(nMode
& embed::ElementModes::WRITE
);
177 } // if ( xSet.is() )
178 if ( !bReadOnlyMode
)
180 uno::Reference
< embed::XTransactedObject
> xTransact( pImpl
->mxImageStorage
, uno::UNO_QUERY_THROW
);
184 catch( uno::Exception
& )
193 void EmbeddedObjectContainer::ReleaseImageSubStorage()
195 CommitImageSubStorage();
197 if ( pImpl
->mxImageStorage
.is() )
201 pImpl
->mxImageStorage
->dispose();
202 pImpl
->mxImageStorage
= uno::Reference
< embed::XStorage
>();
204 catch( uno::Exception
& )
206 OSL_ASSERT( "Problems releasing image substorage!\n" );
211 EmbeddedObjectContainer::~EmbeddedObjectContainer()
213 ReleaseImageSubStorage();
215 if ( pImpl
->bOwnsStorage
)
216 pImpl
->mxStorage
->dispose();
218 delete pImpl
->mpTempObjectContainer
;
222 void EmbeddedObjectContainer::CloseEmbeddedObjects()
224 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
225 while ( aIt
!= pImpl
->maObjectContainer
.end() )
227 uno::Reference
< util::XCloseable
> xClose( (*aIt
).second
, uno::UNO_QUERY
);
232 xClose
->close( sal_True
);
234 catch ( uno::Exception
& )
243 ::rtl::OUString
EmbeddedObjectContainer::CreateUniqueObjectName()
245 ::rtl::OUString aPersistName
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
246 ::rtl::OUString aStr
;
251 aStr
+= ::rtl::OUString::valueOf( i
++ );
253 while( HasEmbeddedObject( aStr
) );
254 // TODO/LATER: should we consider deleted objects?
259 uno::Sequence
< ::rtl::OUString
> EmbeddedObjectContainer::GetObjectNames()
261 uno::Sequence
< ::rtl::OUString
> aSeq( pImpl
->maObjectContainer
.size() );
262 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
264 while ( aIt
!= pImpl
->maObjectContainer
.end() )
265 aSeq
[nIdx
++] = (*aIt
++).first
;
269 sal_Bool
EmbeddedObjectContainer::HasEmbeddedObjects()
271 return pImpl
->maObjectContainer
.size() != 0;
274 sal_Bool
EmbeddedObjectContainer::HasEmbeddedObject( const ::rtl::OUString
& rName
)
276 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
277 if ( aIt
== pImpl
->maObjectContainer
.end() )
279 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
280 return xAccess
->hasByName(rName
);
286 sal_Bool
EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
)
288 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
289 while ( aIt
!= pImpl
->maObjectContainer
.end() )
291 if ( (*aIt
).second
== xObj
)
300 sal_Bool
EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const ::rtl::OUString
& rName
)
302 // allows to detect whether the object was already instantiated
303 // currently the filter instantiate it on loading, so this method allows
304 // to avoid objects pointing to the same persistence
305 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
306 return ( aIt
!= pImpl
->maObjectContainer
.end() );
309 ::rtl::OUString
EmbeddedObjectContainer::GetEmbeddedObjectName( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XEmbeddedObject
>& xObj
)
311 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
312 while ( aIt
!= pImpl
->maObjectContainer
.end() )
314 if ( (*aIt
).second
== xObj
)
320 OSL_ENSURE( 0, "Unknown object!" );
321 return ::rtl::OUString();
324 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::GetEmbeddedObject( const ::rtl::OUString
& rName
)
326 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetEmbeddedObject" );
328 OSL_ENSURE( rName
.getLength(), "Empty object name!");
330 uno::Reference
< embed::XEmbeddedObject
> xObj
;
331 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
333 #if OSL_DEBUG_LEVEL > 1
334 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
335 uno::Sequence
< ::rtl::OUString
> aSeq
= xAccess
->getElementNames();
336 const ::rtl::OUString
* pIter
= aSeq
.getConstArray();
337 const ::rtl::OUString
* pEnd
= pIter
+ aSeq
.getLength();
338 for(;pIter
!= pEnd
;++pIter
)
342 OSL_ENSURE( aIt
!= pImpl
->maObjectContainer
.end() || xAccess
->hasByName(rName
), "Could not return object!" );
345 // check if object was already created
346 if ( aIt
!= pImpl
->maObjectContainer
.end() )
347 xObj
= (*aIt
).second
;
349 xObj
= Get_Impl( rName
, uno::Reference
< embed::XEmbeddedObject
>() );
354 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::Get_Impl( const ::rtl::OUString
& rName
, const uno::Reference
< embed::XEmbeddedObject
>& xCopy
)
356 uno::Reference
< embed::XEmbeddedObject
> xObj
;
359 // create the object from the storage
360 uno::Reference
< beans::XPropertySet
> xSet( pImpl
->mxStorage
, uno::UNO_QUERY
);
361 sal_Bool bReadOnlyMode
= sal_True
;
364 // get the open mode from the parent storage
366 uno::Any aAny
= xSet
->getPropertyValue( ::rtl::OUString::createFromAscii("OpenMode") );
367 if ( aAny
>>= nMode
)
368 bReadOnlyMode
= !(nMode
& embed::ElementModes::WRITE
);
371 // object was not added until now - should happen only by calling this method from "inside"
372 //TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call)
373 uno::Reference
< embed::XEmbedObjectCreator
> xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
374 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY
);
375 uno::Sequence
< beans::PropertyValue
> aObjDescr( xCopy
.is() ? 2 : 1 );
376 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
377 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
380 aObjDescr
[1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CloneFrom" ) );
381 aObjDescr
[1].Value
<<= xCopy
;
384 uno::Sequence
< beans::PropertyValue
> aMediaDescr( 1 );
385 aMediaDescr
[0].Name
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly"));
386 aMediaDescr
[0].Value
<<= bReadOnlyMode
;
387 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceInitFromEntry(
388 pImpl
->mxStorage
, rName
,
389 aMediaDescr
, aObjDescr
), uno::UNO_QUERY
);
391 // insert object into my list
392 AddEmbeddedObject( xObj
, rName
);
394 catch ( uno::Exception
& )
401 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence
< sal_Int8
>& rClassId
,
402 const uno::Sequence
< beans::PropertyValue
>& rArgs
, ::rtl::OUString
& rNewName
)
404 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CreateEmbeddedObject" );
406 if ( !rNewName
.getLength() )
407 rNewName
= CreateUniqueObjectName();
409 OSL_ENSURE( !HasEmbeddedObject(rNewName
), "Object to create already exists!");
411 // create object from classid by inserting it into storage
412 uno::Reference
< embed::XEmbeddedObject
> xObj
;
415 uno::Reference
< embed::XEmbedObjectCreator
> xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
416 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY
);
418 uno::Sequence
< beans::PropertyValue
> aObjDescr( rArgs
.getLength() + 1 );
419 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
420 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
421 ::std::copy( rArgs
.getConstArray(), rArgs
.getConstArray() + rArgs
.getLength(), aObjDescr
.getArray() + 1 );
422 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceInitNew(
423 rClassId
, ::rtl::OUString(), pImpl
->mxStorage
, rNewName
,
424 aObjDescr
), uno::UNO_QUERY
);
426 AddEmbeddedObject( xObj
, rNewName
);
428 OSL_ENSURE( !xObj
.is() || xObj
->getCurrentState() != embed::EmbedStates::LOADED
,
429 "A freshly create object should be running always!\n" );
431 catch ( uno::Exception
& )
438 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence
< sal_Int8
>& rClassId
, ::rtl::OUString
& rNewName
)
440 return CreateEmbeddedObject( rClassId
, uno::Sequence
< beans::PropertyValue
>(), rNewName
);
443 void EmbeddedObjectContainer::AddEmbeddedObject( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XEmbeddedObject
>& xObj
, const ::rtl::OUString
& rName
)
445 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::AddEmbeddedObject" );
447 #if OSL_DEBUG_LEVEL > 1
448 OSL_ENSURE( rName
.getLength(), "Added object doesn't have a name!");
449 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
450 uno::Reference
< embed::XEmbedPersist
> xEmb( xObj
, uno::UNO_QUERY
);
451 uno::Reference
< embed::XLinkageSupport
> xLink( xEmb
, uno::UNO_QUERY
);
452 // if the object has a persistance and the object is not a link than it must have persistence entry in the storage
453 OSL_ENSURE( !( xEmb
.is() && ( !xLink
.is() || !xLink
->isLink() ) ) || xAccess
->hasByName(rName
),
454 "Added element not in storage!" );
457 // remember object - it needs to be in storage already
458 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
459 OSL_ENSURE( aIt
== pImpl
->maObjectContainer
.end(), "Element already inserted!" );
460 pImpl
->maObjectContainer
[ rName
] = xObj
;
461 uno::Reference
< container::XChild
> xChild( xObj
, uno::UNO_QUERY
);
462 if ( xChild
.is() && xChild
->getParent() != pImpl
->m_xModel
.get() )
463 xChild
->setParent( pImpl
->m_xModel
.get() );
465 // look for object in temorary container
466 if ( pImpl
->mpTempObjectContainer
)
468 aIt
= pImpl
->mpTempObjectContainer
->pImpl
->maObjectContainer
.begin();
469 while ( aIt
!= pImpl
->mpTempObjectContainer
->pImpl
->maObjectContainer
.end() )
471 if ( (*aIt
).second
== xObj
)
473 // copy replacement image from temporary container (if there is any)
474 ::rtl::OUString aTempName
= (*aIt
).first
;
475 ::rtl::OUString aMediaType
;
476 uno::Reference
< io::XInputStream
> xStream
= pImpl
->mpTempObjectContainer
->GetGraphicStream( xObj
, &aMediaType
);
479 InsertGraphicStream( xStream
, rName
, aMediaType
);
481 pImpl
->mpTempObjectContainer
->RemoveGraphicStream( aTempName
);
484 // remove object from storage of temporary container
485 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
490 pImpl
->mpTempObjectContainer
->pImpl
->mxStorage
->removeElement( aTempName
);
492 catch ( uno::Exception
& )
497 // temp. container needs to forget the object
498 pImpl
->mpTempObjectContainer
->pImpl
->maObjectContainer
.erase( aIt
);
507 sal_Bool
EmbeddedObjectContainer::StoreEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
, ::rtl::OUString
& rName
, sal_Bool bCopy
)
509 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::StoreEmbeddedObject" );
511 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
512 if ( !rName
.getLength() )
513 rName
= CreateUniqueObjectName();
515 #if OSL_DEBUG_LEVEL > 1
516 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
517 OSL_ENSURE( !xPersist
.is() || !xAccess
->hasByName(rName
), "Inserting element already present in storage!" );
518 OSL_ENSURE( xPersist
.is() || xObj
->getCurrentState() == embed::EmbedStates::RUNNING
, "Non persistent object inserted!");
521 // insert objects' storage into the container storage (if object has one)
526 uno::Sequence
< beans::PropertyValue
> aSeq
;
528 xPersist
->storeToEntry( pImpl
->mxStorage
, rName
, aSeq
, aSeq
);
531 //TODO/LATER: possible optimisation, don't store immediately
532 //xPersist->setPersistentEntry( pImpl->mxStorage, rName, embed::EntryInitModes::ENTRY_NO_INIT, aSeq, aSeq );
533 xPersist
->storeAsEntry( pImpl
->mxStorage
, rName
, aSeq
, aSeq
);
534 xPersist
->saveCompleted( sal_True
);
538 catch ( uno::Exception
& )
540 // TODO/LATER: better error recovery should keep storage intact
547 sal_Bool
EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
, ::rtl::OUString
& rName
)
549 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( Object )" );
550 // store it into the container storage
551 if ( StoreEmbeddedObject( xObj
, rName
, sal_False
) )
554 AddEmbeddedObject( xObj
, rName
);
561 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference
< io::XInputStream
>& xStm
, ::rtl::OUString
& rNewName
)
563 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( InputStream )" );
565 if ( !rNewName
.getLength() )
566 rNewName
= CreateUniqueObjectName();
568 // store it into the container storage
569 sal_Bool bIsStorage
= sal_False
;
572 // first try storage persistence
573 uno::Reference
< embed::XStorage
> xStore
= ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm
);
575 // storage was created from stream successfully
576 bIsStorage
= sal_True
;
578 uno::Reference
< embed::XStorage
> xNewStore
= pImpl
->mxStorage
->openStorageElement( rNewName
, embed::ElementModes::READWRITE
);
579 xStore
->copyToStorage( xNewStore
);
581 catch ( uno::Exception
& )
584 // it is storage persistence, but opening of new substorage or copying to it failed
585 return uno::Reference
< embed::XEmbeddedObject
>();
587 // stream didn't contain a storage, now try stream persistence
590 uno::Reference
< io::XStream
> xNewStream
= pImpl
->mxStorage
->openStreamElement( rNewName
, embed::ElementModes::READWRITE
);
591 ::comphelper::OStorageHelper::CopyInputToOutput( xStm
, xNewStream
->getOutputStream() );
593 // No mediatype is provided so the default for OLE objects value is used
594 // it is correct so for now, but what if somebody introduces a new stream based embedded object?
595 // Probably introducing of such an object must be restricted ( a storage must be used! ).
596 uno::Reference
< beans::XPropertySet
> xProps( xNewStream
, uno::UNO_QUERY_THROW
);
597 xProps
->setPropertyValue(
598 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
599 uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) ) ) );
601 catch ( uno::Exception
& )
603 // complete disaster!
604 return uno::Reference
< embed::XEmbeddedObject
>();
608 // stream was copied into the container storage in either way, now try to open something form it
609 uno::Reference
< embed::XEmbeddedObject
> xRet
= GetEmbeddedObject( rNewName
);
613 // no object could be created, so withdraw insertion
614 pImpl
->mxStorage
->removeElement( rNewName
);
616 catch ( uno::Exception
& )
623 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::InsertEmbeddedObject( const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& aMedium
, ::rtl::OUString
& rNewName
)
625 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( MediaDescriptor )" );
627 if ( !rNewName
.getLength() )
628 rNewName
= CreateUniqueObjectName();
630 uno::Reference
< embed::XEmbeddedObject
> xObj
;
633 uno::Reference
< embed::XEmbedObjectCreator
> xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
634 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY
);
635 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
636 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
637 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
638 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceInitFromMediaDescriptor(
639 pImpl
->mxStorage
, rNewName
, aMedium
, aObjDescr
), uno::UNO_QUERY
);
640 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
642 OSL_ENSURE( !xObj
.is() || xObj
->getCurrentState() != embed::EmbedStates::LOADED
,
643 "A freshly create object should be running always!\n" );
645 // possible optimization: store later!
647 xPersist
->storeOwn();
649 AddEmbeddedObject( xObj
, rNewName
);
651 catch ( uno::Exception
& )
658 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::InsertEmbeddedLink( const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& aMedium
, ::rtl::OUString
& rNewName
)
660 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedLink" );
662 if ( !rNewName
.getLength() )
663 rNewName
= CreateUniqueObjectName();
665 uno::Reference
< embed::XEmbeddedObject
> xObj
;
668 uno::Reference
< embed::XLinkCreator
> xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
669 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY
);
670 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
671 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
672 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
673 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceLink(
674 pImpl
->mxStorage
, rNewName
, aMedium
, aObjDescr
), uno::UNO_QUERY
);
676 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
678 OSL_ENSURE( !xObj
.is() || xObj
->getCurrentState() != embed::EmbedStates::LOADED
,
679 "A freshly create object should be running always!\n" );
681 // possible optimization: store later!
683 xPersist
->storeOwn();
685 AddEmbeddedObject( xObj
, rNewName
);
687 catch ( uno::Exception
& )
694 sal_Bool
EmbeddedObjectContainer::TryToCopyGraphReplacement( EmbeddedObjectContainer
& rSrc
,
695 const ::rtl::OUString
& aOrigName
,
696 const ::rtl::OUString
& aTargetName
)
698 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::TryToCopyGraphReplacement" );
700 sal_Bool bResult
= sal_False
;
702 if ( ( &rSrc
!= this || !aOrigName
.equals( aTargetName
) ) && aOrigName
.getLength() && aTargetName
.getLength() )
704 ::rtl::OUString aMediaType
;
705 uno::Reference
< io::XInputStream
> xGrStream
= rSrc
.GetGraphicStream( aOrigName
, &aMediaType
);
706 if ( xGrStream
.is() )
707 bResult
= InsertGraphicStream( xGrStream
, aTargetName
, aMediaType
);
713 sal_Bool
EmbeddedObjectContainer::CopyEmbeddedObject( EmbeddedObjectContainer
& rSrc
, const uno::Reference
< embed::XEmbeddedObject
>& xObj
, ::rtl::OUString
& rName
)
715 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyEmbeddedObject" );
717 OSL_ENSURE( sal_False
,
718 "This method is depricated! Use EmbeddedObjectContainer::CopyAndGetEmbeddedObject() to copy object!\n" );
720 // get the object name before(!) it is assigned to a new storage
721 ::rtl::OUString aOrigName
;
722 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
724 aOrigName
= xPersist
->getEntryName();
726 if ( !rName
.getLength() )
727 rName
= CreateUniqueObjectName();
729 if ( StoreEmbeddedObject( xObj
, rName
, sal_True
) )
731 TryToCopyGraphReplacement( rSrc
, aOrigName
, rName
);
738 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::CopyAndGetEmbeddedObject( EmbeddedObjectContainer
& rSrc
, const uno::Reference
< embed::XEmbeddedObject
>& xObj
, ::rtl::OUString
& rName
)
740 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyAndGetEmbeddedObject" );
742 uno::Reference
< embed::XEmbeddedObject
> xResult
;
744 // TODO/LATER: For now only objects that implement XEmbedPersist have a replacement image, it might change in future
745 // do an incompatible change so that object name is provided in all the move and copy methods
746 ::rtl::OUString aOrigName
;
749 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY_THROW
);
750 aOrigName
= xPersist
->getEntryName();
752 catch( uno::Exception
& )
755 if ( !rName
.getLength() )
756 rName
= CreateUniqueObjectName();
758 // objects without persistance are not really stored by the method
759 if ( xObj
.is() && StoreEmbeddedObject( xObj
, rName
, sal_True
) )
761 xResult
= Get_Impl( rName
, xObj
);
764 // this is a case when object has no real persistence
765 // in such cases a new object should be explicitly created and initialized with the data of the old one
768 uno::Reference
< embed::XLinkageSupport
> xOrigLinkage( xObj
, uno::UNO_QUERY
);
769 if ( xOrigLinkage
.is() && xOrigLinkage
->isLink() )
771 // this is a OOo link, it has no persistence
772 ::rtl::OUString aURL
= xOrigLinkage
->getLinkURL();
773 if ( !aURL
.getLength() )
774 throw uno::RuntimeException();
776 // create new linked object from the URL the link is based on
777 uno::Reference
< embed::XLinkCreator
> xCreator(
778 ::comphelper::getProcessServiceFactory()->createInstance(
779 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
780 uno::UNO_QUERY_THROW
);
782 uno::Sequence
< beans::PropertyValue
> aMediaDescr( 1 );
783 aMediaDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
784 aMediaDescr
[0].Value
<<= aURL
;
785 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
786 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
787 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
788 xResult
= uno::Reference
< embed::XEmbeddedObject
>(
789 xCreator
->createInstanceLink(
794 uno::UNO_QUERY_THROW
);
798 // the component is required for copying of this object
799 if ( xObj
->getCurrentState() == embed::EmbedStates::LOADED
)
800 xObj
->changeState( embed::EmbedStates::RUNNING
);
802 // this must be an object based on properties, otherwise we can not copy it currently
803 uno::Reference
< beans::XPropertySet
> xOrigProps( xObj
->getComponent(), uno::UNO_QUERY_THROW
);
805 // use object class ID to create a new one and tranfer all the properties
806 uno::Reference
< embed::XEmbedObjectCreator
> xCreator(
807 ::comphelper::getProcessServiceFactory()->createInstance(
808 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
809 uno::UNO_QUERY_THROW
);
811 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
812 aObjDescr
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
813 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
814 xResult
= uno::Reference
< embed::XEmbeddedObject
>(
815 xCreator
->createInstanceInitNew(
817 xObj
->getClassName(),
821 uno::UNO_QUERY_THROW
);
823 if ( xResult
->getCurrentState() == embed::EmbedStates::LOADED
)
824 xResult
->changeState( embed::EmbedStates::RUNNING
);
826 uno::Reference
< beans::XPropertySet
> xTargetProps( xResult
->getComponent(), uno::UNO_QUERY_THROW
);
828 // copy all the properties from xOrigProps to xTargetProps
829 uno::Reference
< beans::XPropertySetInfo
> xOrigInfo
= xOrigProps
->getPropertySetInfo();
830 if ( !xOrigInfo
.is() )
831 throw uno::RuntimeException();
833 uno::Sequence
< beans::Property
> aPropertiesList
= xOrigInfo
->getProperties();
834 for ( sal_Int32 nInd
= 0; nInd
< aPropertiesList
.getLength(); nInd
++ )
838 xTargetProps
->setPropertyValue(
839 aPropertiesList
[nInd
].Name
,
840 xOrigProps
->getPropertyValue( aPropertiesList
[nInd
].Name
) );
842 catch( beans::PropertyVetoException
& )
844 // impossibility to copy readonly property is not treated as an error for now
845 // but the assertion is helpful to detect such scenarios and review them
846 OSL_ENSURE( sal_False
, "Could not copy readonly property!\n" );
852 AddEmbeddedObject( xResult
, rName
);
854 catch( uno::Exception
& )
860 xResult
->close( sal_True
);
862 catch( uno::Exception
& )
864 xResult
= uno::Reference
< embed::XEmbeddedObject
>();
870 OSL_ENSURE( xResult
.is(), "Can not copy embedded object that has no persistance!\n" );
874 // the object is successfully copied, try to copy graphical replacement
875 if ( aOrigName
.getLength() )
876 TryToCopyGraphReplacement( rSrc
, aOrigName
, rName
);
878 // the object might need the size to be set
881 if ( xResult
->getStatus( embed::Aspects::MSOLE_CONTENT
) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD
)
882 xResult
->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT
,
883 xObj
->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
) );
885 catch( uno::Exception
& )
892 sal_Bool
EmbeddedObjectContainer::MoveEmbeddedObject( EmbeddedObjectContainer
& rSrc
, const uno::Reference
< embed::XEmbeddedObject
>& xObj
, ::rtl::OUString
& rName
)
894 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Object )" );
896 // get the object name before(!) it is assigned to a new storage
897 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
898 ::rtl::OUString aName
;
900 aName
= xPersist
->getEntryName();
902 // now move the object to the new container; the returned name is the new persist name in this container
907 bRet
= InsertEmbeddedObject( xObj
, rName
);
909 TryToCopyGraphReplacement( rSrc
, aName
, rName
);
911 catch ( uno::Exception
& e
)
914 OSL_ENSURE( sal_False
, "Failed to insert embedded object into storage!" );
920 // now remove the object from the former container
922 EmbeddedObjectContainerNameMap::iterator aIt
= rSrc
.pImpl
->maObjectContainer
.begin();
923 while ( aIt
!= rSrc
.pImpl
->maObjectContainer
.end() )
925 if ( (*aIt
).second
== xObj
)
927 rSrc
.pImpl
->maObjectContainer
.erase( aIt
);
935 OSL_ENSURE( bRet
, "Object not found for removal!" );
938 // now it's time to remove the storage from the container storage
942 rSrc
.pImpl
->mxStorage
->removeElement( aName
);
944 catch ( uno::Exception
& )
946 OSL_ENSURE( sal_False
, "Failed to remove object from storage!" );
951 // rSrc.RemoveGraphicStream( aName );
957 sal_Bool
EmbeddedObjectContainer::RemoveEmbeddedObject( const ::rtl::OUString
& rName
, sal_Bool bClose
)
959 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Name )" );
961 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( rName
);
963 return RemoveEmbeddedObject( xObj
, bClose
);
968 sal_Bool
EmbeddedObjectContainer::MoveEmbeddedObject( const ::rtl::OUString
& rName
, EmbeddedObjectContainer
& rCnt
)
970 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Name )" );
973 EmbeddedObjectContainerNameMap::iterator aIt2
= rCnt
.pImpl
->maObjectContainer
.find( rName
);
974 OSL_ENSURE( aIt2
== rCnt
.pImpl
->maObjectContainer
.end(), "Object does already exist in target container!" );
976 if ( aIt2
!= rCnt
.pImpl
->maObjectContainer
.end() )
979 uno::Reference
< embed::XEmbeddedObject
> xObj
;
980 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
981 if ( aIt
!= pImpl
->maObjectContainer
.end() )
983 xObj
= (*aIt
).second
;
989 ::rtl::OUString
aName( rName
);
990 rCnt
.InsertEmbeddedObject( xObj
, aName
);
991 pImpl
->maObjectContainer
.erase( aIt
);
992 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
994 pImpl
->mxStorage
->removeElement( rName
);
998 // copy storages; object *must* have persistence!
999 uno::Reference
< embed::XStorage
> xOld
= pImpl
->mxStorage
->openStorageElement( rName
, embed::ElementModes::READ
);
1000 uno::Reference
< embed::XStorage
> xNew
= rCnt
.pImpl
->mxStorage
->openStorageElement( rName
, embed::ElementModes::READWRITE
);
1001 xOld
->copyToStorage( xNew
);
1004 rCnt
.TryToCopyGraphReplacement( *this, rName
, rName
);
1005 // RemoveGraphicStream( rName );
1009 catch ( uno::Exception
& )
1011 OSL_ENSURE(0,"Could not move object!");
1017 OSL_ENSURE(0,"Unknown object!");
1021 sal_Bool
EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
, sal_Bool bClose
)
1023 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Object )" );
1025 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1026 ::rtl::OUString aName
;
1027 if ( xPersist
.is() )
1028 aName
= xPersist
->getEntryName();
1030 #if OSL_DEBUG_LEVEL > 1
1031 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
1032 uno::Reference
< embed::XLinkageSupport
> xLink( xPersist
, uno::UNO_QUERY
);
1033 sal_Bool bIsNotEmbedded
= !xPersist
.is() || xLink
.is() && xLink
->isLink();
1035 // if the object has a persistance and the object is not a link than it must have persistence entry in the storage
1036 OSL_ENSURE( bIsNotEmbedded
|| xAccess
->hasByName(aName
), "Removing element not present in storage!" );
1039 // try to close it if permitted
1042 uno::Reference
< ::util::XCloseable
> xClose( xObj
, uno::UNO_QUERY
);
1045 xClose
->close( sal_True
);
1047 catch ( util::CloseVetoException
& )
1055 // somebody still needs the object, so we must assign a temporary persistence
1058 if ( xPersist
.is() )
1061 //TODO/LATER: needs storage handling! Why not letting the object do it?!
1062 if ( !pImpl->mxTempStorage.is() )
1063 pImpl->mxTempStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
1064 uno::Sequence < beans::PropertyValue > aSeq;
1066 ::rtl::OUString aTmpPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
1067 aTmpPersistName += ::rtl::OUString::valueOf( (sal_Int32) pImpl->maTempObjectContainer.size() );
1069 xPersist->storeAsEntry( pImpl->mxTempStorage, aTmpPersistName, aSeq, aSeq );
1070 xPersist->saveCompleted( sal_True );
1072 pImpl->maTempObjectContainer[ aTmpPersistName ] = uno::Reference < embed::XEmbeddedObject >();
1075 if ( !pImpl
->mpTempObjectContainer
)
1077 pImpl
->mpTempObjectContainer
= new EmbeddedObjectContainer();
1080 // TODO/LATER: in future probably the temporary container will have two storages ( of two formats )
1081 // the media type will be provided with object insertion
1082 ::rtl::OUString aOrigStorMediaType
;
1083 uno::Reference
< beans::XPropertySet
> xStorProps( pImpl
->mxStorage
, uno::UNO_QUERY_THROW
);
1084 static const ::rtl::OUString
s_sMediaType(RTL_CONSTASCII_USTRINGPARAM("MediaType"));
1085 xStorProps
->getPropertyValue( s_sMediaType
) >>= aOrigStorMediaType
;
1087 OSL_ENSURE( aOrigStorMediaType
.getLength(), "No valuable media type in the storage!\n" );
1089 uno::Reference
< beans::XPropertySet
> xTargetStorProps(
1090 pImpl
->mpTempObjectContainer
->pImpl
->mxStorage
,
1091 uno::UNO_QUERY_THROW
);
1092 xTargetStorProps
->setPropertyValue( s_sMediaType
,uno::makeAny( aOrigStorMediaType
) );
1094 catch( uno::Exception
& )
1096 OSL_ENSURE( sal_False
, "Can not set the new media type to a storage!\n" );
1100 ::rtl::OUString aTempName
, aMediaType
;
1101 pImpl
->mpTempObjectContainer
->InsertEmbeddedObject( xObj
, aTempName
);
1103 uno::Reference
< io::XInputStream
> xStream
= GetGraphicStream( xObj
, &aMediaType
);
1105 pImpl
->mpTempObjectContainer
->InsertGraphicStream( xStream
, aTempName
, aMediaType
);
1107 // object is stored, so at least it can be set to loaded state
1108 xObj
->changeState( embed::EmbedStates::LOADED
);
1111 // objects without persistence need to stay in running state if they shall not be closed
1112 xObj
->changeState( embed::EmbedStates::RUNNING
);
1114 catch ( uno::Exception
& )
1120 sal_Bool bFound
= sal_False
;
1121 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
1122 while ( aIt
!= pImpl
->maObjectContainer
.end() )
1124 if ( (*aIt
).second
== xObj
)
1126 pImpl
->maObjectContainer
.erase( aIt
);
1128 uno::Reference
< container::XChild
> xChild( xObj
, uno::UNO_QUERY
);
1130 xChild
->setParent( uno::Reference
< uno::XInterface
>() );
1137 OSL_ENSURE( bFound
, "Object not found for removal!" );
1138 if ( xPersist
.is() )
1140 // remove replacement image (if there is one)
1141 RemoveGraphicStream( aName
);
1143 // now it's time to remove the storage from the container storage
1146 #if OSL_DEBUG_LEVEL > 1
1147 // if the object has a persistance and the object is not a link than it must have persistence entry in storage
1148 OSL_ENSURE( bIsNotEmbedded
|| pImpl
->mxStorage
->hasByName( aName
), "The object has no persistence entry in the storage!" );
1150 if ( xPersist
.is() && pImpl
->mxStorage
->hasByName( aName
) )
1151 pImpl
->mxStorage
->removeElement( aName
);
1153 catch ( uno::Exception
& )
1155 OSL_ENSURE( sal_False
, "Failed to remove object from storage!" );
1163 sal_Bool
EmbeddedObjectContainer::CloseEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
)
1165 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CloseEmbeddedObject" );
1167 // disconnect the object from the container and close it if possible
1169 sal_Bool bFound
= sal_False
;
1170 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
1171 while ( aIt
!= pImpl
->maObjectContainer
.end() )
1173 if ( (*aIt
).second
== xObj
)
1175 pImpl
->maObjectContainer
.erase( aIt
);
1185 uno::Reference
< ::util::XCloseable
> xClose( xObj
, uno::UNO_QUERY
);
1188 xClose
->close( sal_True
);
1190 catch ( uno::Exception
& )
1192 // it is no problem if the object is already closed
1193 // TODO/LATER: what if the object can not be closed?
1200 uno::Reference
< io::XInputStream
> EmbeddedObjectContainer::GetGraphicStream( const ::rtl::OUString
& aName
, rtl::OUString
* pMediaType
)
1202 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Name )" );
1204 uno::Reference
< io::XInputStream
> xStream
;
1206 OSL_ENSURE( aName
.getLength(), "Retrieving graphic for unknown object!" );
1207 if ( aName
.getLength() )
1211 uno::Reference
< embed::XStorage
> xReplacements
= pImpl
->GetReplacements();
1212 uno::Reference
< io::XStream
> xGraphicStream
= xReplacements
->openStreamElement( aName
, embed::ElementModes::READ
);
1213 xStream
= xGraphicStream
->getInputStream();
1216 uno::Reference
< beans::XPropertySet
> xSet( xStream
, uno::UNO_QUERY
);
1219 uno::Any aAny
= xSet
->getPropertyValue( ::rtl::OUString::createFromAscii("MediaType") );
1220 aAny
>>= *pMediaType
;
1224 catch ( uno::Exception
& )
1232 uno::Reference
< io::XInputStream
> EmbeddedObjectContainer::GetGraphicStream( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XEmbeddedObject
>& xObj
, rtl::OUString
* pMediaType
)
1234 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Object )" );
1236 // get the object name
1237 ::rtl::OUString aName
;
1238 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
1239 while ( aIt
!= pImpl
->maObjectContainer
.end() )
1241 if ( (*aIt
).second
== xObj
)
1243 aName
= (*aIt
).first
;
1250 // try to load it from the container storage
1251 return GetGraphicStream( aName
, pMediaType
);
1254 sal_Bool
EmbeddedObjectContainer::InsertGraphicStream( const com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
>& rStream
, const ::rtl::OUString
& rObjectName
, const rtl::OUString
& rMediaType
)
1256 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStream" );
1260 uno::Reference
< embed::XStorage
> xReplacements
= pImpl
->GetReplacements();
1262 // store it into the subfolder
1263 uno::Reference
< io::XOutputStream
> xOutStream
;
1264 uno::Reference
< io::XStream
> xGraphicStream
= xReplacements
->openStreamElement( rObjectName
,
1265 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
1266 xOutStream
= xGraphicStream
->getOutputStream();
1267 ::comphelper::OStorageHelper::CopyInputToOutput( rStream
, xOutStream
);
1268 xOutStream
->flush();
1270 uno::Reference
< beans::XPropertySet
> xPropSet( xGraphicStream
, uno::UNO_QUERY
);
1271 if ( !xPropSet
.is() )
1272 throw uno::RuntimeException();
1274 xPropSet
->setPropertyValue( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ),
1275 uno::makeAny( (sal_Bool
)sal_True
) );
1277 aAny
<<= rMediaType
;
1278 xPropSet
->setPropertyValue( ::rtl::OUString::createFromAscii("MediaType"), aAny
);
1280 xPropSet
->setPropertyValue( ::rtl::OUString::createFromAscii( "Compressed" ),
1281 uno::makeAny( (sal_Bool
)sal_True
) );
1283 catch( uno::Exception
& )
1291 sal_Bool
EmbeddedObjectContainer::InsertGraphicStreamDirectly( const com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
>& rStream
, const ::rtl::OUString
& rObjectName
, const rtl::OUString
& rMediaType
)
1293 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStreamDirectly" );
1297 uno::Reference
< embed::XStorage
> xReplacement
= pImpl
->GetReplacements();
1298 uno::Reference
< embed::XOptimizedStorage
> xOptRepl( xReplacement
, uno::UNO_QUERY_THROW
);
1300 // store it into the subfolder
1301 uno::Sequence
< beans::PropertyValue
> aProps( 3 );
1302 aProps
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
1303 aProps
[0].Value
<<= rMediaType
;
1304 aProps
[1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" ) );
1305 aProps
[1].Value
<<= (sal_Bool
)sal_True
;
1306 aProps
[2].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
1307 aProps
[2].Value
<<= (sal_Bool
)sal_True
;
1309 if ( xReplacement
->hasByName( rObjectName
) )
1310 xReplacement
->removeElement( rObjectName
);
1312 xOptRepl
->insertStreamElementDirect( rObjectName
, rStream
, aProps
);
1314 catch( uno::Exception
& )
1323 sal_Bool
EmbeddedObjectContainer::RemoveGraphicStream( const ::rtl::OUString
& rObjectName
)
1325 RTL_LOGFILE_CONTEXT( aLog
, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveGraphicStream" );
1329 uno::Reference
< embed::XStorage
> xReplacements
= pImpl
->GetReplacements();
1330 xReplacements
->removeElement( rObjectName
);
1332 catch( uno::Exception
& )
1340 void InsertStreamIntoPicturesStorage_Impl( const uno::Reference
< embed::XStorage
>& xDocStor
,
1341 const uno::Reference
< io::XInputStream
>& xInStream
,
1342 const ::rtl::OUString
& aStreamName
)
1344 OSL_ENSURE( aStreamName
.getLength() && xInStream
.is() && xDocStor
.is(), "Misuse of the method!\n" );
1348 uno::Reference
< embed::XStorage
> xPictures
= xDocStor
->openStorageElement(
1349 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pictures" ) ),
1350 embed::ElementModes::READWRITE
);
1351 uno::Reference
< io::XStream
> xObjReplStr
= xPictures
->openStreamElement(
1353 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
1354 uno::Reference
< io::XOutputStream
> xOutStream(
1355 xObjReplStr
->getInputStream(), uno::UNO_QUERY_THROW
);
1357 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream
, xOutStream
);
1358 xOutStream
->closeOutput();
1360 uno::Reference
< embed::XTransactedObject
> xTransact( xPictures
, uno::UNO_QUERY
);
1361 if ( xTransact
.is() )
1362 xTransact
->commit();
1364 catch( uno::Exception
& )
1366 OSL_ENSURE( sal_False
, "The pictures storage is not available!\n" );
1371 // -----------------------------------------------------------------------------
1372 sal_Bool
EmbeddedObjectContainer::StoreAsChildren(sal_Bool _bOasisFormat
,sal_Bool _bCreateEmbedded
,const uno::Reference
< embed::XStorage
>& _xStorage
)
1374 sal_Bool bResult
= sal_False
;
1377 comphelper::EmbeddedObjectContainer
aCnt( _xStorage
);
1378 const uno::Sequence
< ::rtl::OUString
> aNames
= GetObjectNames();
1379 const ::rtl::OUString
* pIter
= aNames
.getConstArray();
1380 const ::rtl::OUString
* pEnd
= pIter
+ aNames
.getLength();
1381 for(;pIter
!= pEnd
;++pIter
)
1383 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( *pIter
);
1384 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
1387 sal_Bool bSwitchBackToLoaded
= sal_False
;
1388 uno::Reference
< embed::XLinkageSupport
> xLink( xObj
, uno::UNO_QUERY
);
1390 uno::Reference
< io::XInputStream
> xStream
;
1391 ::rtl::OUString aMediaType
;
1393 sal_Int32 nCurState
= xObj
->getCurrentState();
1394 if ( nCurState
== embed::EmbedStates::LOADED
|| nCurState
== embed::EmbedStates::RUNNING
)
1396 // means that the object is not active
1397 // copy replacement image from old to new container
1398 xStream
= GetGraphicStream( xObj
, &aMediaType
);
1401 if ( !xStream
.is() )
1403 // the image must be regenerated
1404 // TODO/LATER: another aspect could be used
1405 if ( xObj
->getCurrentState() == embed::EmbedStates::LOADED
)
1406 bSwitchBackToLoaded
= sal_True
;
1408 xStream
= GetGraphicReplacementStream(
1409 embed::Aspects::MSOLE_CONTENT
,
1414 if ( _bOasisFormat
|| (xLink
.is() && xLink
->isLink()) )
1418 if ( _bOasisFormat
)
1420 // if it is an embedded object or the optimized inserting fails the normal inserting should be done
1421 if ( _bCreateEmbedded
1422 || !aCnt
.InsertGraphicStreamDirectly( xStream
, *pIter
, aMediaType
) )
1423 aCnt
.InsertGraphicStream( xStream
, *pIter
, aMediaType
);
1427 // it is a linked object exported into SO7 format
1428 InsertStreamIntoPicturesStorage_Impl( _xStorage
, xStream
, *pIter
);
1433 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1434 if ( xPersist
.is() )
1436 uno::Sequence
< beans::PropertyValue
> aArgs( _bOasisFormat
? 2 : 3 );
1437 aArgs
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StoreVisualReplacement" ) );
1438 aArgs
[0].Value
<<= (sal_Bool
)( !_bOasisFormat
);
1440 // if it is an embedded object or the optimized inserting fails the normal inserting should be done
1441 aArgs
[1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanTryOptimization" ) );
1442 aArgs
[1].Value
<<= !_bCreateEmbedded
;
1443 if ( !_bOasisFormat
)
1445 // if object has no cached replacement it will use this one
1446 aArgs
[2].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VisualReplacement" ) );
1447 aArgs
[2].Value
<<= xStream
;
1450 xPersist
->storeAsEntry( _xStorage
,
1451 xPersist
->getEntryName(),
1452 uno::Sequence
< beans::PropertyValue
>(),
1456 if ( bSwitchBackToLoaded
)
1457 // switch back to loaded state; that way we have a minimum cache confusion
1458 xObj
->changeState( embed::EmbedStates::LOADED
);
1462 bResult
= aCnt
.CommitImageSubStorage();
1465 catch ( uno::Exception
& )
1467 // TODO/LATER: error handling
1468 bResult
= sal_False
;
1471 // the old SO6 format does not store graphical replacements
1472 if ( !_bOasisFormat
&& bResult
)
1476 // the substorage still can not be locked by the embedded object conteiner
1477 ::rtl::OUString
aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
1478 if ( _xStorage
->hasByName( aObjReplElement
) && _xStorage
->isStorageElement( aObjReplElement
) )
1479 _xStorage
->removeElement( aObjReplElement
);
1481 catch ( uno::Exception
& )
1483 // TODO/LATER: error handling;
1484 bResult
= sal_False
;
1489 // -----------------------------------------------------------------------------
1490 sal_Bool
EmbeddedObjectContainer::StoreChildren(sal_Bool _bOasisFormat
,sal_Bool _bObjectsOnly
)
1492 sal_Bool bResult
= sal_True
;
1493 const uno::Sequence
< ::rtl::OUString
> aNames
= GetObjectNames();
1494 const ::rtl::OUString
* pIter
= aNames
.getConstArray();
1495 const ::rtl::OUString
* pEnd
= pIter
+ aNames
.getLength();
1496 for(;pIter
!= pEnd
;++pIter
)
1498 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( *pIter
);
1499 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
1502 sal_Int32 nCurState
= xObj
->getCurrentState();
1503 if ( _bOasisFormat
&& nCurState
!= embed::EmbedStates::LOADED
&& nCurState
!= embed::EmbedStates::RUNNING
)
1505 // means that the object is active
1506 // the image must be regenerated
1507 ::rtl::OUString aMediaType
;
1509 // TODO/LATER: another aspect could be used
1510 uno::Reference
< io::XInputStream
> xStream
=
1511 GetGraphicReplacementStream(
1512 embed::Aspects::MSOLE_CONTENT
,
1517 if ( !InsertGraphicStreamDirectly( xStream
, *pIter
, aMediaType
) )
1518 InsertGraphicStream( xStream
, *pIter
, aMediaType
);
1522 // TODO/LATER: currently the object by default does not cache replacement image
1523 // that means that if somebody loads SO7 document and store its objects using
1524 // this method the images might be lost.
1525 // Currently this method is only used on storing to alien formats, that means
1526 // that SO7 documents storing does not use it, and all other filters are
1527 // based on OASIS format. But if it changes the method must be fixed. The fix
1528 // must be done only on demand since it can affect performance.
1530 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1531 if ( xPersist
.is() )
1535 //TODO/LATER: only storing if changed!
1536 xPersist
->storeOwn();
1538 catch( uno::Exception
& )
1540 // TODO/LATER: error handling
1541 bResult
= sal_False
;
1546 if ( !_bOasisFormat
&& !_bObjectsOnly
)
1548 // copy replacement images for linked objects
1551 uno::Reference
< embed::XLinkageSupport
> xLink( xObj
, uno::UNO_QUERY
);
1552 if ( xLink
.is() && xLink
->isLink() )
1554 ::rtl::OUString aMediaType
;
1555 uno::Reference
< io::XInputStream
> xInStream
= GetGraphicStream( xObj
, &aMediaType
);
1556 if ( xInStream
.is() )
1557 InsertStreamIntoPicturesStorage_Impl( pImpl
->mxStorage
, xInStream
, *pIter
);
1560 catch( uno::Exception
& )
1567 if ( bResult
&& _bOasisFormat
)
1568 bResult
= CommitImageSubStorage();
1570 if ( bResult
&& !_bObjectsOnly
)
1574 ReleaseImageSubStorage();
1575 ::rtl::OUString
aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
1576 if ( !_bOasisFormat
&& pImpl
->mxStorage
->hasByName( aObjReplElement
) && pImpl
->mxStorage
->isStorageElement( aObjReplElement
) )
1577 pImpl
->mxStorage
->removeElement( aObjReplElement
);
1579 catch( uno::Exception
& )
1581 // TODO/LATER: error handling
1582 bResult
= sal_False
;
1587 // -----------------------------------------------------------------------------
1588 uno::Reference
< io::XInputStream
> EmbeddedObjectContainer::GetGraphicReplacementStream(
1589 sal_Int64 nViewAspect
,
1590 const uno::Reference
< embed::XEmbeddedObject
>& xObj
,
1591 ::rtl::OUString
* pMediaType
)
1593 uno::Reference
< io::XInputStream
> xInStream
;
1598 // retrieving of the visual representation can switch object to running state
1599 embed::VisualRepresentation aRep
= xObj
->getPreferredVisualRepresentation( nViewAspect
);
1601 *pMediaType
= aRep
.Flavor
.MimeType
;
1603 uno::Sequence
< sal_Int8
> aSeq
;
1605 xInStream
= new ::comphelper::SequenceInputStream( aSeq
);
1607 catch ( uno::Exception
& )
1614 // -----------------------------------------------------------------------------
1615 sal_Bool
EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference
< embed::XStorage
>& _xStorage
,bool _bClearModifedFlag
)
1617 sal_Bool bError
= sal_False
;
1618 const uno::Sequence
< ::rtl::OUString
> aNames
= GetObjectNames();
1619 const ::rtl::OUString
* pIter
= aNames
.getConstArray();
1620 const ::rtl::OUString
* pEnd
= pIter
+ aNames
.getLength();
1621 for(;pIter
!= pEnd
;++pIter
)
1623 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( *pIter
);
1624 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
1627 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1628 if ( xPersist
.is() )
1632 xPersist
->setPersistentEntry( _xStorage
,
1634 embed::EntryInitModes::NO_INIT
,
1635 uno::Sequence
< beans::PropertyValue
>(),
1636 uno::Sequence
< beans::PropertyValue
>() );
1639 catch( uno::Exception
& )
1641 // TODO/LATER: error handling
1646 if ( _bClearModifedFlag
)
1648 // if this method is used as part of SaveCompleted the object must stay unmodified after execution
1651 uno::Reference
< util::XModifiable
> xModif( xObj
->getComponent(), uno::UNO_QUERY_THROW
);
1652 if ( xModif
->isModified() )
1653 xModif
->setModified( sal_False
);
1655 catch( uno::Exception
& )