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