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