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