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