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