1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 #include <com/sun/star/container/XChild.hpp>
31 #include <com/sun/star/container/XNameAccess.hpp>
32 #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
33 #include <com/sun/star/embed/XLinkCreator.hpp>
34 #include <com/sun/star/embed/XEmbedPersist.hpp>
35 #include <com/sun/star/embed/XLinkageSupport.hpp>
36 #include <com/sun/star/embed/XTransactedObject.hpp>
37 #include <com/sun/star/embed/XOptimizedStorage.hpp>
38 #include <com/sun/star/embed/EntryInitModes.hpp>
39 #include <com/sun/star/util/XCloseable.hpp>
40 #include <com/sun/star/util/XModifiable.hpp>
41 #include <com/sun/star/embed/EmbedStates.hpp>
42 #include <com/sun/star/datatransfer/XTransferable.hpp>
43 #include <com/sun/star/beans/XPropertySetInfo.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/embed/Aspects.hpp>
46 #include <com/sun/star/embed/EmbedMisc.hpp>
47 
48 #include <comphelper/seqstream.hxx>
49 #include <comphelper/processfactory.hxx>
50 #include <comphelper/storagehelper.hxx>
51 #include <comphelper/embeddedobjectcontainer.hxx>
52 #include <comphelper/sequence.hxx>
53 #include <cppuhelper/weakref.hxx>
54 #include <hash_map>
55 #include <algorithm>
56 
57 #include <rtl/logfile.hxx>
58 
59 using namespace ::com::sun::star;
60 
61 namespace comphelper
62 {
63 
64 struct hashObjectName_Impl
65 {
66 	size_t operator()(const ::rtl::OUString Str) const
67 	{
68 		return (size_t)Str.hashCode();
69 	}
70 };
71 
72 struct eqObjectName_Impl
73 {
74 	sal_Bool operator()(const ::rtl::OUString Str1, const ::rtl::OUString Str2) const
75 	{
76 		return ( Str1 == Str2 );
77 	}
78 };
79 
80 typedef std::hash_map
81 <
82 	::rtl::OUString,
83     ::com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >,
84     hashObjectName_Impl,
85     eqObjectName_Impl
86 >
87 EmbeddedObjectContainerNameMap;
88 
89 struct EmbedImpl
90 {
91     // TODO/LATER: remove objects from temp. Container storage when object is disposed
92     EmbeddedObjectContainerNameMap maObjectContainer;
93     uno::Reference < embed::XStorage > mxStorage;
94     EmbeddedObjectContainer* mpTempObjectContainer;
95     uno::Reference < embed::XStorage > mxImageStorage;
96     uno::WeakReference < uno::XInterface > m_xModel;
97     //EmbeddedObjectContainerNameMap maTempObjectContainer;
98     //uno::Reference < embed::XStorage > mxTempStorage;
99     sal_Bool bOwnsStorage;
100 
101     const uno::Reference < embed::XStorage >& GetReplacements();
102 };
103 
104 const uno::Reference < embed::XStorage >& EmbedImpl::GetReplacements()
105 {
106     if ( !mxImageStorage.is() )
107     {
108         try
109         {
110             mxImageStorage = mxStorage->openStorageElement(
111                 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READWRITE );
112         }
113         catch ( uno::Exception& )
114         {
115             mxImageStorage = mxStorage->openStorageElement(
116                 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READ );
117         }
118     }
119 
120     if ( !mxImageStorage.is() )
121         throw io::IOException();
122 
123     return mxImageStorage;
124 }
125 
126 EmbeddedObjectContainer::EmbeddedObjectContainer()
127 {
128     pImpl = new EmbedImpl;
129     pImpl->mxStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
130     pImpl->bOwnsStorage = sal_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->bOwnsStorage = sal_False;
139     pImpl->mpTempObjectContainer = 0;
140 }
141 
142 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor, const uno::Reference < uno::XInterface >& xModel )
143 {
144     pImpl = new EmbedImpl;
145     pImpl->mxStorage = rStor;
146     pImpl->bOwnsStorage = sal_False;
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->bOwnsStorage )
156         pImpl->mxStorage->dispose();
157 
158     pImpl->mxStorage = rStor;
159     pImpl->bOwnsStorage = sal_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->bOwnsStorage )
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.getLength(), "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.getLength() )
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.getLength(), "Added object doesn't have a name!");
449     uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
450     uno::Reference < embed::XEmbedPersist > xEmb( xObj, uno::UNO_QUERY );
451 	uno::Reference < embed::XLinkageSupport > xLink( xEmb, uno::UNO_QUERY );
452 	// if the object has a persistance and the object is not a link than it must have persistence entry in the storage
453     OSL_ENSURE( !( xEmb.is() && ( !xLink.is() || !xLink->isLink() ) ) || xAccess->hasByName(rName),
454 					"Added element not in storage!" );
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.getLength() )
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 optimisation, don't store immediately
532                 //xPersist->setPersistentEntry( pImpl->mxStorage, rName, embed::EntryInitModes::ENTRY_NO_INIT, aSeq, aSeq );
533                 xPersist->storeAsEntry( pImpl->mxStorage, rName, aSeq, aSeq );
534                 xPersist->saveCompleted( sal_True );
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.getLength() )
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.getLength() )
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.getLength() )
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.getLength() && aTargetName.getLength() )
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.getLength() )
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.getLength() )
756         rName = CreateUniqueObjectName();
757 
758 	// objects without persistance 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.getLength() )
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 tranfer all the properties
806         			uno::Reference < embed::XEmbedObjectCreator > xCreator(
807 						::comphelper::getProcessServiceFactory()->createInstance(
808                 			::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
809 						uno::UNO_QUERY_THROW );
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 persistance!\n" );
871 
872 	if ( xResult.is() )
873 	{
874 		// the object is successfully copied, try to copy graphical replacement
875 		if ( aOrigName.getLength() )
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 {
959 	RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Name )" );
960 
961     uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( rName );
962     if ( xObj.is() )
963         return RemoveEmbeddedObject( xObj, bClose );
964     else
965         return sal_False;
966 }
967 
968 sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( const ::rtl::OUString& rName, EmbeddedObjectContainer& rCnt )
969 {
970 	RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Name )" );
971 
972     // find object entry
973     EmbeddedObjectContainerNameMap::iterator aIt2 = rCnt.pImpl->maObjectContainer.find( rName );
974     OSL_ENSURE( aIt2 == rCnt.pImpl->maObjectContainer.end(), "Object does already exist in target container!" );
975 
976     if ( aIt2 != rCnt.pImpl->maObjectContainer.end() )
977         return sal_False;
978 
979     uno::Reference < embed::XEmbeddedObject > xObj;
980     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
981     if ( aIt != pImpl->maObjectContainer.end() )
982     {
983         xObj = (*aIt).second;
984         try
985         {
986             if ( xObj.is() )
987             {
988                 // move object
989                 ::rtl::OUString aName( rName );
990                 rCnt.InsertEmbeddedObject( xObj, aName );
991                 pImpl->maObjectContainer.erase( aIt );
992                 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
993                 if ( xPersist.is() )
994                     pImpl->mxStorage->removeElement( rName );
995             }
996             else
997             {
998                 // copy storages; object *must* have persistence!
999                 uno::Reference < embed::XStorage > xOld = pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READ );
1000                 uno::Reference < embed::XStorage > xNew = rCnt.pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READWRITE );
1001                 xOld->copyToStorage( xNew );
1002             }
1003 
1004 			rCnt.TryToCopyGraphReplacement( *this, rName, rName );
1005 			// RemoveGraphicStream( rName );
1006 
1007             return sal_True;
1008         }
1009         catch ( uno::Exception& )
1010         {
1011             OSL_ENSURE(0,"Could not move object!");
1012             return sal_False;
1013         }
1014 
1015     }
1016     else
1017         OSL_ENSURE(0,"Unknown object!");
1018     return sal_False;
1019 }
1020 
1021 sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Bool bClose )
1022 {
1023 	RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Object )" );
1024 
1025     uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1026     ::rtl::OUString aName;
1027     if ( xPersist.is() )
1028         aName = xPersist->getEntryName();
1029 
1030 #if OSL_DEBUG_LEVEL > 1
1031     uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
1032 	uno::Reference < embed::XLinkageSupport > xLink( xPersist, uno::UNO_QUERY );
1033     sal_Bool bIsNotEmbedded = !xPersist.is() || xLink.is() && xLink->isLink();
1034 
1035     // if the object has a persistance and the object is not a link than it must have persistence entry in the storage
1036     OSL_ENSURE( bIsNotEmbedded || xAccess->hasByName(aName), "Removing element not present in storage!" );
1037 #endif
1038 
1039     // try to close it if permitted
1040     if ( bClose )
1041     {
1042         uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
1043         try
1044         {
1045             xClose->close( sal_True );
1046         }
1047         catch ( util::CloseVetoException& )
1048         {
1049             bClose = sal_False;
1050         }
1051     }
1052 
1053     if ( !bClose )
1054     {
1055         // somebody still needs the object, so we must assign a temporary persistence
1056         try
1057         {
1058             if ( xPersist.is() )
1059             {
1060                 /*
1061                 //TODO/LATER: needs storage handling!  Why not letting the object do it?!
1062                 if ( !pImpl->mxTempStorage.is() )
1063                     pImpl->mxTempStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
1064                 uno::Sequence < beans::PropertyValue > aSeq;
1065 
1066                 ::rtl::OUString aTmpPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
1067                 aTmpPersistName += ::rtl::OUString::valueOf( (sal_Int32) pImpl->maTempObjectContainer.size() );
1068 
1069                 xPersist->storeAsEntry( pImpl->mxTempStorage, aTmpPersistName, aSeq, aSeq );
1070                 xPersist->saveCompleted( sal_True );
1071 
1072                 pImpl->maTempObjectContainer[ aTmpPersistName ] = uno::Reference < embed::XEmbeddedObject >();
1073                 */
1074 
1075                 if ( !pImpl->mpTempObjectContainer )
1076 				{
1077                     pImpl->mpTempObjectContainer = new EmbeddedObjectContainer();
1078 					try
1079 					{
1080 						// TODO/LATER: in future probably the temporary container will have two storages ( of two formats )
1081 						//             the media type will be provided with object insertion
1082 						::rtl::OUString aOrigStorMediaType;
1083 						uno::Reference< beans::XPropertySet > xStorProps( pImpl->mxStorage, uno::UNO_QUERY_THROW );
1084                         static const ::rtl::OUString s_sMediaType(RTL_CONSTASCII_USTRINGPARAM("MediaType"));
1085 						xStorProps->getPropertyValue( s_sMediaType ) >>= aOrigStorMediaType;
1086 
1087 						OSL_ENSURE( aOrigStorMediaType.getLength(), "No valuable media type in the storage!\n" );
1088 
1089 						uno::Reference< beans::XPropertySet > xTargetStorProps(
1090 																	pImpl->mpTempObjectContainer->pImpl->mxStorage,
1091 																	uno::UNO_QUERY_THROW );
1092 						xTargetStorProps->setPropertyValue( s_sMediaType,uno::makeAny( aOrigStorMediaType ) );
1093 					}
1094 					catch( uno::Exception& )
1095 					{
1096 						OSL_ENSURE( sal_False, "Can not set the new media type to a storage!\n" );
1097 					}
1098 				}
1099 
1100                 ::rtl::OUString aTempName, aMediaType;
1101                 pImpl->mpTempObjectContainer->InsertEmbeddedObject( xObj, aTempName );
1102 
1103                 uno::Reference < io::XInputStream > xStream = GetGraphicStream( xObj, &aMediaType );
1104                 if ( xStream.is() )
1105                     pImpl->mpTempObjectContainer->InsertGraphicStream( xStream, aTempName, aMediaType );
1106 
1107                 // object is stored, so at least it can be set to loaded state
1108                 xObj->changeState( embed::EmbedStates::LOADED );
1109             }
1110             else
1111                 // objects without persistence need to stay in running state if they shall not be closed
1112                 xObj->changeState( embed::EmbedStates::RUNNING );
1113         }
1114         catch ( uno::Exception& )
1115         {
1116             return sal_False;
1117         }
1118     }
1119 
1120     sal_Bool bFound = sal_False;
1121     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
1122     while ( aIt != pImpl->maObjectContainer.end() )
1123     {
1124         if ( (*aIt).second == xObj )
1125         {
1126             pImpl->maObjectContainer.erase( aIt );
1127             bFound = sal_True;
1128             uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
1129             if ( xChild.is() )
1130                 xChild->setParent( uno::Reference < uno::XInterface >() );
1131             break;
1132         }
1133 
1134         aIt++;
1135     }
1136 
1137     OSL_ENSURE( bFound, "Object not found for removal!" );
1138     if ( xPersist.is() )
1139     {
1140         // remove replacement image (if there is one)
1141         RemoveGraphicStream( aName );
1142 
1143         // now it's time to remove the storage from the container storage
1144         try
1145         {
1146 #if OSL_DEBUG_LEVEL > 1
1147 			// if the object has a persistance and the object is not a link than it must have persistence entry in storage
1148             OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" );
1149 #endif
1150             if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) )
1151                 pImpl->mxStorage->removeElement( aName );
1152         }
1153         catch ( uno::Exception& )
1154         {
1155             OSL_ENSURE( sal_False, "Failed to remove object from storage!" );
1156             return sal_False;
1157         }
1158     }
1159 
1160     return sal_True;
1161 }
1162 
1163 sal_Bool EmbeddedObjectContainer::CloseEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj )
1164 {
1165 	RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CloseEmbeddedObject" );
1166 
1167 	// disconnect the object from the container and close it if possible
1168 
1169     sal_Bool bFound = sal_False;
1170     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
1171     while ( aIt != pImpl->maObjectContainer.end() )
1172     {
1173         if ( (*aIt).second == xObj )
1174         {
1175             pImpl->maObjectContainer.erase( aIt );
1176             bFound = sal_True;
1177             break;
1178         }
1179 
1180         aIt++;
1181     }
1182 
1183 	if ( bFound )
1184 	{
1185 		uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
1186 		try
1187 		{
1188 			xClose->close( sal_True );
1189 		}
1190 		catch ( uno::Exception& )
1191 		{
1192 			// it is no problem if the object is already closed
1193 			// TODO/LATER: what if the object can not be closed?
1194 		}
1195 	}
1196 
1197 	return bFound;
1198 }
1199 
1200 uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::rtl::OUString& aName, rtl::OUString* pMediaType )
1201 {
1202 	RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Name )" );
1203 
1204     uno::Reference < io::XInputStream > xStream;
1205 
1206     OSL_ENSURE( aName.getLength(), "Retrieving graphic for unknown object!" );
1207 	if ( aName.getLength() )
1208 	{
1209     	try
1210     	{
1211         	uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
1212         	uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( aName, embed::ElementModes::READ );
1213         	xStream = xGraphicStream->getInputStream();
1214         	if ( pMediaType )
1215         	{
1216             	uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
1217             	if ( xSet.is() )
1218             	{
1219                 	uno::Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("MediaType") );
1220                 	aAny >>= *pMediaType;
1221             	}
1222         	}
1223     	}
1224     	catch ( uno::Exception& )
1225     	{
1226     	}
1227 	}
1228 
1229     return xStream;
1230 }
1231 
1232 uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, rtl::OUString* pMediaType )
1233 {
1234 	RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Object )" );
1235 
1236     // get the object name
1237     ::rtl::OUString aName;
1238     EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
1239     while ( aIt != pImpl->maObjectContainer.end() )
1240     {
1241         if ( (*aIt).second == xObj )
1242         {
1243             aName = (*aIt).first;
1244             break;
1245         }
1246 
1247         aIt++;
1248     }
1249 
1250     // try to load it from the container storage
1251 	return GetGraphicStream( aName, pMediaType );
1252 }
1253 
1254 sal_Bool EmbeddedObjectContainer::InsertGraphicStream( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const ::rtl::OUString& rObjectName, const rtl::OUString& rMediaType )
1255 {
1256 	RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStream" );
1257 
1258     try
1259     {
1260         uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
1261 
1262         // store it into the subfolder
1263         uno::Reference < io::XOutputStream > xOutStream;
1264         uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( rObjectName,
1265                 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
1266         xOutStream = xGraphicStream->getOutputStream();
1267         ::comphelper::OStorageHelper::CopyInputToOutput( rStream, xOutStream );
1268         xOutStream->flush();
1269 
1270 		uno::Reference< beans::XPropertySet > xPropSet( xGraphicStream, uno::UNO_QUERY );
1271 		if ( !xPropSet.is() )
1272 			throw uno::RuntimeException();
1273 
1274 		xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ),
1275 									uno::makeAny( (sal_Bool)sal_True ) );
1276         uno::Any aAny;
1277         aAny <<= rMediaType;
1278         xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii("MediaType"), aAny );
1279 
1280 		xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "Compressed" ),
1281 									uno::makeAny( (sal_Bool)sal_True ) );
1282     }
1283     catch( uno::Exception& )
1284     {
1285         return sal_False;
1286     }
1287 
1288     return sal_True;
1289 }
1290 
1291 sal_Bool EmbeddedObjectContainer::InsertGraphicStreamDirectly( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const ::rtl::OUString& rObjectName, const rtl::OUString& rMediaType )
1292 {
1293 	RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStreamDirectly" );
1294 
1295     try
1296     {
1297         uno::Reference < embed::XStorage > xReplacement = pImpl->GetReplacements();
1298         uno::Reference < embed::XOptimizedStorage > xOptRepl( xReplacement, uno::UNO_QUERY_THROW );
1299 
1300         // store it into the subfolder
1301 		uno::Sequence< beans::PropertyValue > aProps( 3 );
1302 		aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
1303 		aProps[0].Value <<= rMediaType;
1304 		aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" ) );
1305 		aProps[1].Value <<= (sal_Bool)sal_True;
1306 		aProps[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
1307 		aProps[2].Value <<= (sal_Bool)sal_True;
1308 
1309 		if ( xReplacement->hasByName( rObjectName ) )
1310 			xReplacement->removeElement( rObjectName );
1311 
1312 		xOptRepl->insertStreamElementDirect( rObjectName, rStream, aProps );
1313     }
1314     catch( uno::Exception& )
1315     {
1316         return sal_False;
1317     }
1318 
1319     return sal_True;
1320 }
1321 
1322 
1323 sal_Bool EmbeddedObjectContainer::RemoveGraphicStream( const ::rtl::OUString& rObjectName )
1324 {
1325 	RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveGraphicStream" );
1326 
1327     try
1328     {
1329         uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
1330         xReplacements->removeElement( rObjectName );
1331     }
1332     catch( uno::Exception& )
1333     {
1334         return sal_False;
1335     }
1336 
1337     return sal_True;
1338 }
1339 namespace {
1340     void InsertStreamIntoPicturesStorage_Impl( const uno::Reference< embed::XStorage >& xDocStor,
1341 											const uno::Reference< io::XInputStream >& xInStream,
1342 											const ::rtl::OUString& aStreamName )
1343     {
1344 	    OSL_ENSURE( aStreamName.getLength() && xInStream.is() && xDocStor.is(), "Misuse of the method!\n" );
1345 
1346 	    try
1347 	    {
1348 		    uno::Reference< embed::XStorage > xPictures = xDocStor->openStorageElement(
1349 									    ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pictures" ) ),
1350 									    embed::ElementModes::READWRITE );
1351 		    uno::Reference< io::XStream > xObjReplStr = xPictures->openStreamElement(
1352 									    aStreamName,
1353 									    embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
1354 		    uno::Reference< io::XOutputStream > xOutStream(
1355 									    xObjReplStr->getInputStream(), uno::UNO_QUERY_THROW );
1356 
1357 		    ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xOutStream );
1358 		    xOutStream->closeOutput();
1359 
1360 		    uno::Reference< embed::XTransactedObject > xTransact( xPictures, uno::UNO_QUERY );
1361 		    if ( xTransact.is() )
1362 			    xTransact->commit();
1363 	    }
1364 	    catch( uno::Exception& )
1365 	    {
1366 		    OSL_ENSURE( sal_False, "The pictures storage is not available!\n" );
1367 	    }
1368     }
1369 
1370 }
1371 // -----------------------------------------------------------------------------
1372 sal_Bool EmbeddedObjectContainer::StoreAsChildren(sal_Bool _bOasisFormat,sal_Bool _bCreateEmbedded,const uno::Reference < embed::XStorage >& _xStorage)
1373 {
1374     sal_Bool bResult = sal_False;
1375     try
1376     {
1377         comphelper::EmbeddedObjectContainer aCnt( _xStorage );
1378         const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames();
1379         const ::rtl::OUString* pIter = aNames.getConstArray();
1380         const ::rtl::OUString* pEnd	  = pIter + aNames.getLength();
1381         for(;pIter != pEnd;++pIter)
1382         {
1383             uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
1384             OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
1385             if ( xObj.is() )
1386             {
1387                 sal_Bool bSwitchBackToLoaded = sal_False;
1388                 uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY );
1389 
1390                 uno::Reference < io::XInputStream > xStream;
1391                 ::rtl::OUString aMediaType;
1392 
1393                 sal_Int32 nCurState = xObj->getCurrentState();
1394                 if ( nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING )
1395                 {
1396                     // means that the object is not active
1397                     // copy replacement image from old to new container
1398                     xStream = GetGraphicStream( xObj, &aMediaType );
1399                 }
1400 
1401                 if ( !xStream.is() )
1402                 {
1403                     // the image must be regenerated
1404                     // TODO/LATER: another aspect could be used
1405                     if ( xObj->getCurrentState() == embed::EmbedStates::LOADED )
1406                             bSwitchBackToLoaded = sal_True;
1407 
1408                     xStream = GetGraphicReplacementStream(
1409                                                             embed::Aspects::MSOLE_CONTENT,
1410                                                             xObj,
1411                                                             &aMediaType );
1412                 }
1413 
1414                 if ( _bOasisFormat || (xLink.is() && xLink->isLink()) )
1415                 {
1416                     if ( xStream.is() )
1417                     {
1418                         if ( _bOasisFormat )
1419 						{
1420 							// if it is an embedded object or the optimized inserting fails the normal inserting should be done
1421 							if ( _bCreateEmbedded
1422                                 || !aCnt.InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) )
1423                                 aCnt.InsertGraphicStream( xStream, *pIter, aMediaType );
1424 						}
1425                         else
1426                         {
1427                             // it is a linked object exported into SO7 format
1428                             InsertStreamIntoPicturesStorage_Impl( _xStorage, xStream, *pIter );
1429                         }
1430                     }
1431                 }
1432 
1433                 uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1434                 if ( xPersist.is() )
1435                 {
1436                     uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 );
1437                     aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StoreVisualReplacement" ) );
1438                     aArgs[0].Value <<= (sal_Bool)( !_bOasisFormat );
1439 
1440 					// if it is an embedded object or the optimized inserting fails the normal inserting should be done
1441                     aArgs[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanTryOptimization" ) );
1442                     aArgs[1].Value <<= !_bCreateEmbedded;
1443 					if ( !_bOasisFormat )
1444 					{
1445 						// if object has no cached replacement it will use this one
1446 	                    aArgs[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VisualReplacement" ) );
1447                         aArgs[2].Value <<= xStream;
1448 					}
1449 
1450                     xPersist->storeAsEntry( _xStorage,
1451                                             xPersist->getEntryName(),
1452                                             uno::Sequence< beans::PropertyValue >(),
1453                                             aArgs );
1454                 }
1455 
1456                 if ( bSwitchBackToLoaded )
1457                     // switch back to loaded state; that way we have a minimum cache confusion
1458                     xObj->changeState( embed::EmbedStates::LOADED );
1459             }
1460         }
1461 
1462 		bResult = aCnt.CommitImageSubStorage();
1463 
1464     }
1465     catch ( uno::Exception& )
1466     {
1467         // TODO/LATER: error handling
1468         bResult = sal_False;
1469     }
1470 
1471     // the old SO6 format does not store graphical replacements
1472     if ( !_bOasisFormat && bResult )
1473     {
1474         try
1475         {
1476             // the substorage still can not be locked by the embedded object conteiner
1477             ::rtl::OUString aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
1478             if ( _xStorage->hasByName( aObjReplElement ) && _xStorage->isStorageElement( aObjReplElement ) )
1479                 _xStorage->removeElement( aObjReplElement );
1480         }
1481         catch ( uno::Exception& )
1482         {
1483             // TODO/LATER: error handling;
1484             bResult = sal_False;
1485         }
1486     }
1487     return bResult;
1488 }
1489 // -----------------------------------------------------------------------------
1490 sal_Bool EmbeddedObjectContainer::StoreChildren(sal_Bool _bOasisFormat,sal_Bool _bObjectsOnly)
1491 {
1492     sal_Bool bResult = sal_True;
1493     const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames();
1494     const ::rtl::OUString* pIter = aNames.getConstArray();
1495     const ::rtl::OUString* pEnd	  = pIter + aNames.getLength();
1496     for(;pIter != pEnd;++pIter)
1497     {
1498         uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
1499         OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
1500         if ( xObj.is() )
1501         {
1502             sal_Int32 nCurState = xObj->getCurrentState();
1503             if ( _bOasisFormat && nCurState != embed::EmbedStates::LOADED && nCurState != embed::EmbedStates::RUNNING )
1504             {
1505                 // means that the object is active
1506                 // the image must be regenerated
1507                 ::rtl::OUString aMediaType;
1508 
1509                 // TODO/LATER: another aspect could be used
1510                 uno::Reference < io::XInputStream > xStream =
1511                             GetGraphicReplacementStream(
1512                                                         embed::Aspects::MSOLE_CONTENT,
1513                                                         xObj,
1514                                                         &aMediaType );
1515                 if ( xStream.is() )
1516 				{
1517                     if ( !InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) )
1518                         InsertGraphicStream( xStream, *pIter, aMediaType );
1519 				}
1520             }
1521 
1522 			// TODO/LATER: currently the object by default does not cache replacement image
1523 			// that means that if somebody loads SO7 document and store its objects using
1524 			// this method the images might be lost.
1525 			// Currently this method is only used on storing to alien formats, that means
1526 			// that SO7 documents storing does not use it, and all other filters are
1527 			// based on OASIS format. But if it changes the method must be fixed. The fix
1528 			// must be done only on demand since it can affect performance.
1529 
1530             uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1531             if ( xPersist.is() )
1532             {
1533                 try
1534                 {
1535                     //TODO/LATER: only storing if changed!
1536                     xPersist->storeOwn();
1537                 }
1538                 catch( uno::Exception& )
1539                 {
1540                     // TODO/LATER: error handling
1541                     bResult = sal_False;
1542                     break;
1543                 }
1544             }
1545 
1546             if ( !_bOasisFormat && !_bObjectsOnly )
1547             {
1548                 // copy replacement images for linked objects
1549                 try
1550                 {
1551                     uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY );
1552                     if ( xLink.is() && xLink->isLink() )
1553                     {
1554                         ::rtl::OUString aMediaType;
1555                         uno::Reference < io::XInputStream > xInStream = GetGraphicStream( xObj, &aMediaType );
1556                         if ( xInStream.is() )
1557                             InsertStreamIntoPicturesStorage_Impl( pImpl->mxStorage, xInStream, *pIter );
1558                     }
1559                 }
1560                 catch( uno::Exception& )
1561                 {
1562                 }
1563             }
1564         }
1565     }
1566 
1567 	if ( bResult && _bOasisFormat )
1568 		bResult = CommitImageSubStorage();
1569 
1570     if ( bResult && !_bObjectsOnly )
1571     {
1572         try
1573         {
1574             ReleaseImageSubStorage();
1575             ::rtl::OUString aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
1576             if ( !_bOasisFormat && pImpl->mxStorage->hasByName( aObjReplElement ) && pImpl->mxStorage->isStorageElement( aObjReplElement ) )
1577                 pImpl->mxStorage->removeElement( aObjReplElement );
1578         }
1579         catch( uno::Exception& )
1580         {
1581             // TODO/LATER: error handling
1582             bResult = sal_False;
1583         }
1584     }
1585     return bResult;
1586 }
1587 // -----------------------------------------------------------------------------
1588 uno::Reference< io::XInputStream > EmbeddedObjectContainer::GetGraphicReplacementStream(
1589 																sal_Int64 nViewAspect,
1590 																const uno::Reference< embed::XEmbeddedObject >& xObj,
1591 																::rtl::OUString* pMediaType )
1592 {
1593 	uno::Reference< io::XInputStream > xInStream;
1594 	if ( xObj.is() )
1595 	{
1596 		try
1597 		{
1598             // retrieving of the visual representation can switch object to running state
1599 			embed::VisualRepresentation aRep = xObj->getPreferredVisualRepresentation( nViewAspect );
1600 			if ( pMediaType )
1601 				*pMediaType = aRep.Flavor.MimeType;
1602 
1603 			uno::Sequence < sal_Int8 > aSeq;
1604 			aRep.Data >>= aSeq;
1605 			xInStream = new ::comphelper::SequenceInputStream( aSeq );
1606 		}
1607 		catch ( uno::Exception& )
1608 		{
1609 		}
1610 	}
1611 
1612 	return xInStream;
1613 }
1614 // -----------------------------------------------------------------------------
1615 sal_Bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed::XStorage >& _xStorage,bool _bClearModifedFlag)
1616 {
1617     sal_Bool bError = sal_False;
1618     const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames();
1619     const ::rtl::OUString* pIter = aNames.getConstArray();
1620     const ::rtl::OUString* pEnd	  = pIter + aNames.getLength();
1621     for(;pIter != pEnd;++pIter)
1622     {
1623 		uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
1624 		OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
1625 		if ( xObj.is() )
1626 		{
1627 			uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1628 			if ( xPersist.is() )
1629 			{
1630 				try
1631 				{
1632 					xPersist->setPersistentEntry( _xStorage,
1633 												*pIter,
1634 												embed::EntryInitModes::NO_INIT,
1635 												uno::Sequence< beans::PropertyValue >(),
1636 												uno::Sequence< beans::PropertyValue >() );
1637 
1638 				}
1639 				catch( uno::Exception& )
1640 				{
1641 					// TODO/LATER: error handling
1642                     bError = sal_True;
1643 					break;
1644 				}
1645 			}
1646             if ( _bClearModifedFlag )
1647 			{
1648 				// if this method is used as part of SaveCompleted the object must stay unmodified after execution
1649 				try
1650 				{
1651 					uno::Reference< util::XModifiable > xModif( xObj->getComponent(), uno::UNO_QUERY_THROW );
1652 					if ( xModif->isModified() )
1653 						xModif->setModified( sal_False );
1654 				}
1655 				catch( uno::Exception& )
1656 				{
1657 				}
1658 			}
1659 		}
1660 	}
1661     return bError;
1662 }
1663 }
1664