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