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