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