xref: /AOO41X/main/comphelper/source/container/embeddedobjectcontainer.cxx (revision 83137a03adbb58b5b3bdafefefa1e93de35e0011)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_comphelper.hxx"
26 #include <com/sun/star/container/XChild.hpp>
27 #include <com/sun/star/container/XNameAccess.hpp>
28 #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
29 #include <com/sun/star/embed/XLinkCreator.hpp>
30 #include <com/sun/star/embed/XEmbedPersist.hpp>
31 #include <com/sun/star/embed/XLinkageSupport.hpp>
32 #include <com/sun/star/embed/XTransactedObject.hpp>
33 #include <com/sun/star/embed/XOptimizedStorage.hpp>
34 #include <com/sun/star/embed/EntryInitModes.hpp>
35 #include <com/sun/star/util/XCloseable.hpp>
36 #include <com/sun/star/util/XModifiable.hpp>
37 #include <com/sun/star/embed/EmbedStates.hpp>
38 #include <com/sun/star/datatransfer/XTransferable.hpp>
39 #include <com/sun/star/beans/XPropertySetInfo.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/embed/Aspects.hpp>
42 #include <com/sun/star/embed/EmbedMisc.hpp>
43 
44 #include <comphelper/seqstream.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <comphelper/storagehelper.hxx>
47 #include <comphelper/embeddedobjectcontainer.hxx>
48 #include <comphelper/sequence.hxx>
49 #include <cppuhelper/weakref.hxx>
50 #include <hash_map>
51 #include <algorithm>
52 
53 #include <rtl/logfile.hxx>
54 
55 using namespace ::com::sun::star;
56 
57 namespace comphelper
58 {
59 
60 struct hashObjectName_Impl
61 {
62     size_t operator()(const ::rtl::OUString Str) const
63     {
64         return (size_t)Str.hashCode();
65     }
66 };
67 
68 struct eqObjectName_Impl
69 {
70     sal_Bool operator()(const ::rtl::OUString Str1, const ::rtl::OUString Str2) const
71     {
72         return ( Str1 == Str2 );
73     }
74 };
75 
76 typedef std::hash_map
77 <
78     ::rtl::OUString,
79     ::com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >,
80     hashObjectName_Impl,
81     eqObjectName_Impl
82 >
83 EmbeddedObjectContainerNameMap;
84 
85 struct EmbedImpl
86 {
87     // TODO/LATER: remove objects from temp. Container storage when object is disposed
88     EmbeddedObjectContainerNameMap maObjectContainer;
89     uno::Reference < embed::XStorage > mxStorage;
90     EmbeddedObjectContainer* mpTempObjectContainer;
91     uno::Reference < embed::XStorage > mxImageStorage;
92     uno::WeakReference < uno::XInterface > m_xModel;
93     //EmbeddedObjectContainerNameMap maTempObjectContainer;
94     //uno::Reference < embed::XStorage > mxTempStorage;
95 
96     /// bitfield
97     bool mbOwnsStorage : 1;
98     bool mbUserAllowsLinkUpdate : 1;
99 
100     const uno::Reference < embed::XStorage >& GetReplacements();
101 };
102 
103 const uno::Reference < embed::XStorage >& EmbedImpl::GetReplacements()
104 {
105     if ( !mxImageStorage.is() )
106     {
107         try
108         {
109             mxImageStorage = mxStorage->openStorageElement(
110                 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READWRITE );
111         }
112         catch ( uno::Exception& )
113         {
114             mxImageStorage = mxStorage->openStorageElement(
115                 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READ );
116         }
117     }
118 
119     if ( !mxImageStorage.is() )
120         throw io::IOException();
121 
122     return mxImageStorage;
123 }
124 
125 EmbeddedObjectContainer::EmbeddedObjectContainer()
126 {
127     pImpl = new EmbedImpl;
128     pImpl->mxStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
129     pImpl->mbOwnsStorage = true;
130     pImpl->mbUserAllowsLinkUpdate = true;
131     pImpl->mpTempObjectContainer = 0;
132 }
133 
134 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor )
135 {
136     pImpl = new EmbedImpl;
137     pImpl->mxStorage = rStor;
138     pImpl->mbOwnsStorage = false;
139     pImpl->mbUserAllowsLinkUpdate = true;
140     pImpl->mpTempObjectContainer = 0;
141 }
142 
143 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor, const uno::Reference < uno::XInterface >& xModel )
144 {
145     pImpl = new EmbedImpl;
146     pImpl->mxStorage = rStor;
147     pImpl->mbOwnsStorage = false;
148     pImpl->mbUserAllowsLinkUpdate = true;
149     pImpl->mpTempObjectContainer = 0;
150     pImpl->m_xModel = xModel;
151 }
152 
153 void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference < embed::XStorage >& rStor )
154 {
155     ReleaseImageSubStorage();
156 
157     if ( pImpl->mbOwnsStorage )
158         pImpl->mxStorage->dispose();
159 
160     pImpl->mxStorage = rStor;
161     pImpl->mbOwnsStorage = false;
162 }
163 
164 sal_Bool EmbeddedObjectContainer::CommitImageSubStorage()
165 {
166     if ( pImpl->mxImageStorage.is() )
167     {
168         try
169         {
170             sal_Bool bReadOnlyMode = sal_True;
171             uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY);
172             if ( xSet.is() )
173             {
174                 // get the open mode from the parent storage
175                 sal_Int32 nMode = 0;
176                 uno::Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("OpenMode") );
177                 if ( aAny >>= nMode )
178                     bReadOnlyMode = !(nMode & embed::ElementModes::WRITE );
179             } // if ( xSet.is() )
180             if ( !bReadOnlyMode )
181             {
182                 uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW );
183                 xTransact->commit();
184             }
185         }
186         catch( uno::Exception& )
187         {
188             return sal_False;
189         }
190     }
191 
192     return sal_True;
193 }
194 
195 void EmbeddedObjectContainer::ReleaseImageSubStorage()
196 {
197     CommitImageSubStorage();
198 
199     if ( pImpl->mxImageStorage.is() )
200     {
201         try
202         {
203             pImpl->mxImageStorage->dispose();
204             pImpl->mxImageStorage = uno::Reference< embed::XStorage >();
205         }
206         catch( uno::Exception& )
207         {
208             OSL_ASSERT( "Problems releasing image substorage!\n" );
209         }
210     }
211 }
212 
213 EmbeddedObjectContainer::~EmbeddedObjectContainer()
214 {
215     ReleaseImageSubStorage();
216 
217     if ( pImpl->mbOwnsStorage )
218         pImpl->mxStorage->dispose();
219 
220     delete pImpl->mpTempObjectContainer;
221     delete pImpl;
222 }
223 
224 void EmbeddedObjectContainer::CloseEmbeddedObjects()
225 {
226     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
227     while ( aIt != pImpl->maObjectContainer.end() )
228     {
229         uno::Reference < util::XCloseable > xClose( (*aIt).second, uno::UNO_QUERY );
230         if ( xClose.is() )
231         {
232             try
233             {
234                 xClose->close( sal_True );
235             }
236             catch ( uno::Exception& )
237             {
238             }
239         }
240 
241         aIt++;
242     }
243 }
244 
245 ::rtl::OUString EmbeddedObjectContainer::CreateUniqueObjectName()
246 {
247     ::rtl::OUString aPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
248     ::rtl::OUString aStr;
249     sal_Int32 i=1;
250     do
251     {
252         aStr = aPersistName;
253         aStr += ::rtl::OUString::valueOf( i++ );
254     }
255     while( HasEmbeddedObject( aStr ) );
256     // TODO/LATER: should we consider deleted objects?
257 
258     return aStr;
259 }
260 
261 uno::Sequence < ::rtl::OUString > EmbeddedObjectContainer::GetObjectNames()
262 {
263     uno::Sequence < ::rtl::OUString > aSeq( pImpl->maObjectContainer.size() );
264     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
265     sal_Int32 nIdx=0;
266     while ( aIt != pImpl->maObjectContainer.end() )
267         aSeq[nIdx++] = (*aIt++).first;
268     return aSeq;
269 }
270 
271 sal_Bool EmbeddedObjectContainer::HasEmbeddedObjects()
272 {
273     return pImpl->maObjectContainer.size() != 0;
274 }
275 
276 sal_Bool EmbeddedObjectContainer::HasEmbeddedObject( const ::rtl::OUString& rName )
277 {
278     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
279     if ( aIt == pImpl->maObjectContainer.end() )
280     {
281         uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
282         return xAccess->hasByName(rName);
283     }
284     else
285         return sal_True;
286 }
287 
288 sal_Bool EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj )
289 {
290     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
291     while ( aIt != pImpl->maObjectContainer.end() )
292     {
293         if ( (*aIt).second == xObj )
294             return sal_True;
295         else
296             aIt++;
297     }
298 
299     return sal_False;
300 }
301 
302 sal_Bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const ::rtl::OUString& rName )
303 {
304     // allows to detect whether the object was already instantiated
305     // currently the filter instantiate it on loading, so this method allows
306     // to avoid objects pointing to the same persistence
307     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
308     return ( aIt != pImpl->maObjectContainer.end() );
309 }
310 
311 ::rtl::OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj )
312 {
313     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
314     while ( aIt != pImpl->maObjectContainer.end() )
315     {
316         if ( (*aIt).second == xObj )
317             return (*aIt).first;
318         else
319             aIt++;
320     }
321 
322     OSL_ENSURE( 0, "Unknown object!" );
323     return ::rtl::OUString();
324 }
325 
326 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::GetEmbeddedObject( const ::rtl::OUString& rName )
327 {
328     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetEmbeddedObject" );
329 
330     OSL_ENSURE( !rName.isEmpty(), "Empty object name!");
331 
332     uno::Reference < embed::XEmbeddedObject > xObj;
333     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
334 
335 #if OSL_DEBUG_LEVEL > 1
336     uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
337     uno::Sequence< ::rtl::OUString> aSeq = xAccess->getElementNames();
338     const ::rtl::OUString* pIter = aSeq.getConstArray();
339     const ::rtl::OUString* pEnd   = pIter + aSeq.getLength();
340     for(;pIter != pEnd;++pIter)
341     {
342         (void)*pIter;
343     }
344     OSL_ENSURE( aIt != pImpl->maObjectContainer.end() || xAccess->hasByName(rName), "Could not return object!" );
345 #endif
346 
347     // check if object was already created
348     if ( aIt != pImpl->maObjectContainer.end() )
349         xObj = (*aIt).second;
350     else
351         xObj = Get_Impl( rName, uno::Reference < embed::XEmbeddedObject >() );
352 
353     return xObj;
354 }
355 
356 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::Get_Impl( const ::rtl::OUString& rName, const uno::Reference < embed::XEmbeddedObject >& xCopy )
357 {
358     uno::Reference < embed::XEmbeddedObject > xObj;
359     try
360     {
361         // create the object from the storage
362         uno::Reference < beans::XPropertySet > xSet( pImpl->mxStorage, uno::UNO_QUERY );
363         sal_Bool bReadOnlyMode = sal_True;
364         if ( xSet.is() )
365         {
366             // get the open mode from the parent storage
367             sal_Int32 nMode = 0;
368             uno::Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("OpenMode") );
369             if ( aAny >>= nMode )
370                 bReadOnlyMode = !(nMode & embed::ElementModes::WRITE );
371         }
372 
373         // object was not added until now - should happen only by calling this method from "inside"
374         //TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call)
375         uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
376                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
377         uno::Sequence< beans::PropertyValue > aObjDescr( xCopy.is() ? 2 : 1 );
378         aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
379         aObjDescr[0].Value <<= pImpl->m_xModel.get();
380         if ( xCopy.is() )
381         {
382             aObjDescr[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CloneFrom" ) );
383             aObjDescr[1].Value <<= xCopy;
384         }
385 
386         uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
387         aMediaDescr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly"));
388         aMediaDescr[0].Value <<= bReadOnlyMode;
389         xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromEntry(
390                 pImpl->mxStorage, rName,
391                 aMediaDescr, aObjDescr ), uno::UNO_QUERY );
392 
393         // insert object into my list
394         AddEmbeddedObject( xObj, rName );
395     }
396     catch ( uno::Exception& )
397     {
398     }
399 
400     return xObj;
401 }
402 
403 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId,
404             const uno::Sequence < beans::PropertyValue >& rArgs, ::rtl::OUString& rNewName )
405 {
406     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CreateEmbeddedObject" );
407 
408     if ( rNewName.isEmpty() )
409         rNewName = CreateUniqueObjectName();
410 
411     OSL_ENSURE( !HasEmbeddedObject(rNewName), "Object to create already exists!");
412 
413     // create object from classid by inserting it into storage
414     uno::Reference < embed::XEmbeddedObject > xObj;
415     try
416     {
417         uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
418                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
419 
420         uno::Sequence< beans::PropertyValue > aObjDescr( rArgs.getLength() + 1 );
421         aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
422         aObjDescr[0].Value <<= pImpl->m_xModel.get();
423         ::std::copy( rArgs.getConstArray(), rArgs.getConstArray() + rArgs.getLength(), aObjDescr.getArray() + 1 );
424         xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitNew(
425                     rClassId, ::rtl::OUString(), pImpl->mxStorage, rNewName,
426                     aObjDescr ), uno::UNO_QUERY );
427 
428         AddEmbeddedObject( xObj, rNewName );
429 
430         OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
431                     "A freshly create object should be running always!\n" );
432     }
433     catch ( uno::Exception& )
434     {
435     }
436 
437     return xObj;
438 }
439 
440 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId, ::rtl::OUString& rNewName )
441 {
442     return CreateEmbeddedObject( rClassId, uno::Sequence < beans::PropertyValue >(), rNewName );
443 }
444 
445 void EmbeddedObjectContainer::AddEmbeddedObject( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, const ::rtl::OUString& rName )
446 {
447     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::AddEmbeddedObject" );
448 
449 #if OSL_DEBUG_LEVEL > 1
450     OSL_ENSURE( !rName.isEmpty(), "Added object doesn't have a name!");
451     uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
452     uno::Reference < embed::XEmbedPersist > xEmb( xObj, uno::UNO_QUERY );
453     uno::Reference < embed::XLinkageSupport > xLink( xEmb, uno::UNO_QUERY );
454     // if the object has a persistance and the object is not a link than it must have persistence entry in the storage
455     OSL_ENSURE( !( xEmb.is() && ( !xLink.is() || !xLink->isLink() ) ) || xAccess->hasByName(rName),
456                     "Added element not in storage!" );
457 #endif
458 
459     // remember object - it needs to be in storage already
460     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
461     OSL_ENSURE( aIt == pImpl->maObjectContainer.end(), "Element already inserted!" );
462     pImpl->maObjectContainer[ rName ] = xObj;
463     uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
464     if ( xChild.is() && xChild->getParent() != pImpl->m_xModel.get() )
465         xChild->setParent( pImpl->m_xModel.get() );
466 
467     // look for object in temorary container
468     if ( pImpl->mpTempObjectContainer )
469     {
470         aIt = pImpl->mpTempObjectContainer->pImpl->maObjectContainer.begin();
471         while ( aIt != pImpl->mpTempObjectContainer->pImpl->maObjectContainer.end() )
472         {
473             if ( (*aIt).second == xObj )
474             {
475                 // copy replacement image from temporary container (if there is any)
476                 ::rtl::OUString aTempName = (*aIt).first;
477                 ::rtl::OUString aMediaType;
478                 uno::Reference < io::XInputStream > xStream = pImpl->mpTempObjectContainer->GetGraphicStream( xObj, &aMediaType );
479                 if ( xStream.is() )
480                 {
481                     InsertGraphicStream( xStream, rName, aMediaType );
482                     xStream = 0;
483                     pImpl->mpTempObjectContainer->RemoveGraphicStream( aTempName );
484                 }
485 
486                 // remove object from storage of temporary container
487                 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
488                 if ( xPersist.is() )
489                 {
490                     try
491                     {
492                         pImpl->mpTempObjectContainer->pImpl->mxStorage->removeElement( aTempName );
493                     }
494                     catch ( uno::Exception& )
495                     {
496                     }
497                 }
498 
499                 // temp. container needs to forget the object
500                 pImpl->mpTempObjectContainer->pImpl->maObjectContainer.erase( aIt );
501                 break;
502             }
503             else
504                 aIt++;
505         }
506     }
507 }
508 
509 sal_Bool EmbeddedObjectContainer::StoreEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName, sal_Bool bCopy )
510 {
511     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::StoreEmbeddedObject" );
512 
513     uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
514     if ( rName.isEmpty() )
515         rName = CreateUniqueObjectName();
516 
517 #if OSL_DEBUG_LEVEL > 1
518     uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
519     OSL_ENSURE( !xPersist.is() || !xAccess->hasByName(rName), "Inserting element already present in storage!" );
520     OSL_ENSURE( xPersist.is() || xObj->getCurrentState() == embed::EmbedStates::RUNNING, "Non persistent object inserted!");
521 #endif
522 
523     // insert objects' storage into the container storage (if object has one)
524     try
525     {
526         if ( xPersist.is() )
527         {
528             uno::Sequence < beans::PropertyValue > aSeq;
529             if ( bCopy )
530                 xPersist->storeToEntry( pImpl->mxStorage, rName, aSeq, aSeq );
531             else
532             {
533                 //TODO/LATER: possible optimisation, don't store immediately
534                 //xPersist->setPersistentEntry( pImpl->mxStorage, rName, embed::EntryInitModes::ENTRY_NO_INIT, aSeq, aSeq );
535                 xPersist->storeAsEntry( pImpl->mxStorage, rName, aSeq, aSeq );
536                 xPersist->saveCompleted( sal_True );
537             }
538         }
539     }
540     catch ( uno::Exception& )
541     {
542         // TODO/LATER: better error recovery should keep storage intact
543         return sal_False;
544     }
545 
546     return sal_True;
547 }
548 
549 sal_Bool EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
550 {
551     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( Object )" );
552     // store it into the container storage
553     if ( StoreEmbeddedObject( xObj, rName, sal_False ) )
554     {
555         // remember object
556         AddEmbeddedObject( xObj, rName );
557         return sal_True;
558     }
559     else
560         return sal_False;
561 }
562 
563 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference < io::XInputStream >& xStm, ::rtl::OUString& rNewName )
564 {
565     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( InputStream )" );
566 
567     if ( rNewName.isEmpty() )
568         rNewName = CreateUniqueObjectName();
569 
570     // store it into the container storage
571     sal_Bool bIsStorage = sal_False;
572     try
573     {
574         // first try storage persistence
575         uno::Reference < embed::XStorage > xStore = ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm );
576 
577         // storage was created from stream successfully
578         bIsStorage = sal_True;
579 
580         uno::Reference < embed::XStorage > xNewStore = pImpl->mxStorage->openStorageElement( rNewName, embed::ElementModes::READWRITE );
581         xStore->copyToStorage( xNewStore );
582     }
583     catch ( uno::Exception& )
584     {
585         if ( bIsStorage )
586             // it is storage persistence, but opening of new substorage or copying to it failed
587             return uno::Reference < embed::XEmbeddedObject >();
588 
589         // stream didn't contain a storage, now try stream persistence
590         try
591         {
592             uno::Reference < io::XStream > xNewStream = pImpl->mxStorage->openStreamElement( rNewName, embed::ElementModes::READWRITE );
593             ::comphelper::OStorageHelper::CopyInputToOutput( xStm, xNewStream->getOutputStream() );
594 
595             // No mediatype is provided so the default for OLE objects value is used
596             // it is correct so for now, but what if somebody introduces a new stream based embedded object?
597             // Probably introducing of such an object must be restricted ( a storage must be used! ).
598             uno::Reference< beans::XPropertySet > xProps( xNewStream, uno::UNO_QUERY_THROW );
599             xProps->setPropertyValue(
600                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
601                     uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) ) ) );
602         }
603         catch ( uno::Exception& )
604         {
605             // complete disaster!
606             return uno::Reference < embed::XEmbeddedObject >();
607         }
608     }
609 
610     // stream was copied into the container storage in either way, now try to open something form it
611     uno::Reference < embed::XEmbeddedObject > xRet = GetEmbeddedObject( rNewName );
612     try
613     {
614         if ( !xRet.is() )
615             // no object could be created, so withdraw insertion
616             pImpl->mxStorage->removeElement( rNewName );
617     }
618     catch ( uno::Exception& )
619     {
620     }
621 
622     return xRet;
623 }
624 
625 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, ::rtl::OUString& rNewName )
626 {
627     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( MediaDescriptor )" );
628 
629     if ( rNewName.isEmpty() )
630         rNewName = CreateUniqueObjectName();
631 
632     uno::Reference < embed::XEmbeddedObject > xObj;
633     try
634     {
635         uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
636                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
637         uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
638         aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
639         aObjDescr[0].Value <<= pImpl->m_xModel.get();
640         xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromMediaDescriptor(
641                 pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY );
642         uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
643 
644         OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
645                     "A freshly create object should be running always!\n" );
646 
647         // possible optimization: store later!
648         if ( xPersist.is())
649             xPersist->storeOwn();
650 
651         AddEmbeddedObject( xObj, rNewName );
652     }
653     catch ( uno::Exception& )
654     {
655     }
656 
657     return xObj;
658 }
659 
660 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedLink( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, ::rtl::OUString& rNewName )
661 {
662     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedLink" );
663 
664     if ( rNewName.isEmpty() )
665         rNewName = CreateUniqueObjectName();
666 
667     uno::Reference < embed::XEmbeddedObject > xObj;
668     try
669     {
670         uno::Reference < embed::XLinkCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
671                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
672         uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
673         aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
674         aObjDescr[0].Value <<= pImpl->m_xModel.get();
675         xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceLink(
676                 pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY );
677 
678         uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
679 
680         OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
681                     "A freshly create object should be running always!\n" );
682 
683         // possible optimization: store later!
684         if ( xPersist.is())
685             xPersist->storeOwn();
686 
687         AddEmbeddedObject( xObj, rNewName );
688     }
689     catch ( uno::Exception& )
690     {
691     }
692 
693     return xObj;
694 }
695 
696 sal_Bool EmbeddedObjectContainer::TryToCopyGraphReplacement( EmbeddedObjectContainer& rSrc,
697                                                             const ::rtl::OUString& aOrigName,
698                                                             const ::rtl::OUString& aTargetName )
699 {
700     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::TryToCopyGraphReplacement" );
701 
702     sal_Bool bResult = sal_False;
703 
704     if ( ( &rSrc != this || !aOrigName.equals( aTargetName ) ) && !aOrigName.isEmpty() && !aTargetName.isEmpty() )
705     {
706         ::rtl::OUString aMediaType;
707         uno::Reference < io::XInputStream > xGrStream = rSrc.GetGraphicStream( aOrigName, &aMediaType );
708         if ( xGrStream.is() )
709             bResult = InsertGraphicStream( xGrStream, aTargetName, aMediaType );
710     }
711 
712     return bResult;
713 }
714 
715 sal_Bool EmbeddedObjectContainer::CopyEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
716 {
717     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyEmbeddedObject" );
718 
719     OSL_ENSURE( sal_False,
720                 "This method is depricated! Use EmbeddedObjectContainer::CopyAndGetEmbeddedObject() to copy object!\n" );
721 
722     // get the object name before(!) it is assigned to a new storage
723     ::rtl::OUString aOrigName;
724     uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
725     if ( xPersist.is() )
726         aOrigName = xPersist->getEntryName();
727 
728     if ( rName.isEmpty() )
729         rName = CreateUniqueObjectName();
730 
731     if ( StoreEmbeddedObject( xObj, rName, sal_True ) )
732     {
733         TryToCopyGraphReplacement( rSrc, aOrigName, rName );
734         return sal_True;
735     }
736 
737     return sal_False;
738 }
739 
740 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CopyAndGetEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
741 {
742     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyAndGetEmbeddedObject" );
743 
744     uno::Reference< embed::XEmbeddedObject > xResult;
745 
746     // TODO/LATER: For now only objects that implement XEmbedPersist have a replacement image, it might change in future
747     // do an incompatible change so that object name is provided in all the move and copy methods
748     ::rtl::OUString aOrigName;
749     try
750     {
751         uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY_THROW );
752         aOrigName = xPersist->getEntryName();
753     }
754     catch( uno::Exception& )
755     {}
756 
757     if ( rName.isEmpty() )
758         rName = CreateUniqueObjectName();
759 
760     // objects without persistance are not really stored by the method
761     if ( xObj.is() && StoreEmbeddedObject( xObj, rName, sal_True ) )
762     {
763         xResult = Get_Impl( rName, xObj);
764         if ( !xResult.is() )
765         {
766             // this is a case when object has no real persistence
767             // in such cases a new object should be explicitly created and initialized with the data of the old one
768             try
769             {
770                 uno::Reference< embed::XLinkageSupport > xOrigLinkage( xObj, uno::UNO_QUERY );
771                 if ( xOrigLinkage.is() && xOrigLinkage->isLink() )
772                 {
773                     // this is a OOo link, it has no persistence
774                     ::rtl::OUString aURL = xOrigLinkage->getLinkURL();
775                     if ( aURL.isEmpty() )
776                         throw uno::RuntimeException();
777 
778                     // create new linked object from the URL the link is based on
779                     uno::Reference < embed::XLinkCreator > xCreator(
780                         ::comphelper::getProcessServiceFactory()->createInstance(
781                             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
782                         uno::UNO_QUERY_THROW );
783 
784                     uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
785                     aMediaDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
786                     aMediaDescr[0].Value <<= aURL;
787                     uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
788                     aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
789                     aObjDescr[0].Value <<= pImpl->m_xModel.get();
790                     xResult = uno::Reference < embed::XEmbeddedObject >(
791                                 xCreator->createInstanceLink(
792                                     pImpl->mxStorage,
793                                     rName,
794                                     aMediaDescr,
795                                     aObjDescr ),
796                                 uno::UNO_QUERY_THROW );
797                 }
798                 else
799                 {
800                     // the component is required for copying of this object
801                     if ( xObj->getCurrentState() == embed::EmbedStates::LOADED )
802                         xObj->changeState( embed::EmbedStates::RUNNING );
803 
804                     // this must be an object based on properties, otherwise we can not copy it currently
805                     uno::Reference< beans::XPropertySet > xOrigProps( xObj->getComponent(), uno::UNO_QUERY_THROW );
806 
807                     // use object class ID to create a new one and tranfer all the properties
808                     uno::Reference < embed::XEmbedObjectCreator > xCreator(
809                         ::comphelper::getProcessServiceFactory()->createInstance(
810                             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
811                         uno::UNO_QUERY_THROW );
812 
813                     uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
814                     aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
815                     aObjDescr[0].Value <<= pImpl->m_xModel.get();
816                     xResult = uno::Reference < embed::XEmbeddedObject >(
817                                 xCreator->createInstanceInitNew(
818                                     xObj->getClassID(),
819                                     xObj->getClassName(),
820                                     pImpl->mxStorage,
821                                     rName,
822                                     aObjDescr ),
823                                 uno::UNO_QUERY_THROW );
824 
825                     if ( xResult->getCurrentState() == embed::EmbedStates::LOADED )
826                         xResult->changeState( embed::EmbedStates::RUNNING );
827 
828                     uno::Reference< beans::XPropertySet > xTargetProps( xResult->getComponent(), uno::UNO_QUERY_THROW );
829 
830                     // copy all the properties from xOrigProps to xTargetProps
831                     uno::Reference< beans::XPropertySetInfo > xOrigInfo = xOrigProps->getPropertySetInfo();
832                     if ( !xOrigInfo.is() )
833                         throw uno::RuntimeException();
834 
835                     uno::Sequence< beans::Property > aPropertiesList = xOrigInfo->getProperties();
836                     for ( sal_Int32 nInd = 0; nInd < aPropertiesList.getLength(); nInd++ )
837                     {
838                         try
839                         {
840                             xTargetProps->setPropertyValue(
841                                 aPropertiesList[nInd].Name,
842                                 xOrigProps->getPropertyValue( aPropertiesList[nInd].Name ) );
843                         }
844                         catch( beans::PropertyVetoException& )
845                         {
846                             // impossibility to copy readonly property is not treated as an error for now
847                             // but the assertion is helpful to detect such scenarios and review them
848                             OSL_ENSURE( sal_False, "Could not copy readonly property!\n" );
849                         }
850                     }
851                 }
852 
853                 if ( xResult.is() )
854                     AddEmbeddedObject( xResult, rName );
855             }
856             catch( uno::Exception& )
857             {
858                 if ( xResult.is() )
859                 {
860                     try
861                     {
862                         xResult->close( sal_True );
863                     }
864                     catch( uno::Exception& )
865                     {}
866                     xResult = uno::Reference< embed::XEmbeddedObject >();
867                 }
868             }
869         }
870     }
871 
872     OSL_ENSURE( xResult.is(), "Can not copy embedded object that has no persistance!\n" );
873 
874     if ( xResult.is() )
875     {
876         // the object is successfully copied, try to copy graphical replacement
877         if ( !aOrigName.isEmpty() )
878             TryToCopyGraphReplacement( rSrc, aOrigName, rName );
879 
880         // the object might need the size to be set
881         try
882         {
883             if ( xResult->getStatus( embed::Aspects::MSOLE_CONTENT ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD )
884                 xResult->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT,
885                                             xObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ) );
886         }
887         catch( uno::Exception& )
888         {}
889     }
890 
891     return xResult;
892 }
893 
894 sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
895 {
896     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Object )" );
897 
898     // get the object name before(!) it is assigned to a new storage
899     uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
900     ::rtl::OUString aName;
901     if ( xPersist.is() )
902         aName = xPersist->getEntryName();
903 
904     // now move the object to the new container; the returned name is the new persist name in this container
905     sal_Bool bRet;
906 
907     try
908     {
909         bRet = InsertEmbeddedObject( xObj, rName );
910         if ( bRet )
911             TryToCopyGraphReplacement( rSrc, aName, rName );
912     }
913     catch ( uno::Exception& e )
914     {
915         (void)e;
916         OSL_ENSURE( sal_False, "Failed to insert embedded object into storage!" );
917         bRet = sal_False;
918     }
919 
920     if ( bRet )
921     {
922         // now remove the object from the former container
923         bRet = sal_False;
924         EmbeddedObjectContainerNameMap::iterator aIt = rSrc.pImpl->maObjectContainer.begin();
925         while ( aIt != rSrc.pImpl->maObjectContainer.end() )
926         {
927             if ( (*aIt).second == xObj )
928             {
929                 rSrc.pImpl->maObjectContainer.erase( aIt );
930                 bRet = sal_True;
931                 break;
932             }
933 
934             aIt++;
935         }
936 
937         OSL_ENSURE( bRet, "Object not found for removal!" );
938         if ( xPersist.is() )
939         {
940             // now it's time to remove the storage from the container storage
941             try
942             {
943                 if ( xPersist.is() )
944                     rSrc.pImpl->mxStorage->removeElement( aName );
945             }
946             catch ( uno::Exception& )
947             {
948                 OSL_ENSURE( sal_False, "Failed to remove object from storage!" );
949                 bRet = sal_False;
950             }
951         }
952 
953         // rSrc.RemoveGraphicStream( aName );
954     }
955 
956     return bRet;
957 }
958 
959 //sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const ::rtl::OUString& rName, sal_Bool bClose )
960 // #i119941, bKeepToTempStorage: use to specify whether store the removed object to temporary storage+
961 sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const ::rtl::OUString& rName, sal_Bool bClose, sal_Bool bKeepToTempStorage )
962 {
963     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Name )" );
964 
965     uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( rName );
966     if ( xObj.is() )
967         //return RemoveEmbeddedObject( xObj, bClose );
968         return RemoveEmbeddedObject( xObj, bClose, bKeepToTempStorage );
969     else
970         return sal_False;
971 }
972 
973 sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( const ::rtl::OUString& rName, EmbeddedObjectContainer& rCnt )
974 {
975     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Name )" );
976 
977     // find object entry
978     EmbeddedObjectContainerNameMap::iterator aIt2 = rCnt.pImpl->maObjectContainer.find( rName );
979     OSL_ENSURE( aIt2 == rCnt.pImpl->maObjectContainer.end(), "Object does already exist in target container!" );
980 
981     if ( aIt2 != rCnt.pImpl->maObjectContainer.end() )
982         return sal_False;
983 
984     uno::Reference < embed::XEmbeddedObject > xObj;
985     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
986     if ( aIt != pImpl->maObjectContainer.end() )
987     {
988         xObj = (*aIt).second;
989         try
990         {
991             if ( xObj.is() )
992             {
993                 // move object
994                 ::rtl::OUString aName( rName );
995                 rCnt.InsertEmbeddedObject( xObj, aName );
996                 pImpl->maObjectContainer.erase( aIt );
997                 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
998                 if ( xPersist.is() )
999                     pImpl->mxStorage->removeElement( rName );
1000             }
1001             else
1002             {
1003                 // copy storages; object *must* have persistence!
1004                 uno::Reference < embed::XStorage > xOld = pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READ );
1005                 uno::Reference < embed::XStorage > xNew = rCnt.pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READWRITE );
1006                 xOld->copyToStorage( xNew );
1007             }
1008 
1009             rCnt.TryToCopyGraphReplacement( *this, rName, rName );
1010             // RemoveGraphicStream( rName );
1011 
1012             return sal_True;
1013         }
1014         catch ( uno::Exception& )
1015         {
1016             OSL_ENSURE(0,"Could not move object!");
1017             return sal_False;
1018         }
1019 
1020     }
1021     else
1022         OSL_ENSURE(0,"Unknown object!");
1023     return sal_False;
1024 }
1025 
1026 //sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Bool bClose )
1027 // #i119941, bKeepToTempStorage: use to specify whether store the removed object to temporary storage+
1028 sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Bool bClose, sal_Bool bKeepToTempStorage )
1029 {
1030     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Object )" );
1031 
1032     uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1033     ::rtl::OUString aName;
1034     if ( xPersist.is() )
1035         aName = xPersist->getEntryName();
1036 
1037 #if OSL_DEBUG_LEVEL > 1
1038     uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
1039     uno::Reference < embed::XLinkageSupport > xLink( xPersist, uno::UNO_QUERY );
1040     sal_Bool bIsNotEmbedded = !xPersist.is() || xLink.is() && xLink->isLink();
1041 
1042     // if the object has a persistance and the object is not a link than it must have persistence entry in the storage
1043     OSL_ENSURE( bIsNotEmbedded || xAccess->hasByName(aName), "Removing element not present in storage!" );
1044 #endif
1045 
1046     // try to close it if permitted
1047     if ( bClose )
1048     {
1049         uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
1050         try
1051         {
1052             xClose->close( sal_True );
1053         }
1054         catch ( util::CloseVetoException& )
1055         {
1056             bClose = sal_False;
1057         }
1058     }
1059 
1060     if ( !bClose )
1061     {
1062         // somebody still needs the object, so we must assign a temporary persistence
1063         try
1064         {
1065         //    if ( xPersist.is() )
1066              if ( xPersist.is() && bKeepToTempStorage ) // #i119941
1067             {
1068                 /*
1069                 //TODO/LATER: needs storage handling!  Why not letting the object do it?!
1070                 if ( !pImpl->mxTempStorage.is() )
1071                     pImpl->mxTempStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
1072                 uno::Sequence < beans::PropertyValue > aSeq;
1073 
1074                 ::rtl::OUString aTmpPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
1075                 aTmpPersistName += ::rtl::OUString::valueOf( (sal_Int32) pImpl->maTempObjectContainer.size() );
1076 
1077                 xPersist->storeAsEntry( pImpl->mxTempStorage, aTmpPersistName, aSeq, aSeq );
1078                 xPersist->saveCompleted( sal_True );
1079 
1080                 pImpl->maTempObjectContainer[ aTmpPersistName ] = uno::Reference < embed::XEmbeddedObject >();
1081                 */
1082 
1083                 if ( !pImpl->mpTempObjectContainer )
1084                 {
1085                     pImpl->mpTempObjectContainer = new EmbeddedObjectContainer();
1086                     try
1087                     {
1088                         // TODO/LATER: in future probably the temporary container will have two storages ( of two formats )
1089                         //             the media type will be provided with object insertion
1090                         ::rtl::OUString aOrigStorMediaType;
1091                         uno::Reference< beans::XPropertySet > xStorProps( pImpl->mxStorage, uno::UNO_QUERY_THROW );
1092                         static const ::rtl::OUString s_sMediaType(RTL_CONSTASCII_USTRINGPARAM("MediaType"));
1093                         xStorProps->getPropertyValue( s_sMediaType ) >>= aOrigStorMediaType;
1094 
1095                         OSL_ENSURE( !aOrigStorMediaType.isEmpty(), "No valuable media type in the storage!\n" );
1096 
1097                         uno::Reference< beans::XPropertySet > xTargetStorProps(
1098                                                                     pImpl->mpTempObjectContainer->pImpl->mxStorage,
1099                                                                     uno::UNO_QUERY_THROW );
1100                         xTargetStorProps->setPropertyValue( s_sMediaType,uno::makeAny( aOrigStorMediaType ) );
1101                     }
1102                     catch( uno::Exception& )
1103                     {
1104                         OSL_ENSURE( sal_False, "Can not set the new media type to a storage!\n" );
1105                     }
1106                 }
1107 
1108                 ::rtl::OUString aTempName, aMediaType;
1109                 pImpl->mpTempObjectContainer->InsertEmbeddedObject( xObj, aTempName );
1110 
1111                 uno::Reference < io::XInputStream > xStream = GetGraphicStream( xObj, &aMediaType );
1112                 if ( xStream.is() )
1113                     pImpl->mpTempObjectContainer->InsertGraphicStream( xStream, aTempName, aMediaType );
1114 
1115                 // object is stored, so at least it can be set to loaded state
1116                 xObj->changeState( embed::EmbedStates::LOADED );
1117             }
1118             else
1119                 // objects without persistence need to stay in running state if they shall not be closed
1120                 xObj->changeState( embed::EmbedStates::RUNNING );
1121         }
1122         catch ( uno::Exception& )
1123         {
1124             return sal_False;
1125         }
1126     }
1127 
1128     sal_Bool bFound = sal_False;
1129     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
1130     while ( aIt != pImpl->maObjectContainer.end() )
1131     {
1132         if ( (*aIt).second == xObj )
1133         {
1134             pImpl->maObjectContainer.erase( aIt );
1135             bFound = sal_True;
1136             uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
1137             if ( xChild.is() )
1138                 xChild->setParent( uno::Reference < uno::XInterface >() );
1139             break;
1140         }
1141 
1142         aIt++;
1143     }
1144 
1145     OSL_ENSURE( bFound, "Object not found for removal!" );
1146    // if ( xPersist.is() )
1147     if ( xPersist.is() && bKeepToTempStorage )  // #i119941
1148     {
1149         // remove replacement image (if there is one)
1150         RemoveGraphicStream( aName );
1151 
1152         // now it's time to remove the storage from the container storage
1153         try
1154         {
1155 #if OSL_DEBUG_LEVEL > 1
1156             // if the object has a persistance and the object is not a link than it must have persistence entry in storage
1157             OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" );
1158 #endif
1159             if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) )
1160                 pImpl->mxStorage->removeElement( aName );
1161         }
1162         catch ( uno::Exception& )
1163         {
1164             OSL_ENSURE( sal_False, "Failed to remove object from storage!" );
1165             return sal_False;
1166         }
1167     }
1168 
1169     return sal_True;
1170 }
1171 
1172 sal_Bool EmbeddedObjectContainer::CloseEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj )
1173 {
1174     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CloseEmbeddedObject" );
1175 
1176     // disconnect the object from the container and close it if possible
1177 
1178     sal_Bool bFound = sal_False;
1179     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
1180     while ( aIt != pImpl->maObjectContainer.end() )
1181     {
1182         if ( (*aIt).second == xObj )
1183         {
1184             pImpl->maObjectContainer.erase( aIt );
1185             bFound = sal_True;
1186             break;
1187         }
1188 
1189         aIt++;
1190     }
1191 
1192     if ( bFound )
1193     {
1194         uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
1195         try
1196         {
1197             xClose->close( sal_True );
1198         }
1199         catch ( uno::Exception& )
1200         {
1201             // it is no problem if the object is already closed
1202             // TODO/LATER: what if the object can not be closed?
1203         }
1204     }
1205 
1206     return bFound;
1207 }
1208 
1209 uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::rtl::OUString& aName, rtl::OUString* pMediaType )
1210 {
1211     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Name )" );
1212 
1213     uno::Reference < io::XInputStream > xStream;
1214 
1215     OSL_ENSURE( !aName.isEmpty(), "Retrieving graphic for unknown object!" );
1216     if ( !aName.isEmpty() )
1217     {
1218         try
1219         {
1220             uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
1221             uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( aName, embed::ElementModes::READ );
1222             xStream = xGraphicStream->getInputStream();
1223             if ( pMediaType )
1224             {
1225                 uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
1226                 if ( xSet.is() )
1227                 {
1228                     uno::Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("MediaType") );
1229                     aAny >>= *pMediaType;
1230                 }
1231             }
1232         }
1233         catch ( uno::Exception& )
1234         {
1235         }
1236     }
1237 
1238     return xStream;
1239 }
1240 
1241 uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, rtl::OUString* pMediaType )
1242 {
1243     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Object )" );
1244 
1245     // get the object name
1246     ::rtl::OUString aName;
1247     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
1248     while ( aIt != pImpl->maObjectContainer.end() )
1249     {
1250         if ( (*aIt).second == xObj )
1251         {
1252             aName = (*aIt).first;
1253             break;
1254         }
1255 
1256         aIt++;
1257     }
1258 
1259     // try to load it from the container storage
1260     return GetGraphicStream( aName, pMediaType );
1261 }
1262 
1263 sal_Bool EmbeddedObjectContainer::InsertGraphicStream( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const ::rtl::OUString& rObjectName, const rtl::OUString& rMediaType )
1264 {
1265     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStream" );
1266 
1267     try
1268     {
1269         uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
1270 
1271         // store it into the subfolder
1272         uno::Reference < io::XOutputStream > xOutStream;
1273         uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( rObjectName,
1274                 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
1275         xOutStream = xGraphicStream->getOutputStream();
1276         ::comphelper::OStorageHelper::CopyInputToOutput( rStream, xOutStream );
1277         xOutStream->flush();
1278 
1279         uno::Reference< beans::XPropertySet > xPropSet( xGraphicStream, uno::UNO_QUERY );
1280         if ( !xPropSet.is() )
1281             throw uno::RuntimeException();
1282 
1283         xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ),
1284                                     uno::makeAny( (sal_Bool)sal_True ) );
1285         uno::Any aAny;
1286         aAny <<= rMediaType;
1287         xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii("MediaType"), aAny );
1288 
1289         xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "Compressed" ),
1290                                     uno::makeAny( (sal_Bool)sal_True ) );
1291     }
1292     catch( uno::Exception& )
1293     {
1294         return sal_False;
1295     }
1296 
1297     return sal_True;
1298 }
1299 
1300 sal_Bool EmbeddedObjectContainer::InsertGraphicStreamDirectly( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const ::rtl::OUString& rObjectName, const rtl::OUString& rMediaType )
1301 {
1302     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStreamDirectly" );
1303 
1304     try
1305     {
1306         uno::Reference < embed::XStorage > xReplacement = pImpl->GetReplacements();
1307         uno::Reference < embed::XOptimizedStorage > xOptRepl( xReplacement, uno::UNO_QUERY_THROW );
1308 
1309         // store it into the subfolder
1310         uno::Sequence< beans::PropertyValue > aProps( 3 );
1311         aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
1312         aProps[0].Value <<= rMediaType;
1313         aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" ) );
1314         aProps[1].Value <<= (sal_Bool)sal_True;
1315         aProps[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
1316         aProps[2].Value <<= (sal_Bool)sal_True;
1317 
1318         if ( xReplacement->hasByName( rObjectName ) )
1319             xReplacement->removeElement( rObjectName );
1320 
1321         xOptRepl->insertStreamElementDirect( rObjectName, rStream, aProps );
1322     }
1323     catch( uno::Exception& )
1324     {
1325         return sal_False;
1326     }
1327 
1328     return sal_True;
1329 }
1330 
1331 
1332 sal_Bool EmbeddedObjectContainer::RemoveGraphicStream( const ::rtl::OUString& rObjectName )
1333 {
1334     RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveGraphicStream" );
1335 
1336     try
1337     {
1338         uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
1339         xReplacements->removeElement( rObjectName );
1340     }
1341     catch( uno::Exception& )
1342     {
1343         return sal_False;
1344     }
1345 
1346     return sal_True;
1347 }
1348 namespace {
1349     void InsertStreamIntoPicturesStorage_Impl( const uno::Reference< embed::XStorage >& xDocStor,
1350                                             const uno::Reference< io::XInputStream >& xInStream,
1351                                             const ::rtl::OUString& aStreamName )
1352     {
1353         OSL_ENSURE( !aStreamName.isEmpty() && xInStream.is() && xDocStor.is(), "Misuse of the method!\n" );
1354 
1355         try
1356         {
1357             uno::Reference< embed::XStorage > xPictures = xDocStor->openStorageElement(
1358                                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pictures" ) ),
1359                                         embed::ElementModes::READWRITE );
1360             uno::Reference< io::XStream > xObjReplStr = xPictures->openStreamElement(
1361                                         aStreamName,
1362                                         embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
1363             uno::Reference< io::XOutputStream > xOutStream(
1364                                         xObjReplStr->getInputStream(), uno::UNO_QUERY_THROW );
1365 
1366             ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xOutStream );
1367             xOutStream->closeOutput();
1368 
1369             uno::Reference< embed::XTransactedObject > xTransact( xPictures, uno::UNO_QUERY );
1370             if ( xTransact.is() )
1371                 xTransact->commit();
1372         }
1373         catch( uno::Exception& )
1374         {
1375             OSL_ENSURE( sal_False, "The pictures storage is not available!\n" );
1376         }
1377     }
1378 
1379 }
1380 // -----------------------------------------------------------------------------
1381 sal_Bool EmbeddedObjectContainer::StoreAsChildren(sal_Bool _bOasisFormat,sal_Bool _bCreateEmbedded,const uno::Reference < embed::XStorage >& _xStorage)
1382 {
1383     sal_Bool bResult = sal_False;
1384     try
1385     {
1386         comphelper::EmbeddedObjectContainer aCnt( _xStorage );
1387         const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames();
1388         const ::rtl::OUString* pIter = aNames.getConstArray();
1389         const ::rtl::OUString* pEnd   = pIter + aNames.getLength();
1390         for(;pIter != pEnd;++pIter)
1391         {
1392             uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
1393             OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
1394             if ( xObj.is() )
1395             {
1396                 sal_Bool bSwitchBackToLoaded = sal_False;
1397                 uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY );
1398 
1399                 uno::Reference < io::XInputStream > xStream;
1400                 ::rtl::OUString aMediaType;
1401 
1402                 sal_Int32 nCurState = xObj->getCurrentState();
1403                 if ( nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING )
1404                 {
1405                     // means that the object is not active
1406                     // copy replacement image from old to new container
1407                     xStream = GetGraphicStream( xObj, &aMediaType );
1408                 }
1409 
1410                 if ( !xStream.is() && getUserAllowsLinkUpdate() )
1411                 {
1412                     // the image must be regenerated
1413                     // TODO/LATER: another aspect could be used
1414                     if ( xObj->getCurrentState() == embed::EmbedStates::LOADED )
1415                             bSwitchBackToLoaded = sal_True;
1416 
1417                     xStream = GetGraphicReplacementStream(
1418                                                             embed::Aspects::MSOLE_CONTENT,
1419                                                             xObj,
1420                                                             &aMediaType );
1421                 }
1422 
1423                 if ( _bOasisFormat || (xLink.is() && xLink->isLink()) )
1424                 {
1425                     if ( xStream.is() )
1426                     {
1427                         if ( _bOasisFormat )
1428                         {
1429                             // if it is an embedded object or the optimized inserting fails the normal inserting should be done
1430                             if ( _bCreateEmbedded
1431                                 || !aCnt.InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) )
1432                                 aCnt.InsertGraphicStream( xStream, *pIter, aMediaType );
1433                         }
1434                         else
1435                         {
1436                             // it is a linked object exported into SO7 format
1437                             InsertStreamIntoPicturesStorage_Impl( _xStorage, xStream, *pIter );
1438                         }
1439                     }
1440                 }
1441 
1442                 uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1443                 if ( xPersist.is() )
1444                 {
1445                     uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 );
1446                     aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StoreVisualReplacement" ) );
1447                     aArgs[0].Value <<= (sal_Bool)( !_bOasisFormat );
1448 
1449                     // if it is an embedded object or the optimized inserting fails the normal inserting should be done
1450                     aArgs[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanTryOptimization" ) );
1451                     aArgs[1].Value <<= !_bCreateEmbedded;
1452                     if ( !_bOasisFormat )
1453                     {
1454                         // if object has no cached replacement it will use this one
1455                         aArgs[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VisualReplacement" ) );
1456                         aArgs[2].Value <<= xStream;
1457                     }
1458 
1459                     xPersist->storeAsEntry( _xStorage,
1460                                             xPersist->getEntryName(),
1461                                             uno::Sequence< beans::PropertyValue >(),
1462                                             aArgs );
1463                 }
1464 
1465                 if ( bSwitchBackToLoaded )
1466                     // switch back to loaded state; that way we have a minimum cache confusion
1467                     xObj->changeState( embed::EmbedStates::LOADED );
1468             }
1469         }
1470 
1471         bResult = aCnt.CommitImageSubStorage();
1472 
1473     }
1474     catch ( uno::Exception& )
1475     {
1476         // TODO/LATER: error handling
1477         bResult = sal_False;
1478     }
1479 
1480     // the old SO6 format does not store graphical replacements
1481     if ( !_bOasisFormat && bResult )
1482     {
1483         try
1484         {
1485             // the substorage still can not be locked by the embedded object conteiner
1486             ::rtl::OUString aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
1487             if ( _xStorage->hasByName( aObjReplElement ) && _xStorage->isStorageElement( aObjReplElement ) )
1488                 _xStorage->removeElement( aObjReplElement );
1489         }
1490         catch ( uno::Exception& )
1491         {
1492             // TODO/LATER: error handling;
1493             bResult = sal_False;
1494         }
1495     }
1496     return bResult;
1497 }
1498 // -----------------------------------------------------------------------------
1499 sal_Bool EmbeddedObjectContainer::StoreChildren(sal_Bool _bOasisFormat,sal_Bool _bObjectsOnly)
1500 {
1501     sal_Bool bResult = sal_True;
1502     const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames();
1503     const ::rtl::OUString* pIter = aNames.getConstArray();
1504     const ::rtl::OUString* pEnd   = pIter + aNames.getLength();
1505     for(;pIter != pEnd;++pIter)
1506     {
1507         uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
1508         OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
1509         if ( xObj.is() )
1510         {
1511             sal_Int32 nCurState = xObj->getCurrentState();
1512             if ( _bOasisFormat && nCurState != embed::EmbedStates::LOADED && nCurState != embed::EmbedStates::RUNNING )
1513             {
1514                 // means that the object is active
1515                 // the image must be regenerated
1516                 ::rtl::OUString aMediaType;
1517 
1518                 // TODO/LATER: another aspect could be used
1519                 uno::Reference < io::XInputStream > xStream =
1520                             GetGraphicReplacementStream(
1521                                                         embed::Aspects::MSOLE_CONTENT,
1522                                                         xObj,
1523                                                         &aMediaType );
1524                 if ( xStream.is() )
1525                 {
1526                     if ( !InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) )
1527                         InsertGraphicStream( xStream, *pIter, aMediaType );
1528                 }
1529             }
1530 
1531             // TODO/LATER: currently the object by default does not cache replacement image
1532             // that means that if somebody loads SO7 document and store its objects using
1533             // this method the images might be lost.
1534             // Currently this method is only used on storing to alien formats, that means
1535             // that SO7 documents storing does not use it, and all other filters are
1536             // based on OASIS format. But if it changes the method must be fixed. The fix
1537             // must be done only on demand since it can affect performance.
1538 
1539             uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1540             if ( xPersist.is() )
1541             {
1542                 try
1543                 {
1544                     //TODO/LATER: only storing if changed!
1545                     //xPersist->storeOwn(); //commented, i120168
1546 
1547             // begin:all charts will be persited as xml format on disk when saving, which is time consuming.
1548                     // '_bObjectsOnly' mean we are storing to alien formats.
1549                     //  'isStorageElement' mean current object is NOT an MS OLE format. (may also include in future), i120168
1550                     if (_bObjectsOnly && (nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING)
1551                         && (pImpl->mxStorage->isStorageElement( *pIter ) ))
1552                     {
1553                         uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
1554                         if ( xModifiable.is() && xModifiable->isModified())
1555                         {
1556                             xPersist->storeOwn();
1557                         }
1558                         else
1559                         {
1560                             //do nothing.embeded model is not modified, no need to persist.
1561                         }
1562                     }
1563                     else //the embeded object is in active status, always store back it.
1564                     {
1565                         xPersist->storeOwn();
1566                     }
1567                     //end i120168
1568                 }
1569                 catch( uno::Exception& )
1570                 {
1571                     // TODO/LATER: error handling
1572                     bResult = sal_False;
1573                     break;
1574                 }
1575             }
1576 
1577             if ( !_bOasisFormat && !_bObjectsOnly )
1578             {
1579                 // copy replacement images for linked objects
1580                 try
1581                 {
1582                     uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY );
1583                     if ( xLink.is() && xLink->isLink() )
1584                     {
1585                         ::rtl::OUString aMediaType;
1586                         uno::Reference < io::XInputStream > xInStream = GetGraphicStream( xObj, &aMediaType );
1587                         if ( xInStream.is() )
1588                             InsertStreamIntoPicturesStorage_Impl( pImpl->mxStorage, xInStream, *pIter );
1589                     }
1590                 }
1591                 catch( uno::Exception& )
1592                 {
1593                 }
1594             }
1595         }
1596     }
1597 
1598     if ( bResult && _bOasisFormat )
1599         bResult = CommitImageSubStorage();
1600 
1601     if ( bResult && !_bObjectsOnly )
1602     {
1603         try
1604         {
1605             ReleaseImageSubStorage();
1606             ::rtl::OUString aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
1607             if ( !_bOasisFormat && pImpl->mxStorage->hasByName( aObjReplElement ) && pImpl->mxStorage->isStorageElement( aObjReplElement ) )
1608                 pImpl->mxStorage->removeElement( aObjReplElement );
1609         }
1610         catch( uno::Exception& )
1611         {
1612             // TODO/LATER: error handling
1613             bResult = sal_False;
1614         }
1615     }
1616     return bResult;
1617 }
1618 // -----------------------------------------------------------------------------
1619 uno::Reference< io::XInputStream > EmbeddedObjectContainer::GetGraphicReplacementStream(
1620                                                                 sal_Int64 nViewAspect,
1621                                                                 const uno::Reference< embed::XEmbeddedObject >& xObj,
1622                                                                 ::rtl::OUString* pMediaType )
1623 {
1624     uno::Reference< io::XInputStream > xInStream;
1625     if ( xObj.is() )
1626     {
1627         try
1628         {
1629             // retrieving of the visual representation can switch object to running state
1630             embed::VisualRepresentation aRep = xObj->getPreferredVisualRepresentation( nViewAspect );
1631             if ( pMediaType )
1632                 *pMediaType = aRep.Flavor.MimeType;
1633 
1634             uno::Sequence < sal_Int8 > aSeq;
1635             aRep.Data >>= aSeq;
1636             xInStream = new ::comphelper::SequenceInputStream( aSeq );
1637         }
1638         catch ( uno::Exception& )
1639         {
1640         }
1641     }
1642 
1643     return xInStream;
1644 }
1645 // -----------------------------------------------------------------------------
1646 sal_Bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed::XStorage >& _xStorage,bool _bClearModifedFlag)
1647 {
1648     sal_Bool bError = sal_False;
1649     const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames();
1650     const ::rtl::OUString* pIter = aNames.getConstArray();
1651     const ::rtl::OUString* pEnd   = pIter + aNames.getLength();
1652     for(;pIter != pEnd;++pIter)
1653     {
1654         uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
1655         OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
1656         if ( xObj.is() )
1657         {
1658             uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1659             if ( xPersist.is() )
1660             {
1661                 try
1662                 {
1663                     xPersist->setPersistentEntry( _xStorage,
1664                                                 *pIter,
1665                                                 embed::EntryInitModes::NO_INIT,
1666                                                 uno::Sequence< beans::PropertyValue >(),
1667                                                 uno::Sequence< beans::PropertyValue >() );
1668 
1669                 }
1670                 catch( uno::Exception& )
1671                 {
1672                     // TODO/LATER: error handling
1673                     bError = sal_True;
1674                     break;
1675                 }
1676             }
1677             if ( _bClearModifedFlag )
1678             {
1679                 // if this method is used as part of SaveCompleted the object must stay unmodified after execution
1680                 try
1681                 {
1682                     uno::Reference< util::XModifiable > xModif( xObj->getComponent(), uno::UNO_QUERY_THROW );
1683                     if ( xModif->isModified() )
1684                         xModif->setModified( sal_False );
1685                 }
1686                 catch( uno::Exception& )
1687                 {
1688                 }
1689             }
1690         }
1691     }
1692     return bError;
1693 }
1694 
1695 bool EmbeddedObjectContainer::getUserAllowsLinkUpdate() const
1696 {
1697     return pImpl->mbUserAllowsLinkUpdate;
1698 }
1699 
1700 void EmbeddedObjectContainer::setUserAllowsLinkUpdate(bool bNew)
1701 {
1702     if(pImpl->mbUserAllowsLinkUpdate != bNew)
1703     {
1704         pImpl->mbUserAllowsLinkUpdate = bNew;
1705     }
1706 }
1707 
1708 }
1709