update dev300-m57
[ooovba.git] / comphelper / source / container / embeddedobjectcontainer.cxx
blob10e27b81d667b8e4f4be075cbec443b01f98bf04
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: embeddedobjectcontainer.cxx,v $
10 * $Revision: 1.26 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_comphelper.hxx"
33 #include <com/sun/star/container/XChild.hpp>
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
36 #include <com/sun/star/embed/XLinkCreator.hpp>
37 #include <com/sun/star/embed/XEmbedPersist.hpp>
38 #include <com/sun/star/embed/XLinkageSupport.hpp>
39 #include <com/sun/star/embed/XTransactedObject.hpp>
40 #include <com/sun/star/embed/XOptimizedStorage.hpp>
41 #include <com/sun/star/embed/EntryInitModes.hpp>
42 #include <com/sun/star/util/XCloseable.hpp>
43 #include <com/sun/star/util/XModifiable.hpp>
44 #include <com/sun/star/embed/EmbedStates.hpp>
45 #include <com/sun/star/datatransfer/XTransferable.hpp>
46 #include <com/sun/star/beans/XPropertySetInfo.hpp>
47 #include <com/sun/star/beans/XPropertySet.hpp>
48 #include <com/sun/star/embed/Aspects.hpp>
49 #include <com/sun/star/embed/EmbedMisc.hpp>
51 #include <comphelper/seqstream.hxx>
52 #include <comphelper/processfactory.hxx>
53 #include <comphelper/storagehelper.hxx>
54 #include <comphelper/embeddedobjectcontainer.hxx>
55 #include <comphelper/sequence.hxx>
56 #include <cppuhelper/weakref.hxx>
57 #include <hash_map>
58 #include <algorithm>
60 #include <rtl/logfile.hxx>
62 using namespace ::com::sun::star;
64 namespace comphelper
67 struct hashObjectName_Impl
69 size_t operator()(const ::rtl::OUString Str) const
71 return (size_t)Str.hashCode();
75 struct eqObjectName_Impl
77 sal_Bool operator()(const ::rtl::OUString Str1, const ::rtl::OUString Str2) const
79 return ( Str1 == Str2 );
83 typedef std::hash_map
85 ::rtl::OUString,
86 ::com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >,
87 hashObjectName_Impl,
88 eqObjectName_Impl
90 EmbeddedObjectContainerNameMap;
92 struct EmbedImpl
94 // TODO/LATER: remove objects from temp. Container storage when object is disposed
95 EmbeddedObjectContainerNameMap maObjectContainer;
96 uno::Reference < embed::XStorage > mxStorage;
97 EmbeddedObjectContainer* mpTempObjectContainer;
98 uno::Reference < embed::XStorage > mxImageStorage;
99 uno::WeakReference < uno::XInterface > m_xModel;
100 //EmbeddedObjectContainerNameMap maTempObjectContainer;
101 //uno::Reference < embed::XStorage > mxTempStorage;
102 sal_Bool bOwnsStorage;
104 const uno::Reference < embed::XStorage >& GetReplacements();
107 const uno::Reference < embed::XStorage >& EmbedImpl::GetReplacements()
109 if ( !mxImageStorage.is() )
113 mxImageStorage = mxStorage->openStorageElement(
114 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READWRITE );
116 catch ( uno::Exception& )
118 mxImageStorage = mxStorage->openStorageElement(
119 ::rtl::OUString::createFromAscii( "ObjectReplacements" ), embed::ElementModes::READ );
123 if ( !mxImageStorage.is() )
124 throw io::IOException();
126 return mxImageStorage;
129 EmbeddedObjectContainer::EmbeddedObjectContainer()
131 pImpl = new EmbedImpl;
132 pImpl->mxStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
133 pImpl->bOwnsStorage = sal_True;
134 pImpl->mpTempObjectContainer = 0;
137 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor )
139 pImpl = new EmbedImpl;
140 pImpl->mxStorage = rStor;
141 pImpl->bOwnsStorage = sal_False;
142 pImpl->mpTempObjectContainer = 0;
145 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference < embed::XStorage >& rStor, const uno::Reference < uno::XInterface >& xModel )
147 pImpl = new EmbedImpl;
148 pImpl->mxStorage = rStor;
149 pImpl->bOwnsStorage = sal_False;
150 pImpl->mpTempObjectContainer = 0;
151 pImpl->m_xModel = xModel;
154 void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference < embed::XStorage >& rStor )
156 ReleaseImageSubStorage();
158 if ( pImpl->bOwnsStorage )
159 pImpl->mxStorage->dispose();
161 pImpl->mxStorage = rStor;
162 pImpl->bOwnsStorage = sal_False;
165 sal_Bool EmbeddedObjectContainer::CommitImageSubStorage()
167 if ( pImpl->mxImageStorage.is() )
171 sal_Bool bReadOnlyMode = sal_True;
172 uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY);
173 if ( xSet.is() )
175 // get the open mode from the parent storage
176 sal_Int32 nMode = 0;
177 uno::Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("OpenMode") );
178 if ( aAny >>= nMode )
179 bReadOnlyMode = !(nMode & embed::ElementModes::WRITE );
180 } // if ( xSet.is() )
181 if ( !bReadOnlyMode )
183 uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW );
184 xTransact->commit();
187 catch( uno::Exception& )
189 return sal_False;
193 return sal_True;
196 void EmbeddedObjectContainer::ReleaseImageSubStorage()
198 CommitImageSubStorage();
200 if ( pImpl->mxImageStorage.is() )
204 pImpl->mxImageStorage->dispose();
205 pImpl->mxImageStorage = uno::Reference< embed::XStorage >();
207 catch( uno::Exception& )
209 OSL_ASSERT( "Problems releasing image substorage!\n" );
214 EmbeddedObjectContainer::~EmbeddedObjectContainer()
216 ReleaseImageSubStorage();
218 if ( pImpl->bOwnsStorage )
219 pImpl->mxStorage->dispose();
221 delete pImpl->mpTempObjectContainer;
222 delete pImpl;
225 void EmbeddedObjectContainer::CloseEmbeddedObjects()
227 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
228 while ( aIt != pImpl->maObjectContainer.end() )
230 uno::Reference < util::XCloseable > xClose( (*aIt).second, uno::UNO_QUERY );
231 if ( xClose.is() )
235 xClose->close( sal_True );
237 catch ( uno::Exception& )
242 aIt++;
246 ::rtl::OUString EmbeddedObjectContainer::CreateUniqueObjectName()
248 ::rtl::OUString aPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
249 ::rtl::OUString aStr;
250 sal_Int32 i=1;
253 aStr = aPersistName;
254 aStr += ::rtl::OUString::valueOf( i++ );
256 while( HasEmbeddedObject( aStr ) );
257 // TODO/LATER: should we consider deleted objects?
259 return aStr;
262 uno::Sequence < ::rtl::OUString > EmbeddedObjectContainer::GetObjectNames()
264 uno::Sequence < ::rtl::OUString > aSeq( pImpl->maObjectContainer.size() );
265 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
266 sal_Int32 nIdx=0;
267 while ( aIt != pImpl->maObjectContainer.end() )
268 aSeq[nIdx++] = (*aIt++).first;
269 return aSeq;
272 sal_Bool EmbeddedObjectContainer::HasEmbeddedObjects()
274 return pImpl->maObjectContainer.size() != 0;
277 sal_Bool EmbeddedObjectContainer::HasEmbeddedObject( const ::rtl::OUString& rName )
279 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
280 if ( aIt == pImpl->maObjectContainer.end() )
282 uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
283 return xAccess->hasByName(rName);
285 else
286 return sal_True;
289 sal_Bool EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj )
291 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
292 while ( aIt != pImpl->maObjectContainer.end() )
294 if ( (*aIt).second == xObj )
295 return sal_True;
296 else
297 aIt++;
300 return sal_False;
303 sal_Bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const ::rtl::OUString& rName )
305 // allows to detect whether the object was already instantiated
306 // currently the filter instantiate it on loading, so this method allows
307 // to avoid objects pointing to the same persistence
308 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
309 return ( aIt != pImpl->maObjectContainer.end() );
312 ::rtl::OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj )
314 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
315 while ( aIt != pImpl->maObjectContainer.end() )
317 if ( (*aIt).second == xObj )
318 return (*aIt).first;
319 else
320 aIt++;
323 OSL_ENSURE( 0, "Unknown object!" );
324 return ::rtl::OUString();
327 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::GetEmbeddedObject( const ::rtl::OUString& rName )
329 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetEmbeddedObject" );
331 OSL_ENSURE( rName.getLength(), "Empty object name!");
333 uno::Reference < embed::XEmbeddedObject > xObj;
334 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
336 #if OSL_DEBUG_LEVEL > 1
337 uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
338 uno::Sequence< ::rtl::OUString> aSeq = xAccess->getElementNames();
339 const ::rtl::OUString* pIter = aSeq.getConstArray();
340 const ::rtl::OUString* pEnd = pIter + aSeq.getLength();
341 for(;pIter != pEnd;++pIter)
343 (void)*pIter;
345 OSL_ENSURE( aIt != pImpl->maObjectContainer.end() || xAccess->hasByName(rName), "Could not return object!" );
346 #endif
348 // check if object was already created
349 if ( aIt != pImpl->maObjectContainer.end() )
350 xObj = (*aIt).second;
351 else
352 xObj = Get_Impl( rName, uno::Reference < embed::XEmbeddedObject >() );
354 return xObj;
357 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::Get_Impl( const ::rtl::OUString& rName, const uno::Reference < embed::XEmbeddedObject >& xCopy )
359 uno::Reference < embed::XEmbeddedObject > xObj;
362 // create the object from the storage
363 uno::Reference < beans::XPropertySet > xSet( pImpl->mxStorage, uno::UNO_QUERY );
364 sal_Bool bReadOnlyMode = sal_True;
365 if ( xSet.is() )
367 // get the open mode from the parent storage
368 sal_Int32 nMode = 0;
369 uno::Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("OpenMode") );
370 if ( aAny >>= nMode )
371 bReadOnlyMode = !(nMode & embed::ElementModes::WRITE );
374 // object was not added until now - should happen only by calling this method from "inside"
375 //TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call)
376 uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
377 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
378 uno::Sequence< beans::PropertyValue > aObjDescr( xCopy.is() ? 2 : 1 );
379 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
380 aObjDescr[0].Value <<= pImpl->m_xModel.get();
381 if ( xCopy.is() )
383 aObjDescr[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CloneFrom" ) );
384 aObjDescr[1].Value <<= xCopy;
387 uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
388 aMediaDescr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly"));
389 aMediaDescr[0].Value <<= bReadOnlyMode;
390 xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromEntry(
391 pImpl->mxStorage, rName,
392 aMediaDescr, aObjDescr ), uno::UNO_QUERY );
394 // insert object into my list
395 AddEmbeddedObject( xObj, rName );
397 catch ( uno::Exception& )
401 return xObj;
404 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId,
405 const uno::Sequence < beans::PropertyValue >& rArgs, ::rtl::OUString& rNewName )
407 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CreateEmbeddedObject" );
409 if ( !rNewName.getLength() )
410 rNewName = CreateUniqueObjectName();
412 OSL_ENSURE( !HasEmbeddedObject(rNewName), "Object to create already exists!");
414 // create object from classid by inserting it into storage
415 uno::Reference < embed::XEmbeddedObject > xObj;
418 uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
419 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
421 uno::Sequence< beans::PropertyValue > aObjDescr( rArgs.getLength() + 1 );
422 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
423 aObjDescr[0].Value <<= pImpl->m_xModel.get();
424 ::std::copy( rArgs.getConstArray(), rArgs.getConstArray() + rArgs.getLength(), aObjDescr.getArray() + 1 );
425 xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitNew(
426 rClassId, ::rtl::OUString(), pImpl->mxStorage, rNewName,
427 aObjDescr ), uno::UNO_QUERY );
429 AddEmbeddedObject( xObj, rNewName );
431 OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
432 "A freshly create object should be running always!\n" );
434 catch ( uno::Exception& )
438 return xObj;
441 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence < sal_Int8 >& rClassId, ::rtl::OUString& rNewName )
443 return CreateEmbeddedObject( rClassId, uno::Sequence < beans::PropertyValue >(), rNewName );
446 void EmbeddedObjectContainer::AddEmbeddedObject( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, const ::rtl::OUString& rName )
448 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::AddEmbeddedObject" );
450 #if OSL_DEBUG_LEVEL > 1
451 OSL_ENSURE( rName.getLength(), "Added object doesn't have a name!");
452 uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
453 uno::Reference < embed::XEmbedPersist > xEmb( xObj, uno::UNO_QUERY );
454 uno::Reference < embed::XLinkageSupport > xLink( xEmb, uno::UNO_QUERY );
455 // if the object has a persistance and the object is not a link than it must have persistence entry in the storage
456 OSL_ENSURE( !( xEmb.is() && ( !xLink.is() || !xLink->isLink() ) ) || xAccess->hasByName(rName),
457 "Added element not in storage!" );
458 #endif
460 // remember object - it needs to be in storage already
461 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
462 OSL_ENSURE( aIt == pImpl->maObjectContainer.end(), "Element already inserted!" );
463 pImpl->maObjectContainer[ rName ] = xObj;
464 uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
465 if ( xChild.is() && xChild->getParent() != pImpl->m_xModel.get() )
466 xChild->setParent( pImpl->m_xModel.get() );
468 // look for object in temorary container
469 if ( pImpl->mpTempObjectContainer )
471 aIt = pImpl->mpTempObjectContainer->pImpl->maObjectContainer.begin();
472 while ( aIt != pImpl->mpTempObjectContainer->pImpl->maObjectContainer.end() )
474 if ( (*aIt).second == xObj )
476 // copy replacement image from temporary container (if there is any)
477 ::rtl::OUString aTempName = (*aIt).first;
478 ::rtl::OUString aMediaType;
479 uno::Reference < io::XInputStream > xStream = pImpl->mpTempObjectContainer->GetGraphicStream( xObj, &aMediaType );
480 if ( xStream.is() )
482 InsertGraphicStream( xStream, rName, aMediaType );
483 xStream = 0;
484 pImpl->mpTempObjectContainer->RemoveGraphicStream( aTempName );
487 // remove object from storage of temporary container
488 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
489 if ( xPersist.is() )
493 pImpl->mpTempObjectContainer->pImpl->mxStorage->removeElement( aTempName );
495 catch ( uno::Exception& )
500 // temp. container needs to forget the object
501 pImpl->mpTempObjectContainer->pImpl->maObjectContainer.erase( aIt );
502 break;
504 else
505 aIt++;
510 sal_Bool EmbeddedObjectContainer::StoreEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName, sal_Bool bCopy )
512 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::StoreEmbeddedObject" );
514 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
515 if ( !rName.getLength() )
516 rName = CreateUniqueObjectName();
518 #if OSL_DEBUG_LEVEL > 1
519 uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
520 OSL_ENSURE( !xPersist.is() || !xAccess->hasByName(rName), "Inserting element already present in storage!" );
521 OSL_ENSURE( xPersist.is() || xObj->getCurrentState() == embed::EmbedStates::RUNNING, "Non persistent object inserted!");
522 #endif
524 // insert objects' storage into the container storage (if object has one)
527 if ( xPersist.is() )
529 uno::Sequence < beans::PropertyValue > aSeq;
530 if ( bCopy )
531 xPersist->storeToEntry( pImpl->mxStorage, rName, aSeq, aSeq );
532 else
534 //TODO/LATER: possible optimisation, don't store immediately
535 //xPersist->setPersistentEntry( pImpl->mxStorage, rName, embed::EntryInitModes::ENTRY_NO_INIT, aSeq, aSeq );
536 xPersist->storeAsEntry( pImpl->mxStorage, rName, aSeq, aSeq );
537 xPersist->saveCompleted( sal_True );
541 catch ( uno::Exception& )
543 // TODO/LATER: better error recovery should keep storage intact
544 return sal_False;
547 return sal_True;
550 sal_Bool EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
552 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( Object )" );
553 // store it into the container storage
554 if ( StoreEmbeddedObject( xObj, rName, sal_False ) )
556 // remember object
557 AddEmbeddedObject( xObj, rName );
558 return sal_True;
560 else
561 return sal_False;
564 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference < io::XInputStream >& xStm, ::rtl::OUString& rNewName )
566 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( InputStream )" );
568 if ( !rNewName.getLength() )
569 rNewName = CreateUniqueObjectName();
571 // store it into the container storage
572 sal_Bool bIsStorage = sal_False;
575 // first try storage persistence
576 uno::Reference < embed::XStorage > xStore = ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm );
578 // storage was created from stream successfully
579 bIsStorage = sal_True;
581 uno::Reference < embed::XStorage > xNewStore = pImpl->mxStorage->openStorageElement( rNewName, embed::ElementModes::READWRITE );
582 xStore->copyToStorage( xNewStore );
584 catch ( uno::Exception& )
586 if ( bIsStorage )
587 // it is storage persistence, but opening of new substorage or copying to it failed
588 return uno::Reference < embed::XEmbeddedObject >();
590 // stream didn't contain a storage, now try stream persistence
593 uno::Reference < io::XStream > xNewStream = pImpl->mxStorage->openStreamElement( rNewName, embed::ElementModes::READWRITE );
594 ::comphelper::OStorageHelper::CopyInputToOutput( xStm, xNewStream->getOutputStream() );
596 // No mediatype is provided so the default for OLE objects value is used
597 // it is correct so for now, but what if somebody introduces a new stream based embedded object?
598 // Probably introducing of such an object must be restricted ( a storage must be used! ).
599 uno::Reference< beans::XPropertySet > xProps( xNewStream, uno::UNO_QUERY_THROW );
600 xProps->setPropertyValue(
601 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
602 uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) ) ) );
604 catch ( uno::Exception& )
606 // complete disaster!
607 return uno::Reference < embed::XEmbeddedObject >();
611 // stream was copied into the container storage in either way, now try to open something form it
612 uno::Reference < embed::XEmbeddedObject > xRet = GetEmbeddedObject( rNewName );
615 if ( !xRet.is() )
616 // no object could be created, so withdraw insertion
617 pImpl->mxStorage->removeElement( rNewName );
619 catch ( uno::Exception& )
623 return xRet;
626 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedObject( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, ::rtl::OUString& rNewName )
628 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( MediaDescriptor )" );
630 if ( !rNewName.getLength() )
631 rNewName = CreateUniqueObjectName();
633 uno::Reference < embed::XEmbeddedObject > xObj;
636 uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
637 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
638 uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
639 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
640 aObjDescr[0].Value <<= pImpl->m_xModel.get();
641 xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitFromMediaDescriptor(
642 pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY );
643 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
645 OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
646 "A freshly create object should be running always!\n" );
648 // possible optimization: store later!
649 if ( xPersist.is())
650 xPersist->storeOwn();
652 AddEmbeddedObject( xObj, rNewName );
654 catch ( uno::Exception& )
658 return xObj;
661 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbeddedLink( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& aMedium, ::rtl::OUString& rNewName )
663 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedLink" );
665 if ( !rNewName.getLength() )
666 rNewName = CreateUniqueObjectName();
668 uno::Reference < embed::XEmbeddedObject > xObj;
671 uno::Reference < embed::XLinkCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance(
672 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY );
673 uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
674 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
675 aObjDescr[0].Value <<= pImpl->m_xModel.get();
676 xObj = uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceLink(
677 pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY );
679 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
681 OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED,
682 "A freshly create object should be running always!\n" );
684 // possible optimization: store later!
685 if ( xPersist.is())
686 xPersist->storeOwn();
688 AddEmbeddedObject( xObj, rNewName );
690 catch ( uno::Exception& )
694 return xObj;
697 sal_Bool EmbeddedObjectContainer::TryToCopyGraphReplacement( EmbeddedObjectContainer& rSrc,
698 const ::rtl::OUString& aOrigName,
699 const ::rtl::OUString& aTargetName )
701 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::TryToCopyGraphReplacement" );
703 sal_Bool bResult = sal_False;
705 if ( ( &rSrc != this || !aOrigName.equals( aTargetName ) ) && aOrigName.getLength() && aTargetName.getLength() )
707 ::rtl::OUString aMediaType;
708 uno::Reference < io::XInputStream > xGrStream = rSrc.GetGraphicStream( aOrigName, &aMediaType );
709 if ( xGrStream.is() )
710 bResult = InsertGraphicStream( xGrStream, aTargetName, aMediaType );
713 return bResult;
716 sal_Bool EmbeddedObjectContainer::CopyEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
718 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyEmbeddedObject" );
720 OSL_ENSURE( sal_False,
721 "This method is depricated! Use EmbeddedObjectContainer::CopyAndGetEmbeddedObject() to copy object!\n" );
723 // get the object name before(!) it is assigned to a new storage
724 ::rtl::OUString aOrigName;
725 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
726 if ( xPersist.is() )
727 aOrigName = xPersist->getEntryName();
729 if ( !rName.getLength() )
730 rName = CreateUniqueObjectName();
732 if ( StoreEmbeddedObject( xObj, rName, sal_True ) )
734 TryToCopyGraphReplacement( rSrc, aOrigName, rName );
735 return sal_True;
738 return sal_False;
741 uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CopyAndGetEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
743 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyAndGetEmbeddedObject" );
745 uno::Reference< embed::XEmbeddedObject > xResult;
747 // TODO/LATER: For now only objects that implement XEmbedPersist have a replacement image, it might change in future
748 // do an incompatible change so that object name is provided in all the move and copy methods
749 ::rtl::OUString aOrigName;
752 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY_THROW );
753 aOrigName = xPersist->getEntryName();
755 catch( uno::Exception& )
758 if ( !rName.getLength() )
759 rName = CreateUniqueObjectName();
761 // objects without persistance are not really stored by the method
762 if ( xObj.is() && StoreEmbeddedObject( xObj, rName, sal_True ) )
764 xResult = Get_Impl( rName, xObj);
765 if ( !xResult.is() )
767 // this is a case when object has no real persistence
768 // in such cases a new object should be explicitly created and initialized with the data of the old one
771 uno::Reference< embed::XLinkageSupport > xOrigLinkage( xObj, uno::UNO_QUERY );
772 if ( xOrigLinkage.is() && xOrigLinkage->isLink() )
774 // this is a OOo link, it has no persistence
775 ::rtl::OUString aURL = xOrigLinkage->getLinkURL();
776 if ( !aURL.getLength() )
777 throw uno::RuntimeException();
779 // create new linked object from the URL the link is based on
780 uno::Reference < embed::XLinkCreator > xCreator(
781 ::comphelper::getProcessServiceFactory()->createInstance(
782 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
783 uno::UNO_QUERY_THROW );
785 uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
786 aMediaDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
787 aMediaDescr[0].Value <<= aURL;
788 uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
789 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
790 aObjDescr[0].Value <<= pImpl->m_xModel.get();
791 xResult = uno::Reference < embed::XEmbeddedObject >(
792 xCreator->createInstanceLink(
793 pImpl->mxStorage,
794 rName,
795 aMediaDescr,
796 aObjDescr ),
797 uno::UNO_QUERY_THROW );
799 else
801 // the component is required for copying of this object
802 if ( xObj->getCurrentState() == embed::EmbedStates::LOADED )
803 xObj->changeState( embed::EmbedStates::RUNNING );
805 // this must be an object based on properties, otherwise we can not copy it currently
806 uno::Reference< beans::XPropertySet > xOrigProps( xObj->getComponent(), uno::UNO_QUERY_THROW );
808 // use object class ID to create a new one and tranfer all the properties
809 uno::Reference < embed::XEmbedObjectCreator > xCreator(
810 ::comphelper::getProcessServiceFactory()->createInstance(
811 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator") ) ),
812 uno::UNO_QUERY_THROW );
814 uno::Sequence< beans::PropertyValue > aObjDescr( 1 );
815 aObjDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Parent" ) );
816 aObjDescr[0].Value <<= pImpl->m_xModel.get();
817 xResult = uno::Reference < embed::XEmbeddedObject >(
818 xCreator->createInstanceInitNew(
819 xObj->getClassID(),
820 xObj->getClassName(),
821 pImpl->mxStorage,
822 rName,
823 aObjDescr ),
824 uno::UNO_QUERY_THROW );
826 if ( xResult->getCurrentState() == embed::EmbedStates::LOADED )
827 xResult->changeState( embed::EmbedStates::RUNNING );
829 uno::Reference< beans::XPropertySet > xTargetProps( xResult->getComponent(), uno::UNO_QUERY_THROW );
831 // copy all the properties from xOrigProps to xTargetProps
832 uno::Reference< beans::XPropertySetInfo > xOrigInfo = xOrigProps->getPropertySetInfo();
833 if ( !xOrigInfo.is() )
834 throw uno::RuntimeException();
836 uno::Sequence< beans::Property > aPropertiesList = xOrigInfo->getProperties();
837 for ( sal_Int32 nInd = 0; nInd < aPropertiesList.getLength(); nInd++ )
841 xTargetProps->setPropertyValue(
842 aPropertiesList[nInd].Name,
843 xOrigProps->getPropertyValue( aPropertiesList[nInd].Name ) );
845 catch( beans::PropertyVetoException& )
847 // impossibility to copy readonly property is not treated as an error for now
848 // but the assertion is helpful to detect such scenarios and review them
849 OSL_ENSURE( sal_False, "Could not copy readonly property!\n" );
854 if ( xResult.is() )
855 AddEmbeddedObject( xResult, rName );
857 catch( uno::Exception& )
859 if ( xResult.is() )
863 xResult->close( sal_True );
865 catch( uno::Exception& )
867 xResult = uno::Reference< embed::XEmbeddedObject >();
873 OSL_ENSURE( xResult.is(), "Can not copy embedded object that has no persistance!\n" );
875 if ( xResult.is() )
877 // the object is successfully copied, try to copy graphical replacement
878 if ( aOrigName.getLength() )
879 TryToCopyGraphReplacement( rSrc, aOrigName, rName );
881 // the object might need the size to be set
884 if ( xResult->getStatus( embed::Aspects::MSOLE_CONTENT ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD )
885 xResult->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT,
886 xObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ) );
888 catch( uno::Exception& )
892 return xResult;
895 sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( EmbeddedObjectContainer& rSrc, const uno::Reference < embed::XEmbeddedObject >& xObj, ::rtl::OUString& rName )
897 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Object )" );
899 // get the object name before(!) it is assigned to a new storage
900 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
901 ::rtl::OUString aName;
902 if ( xPersist.is() )
903 aName = xPersist->getEntryName();
905 // now move the object to the new container; the returned name is the new persist name in this container
906 sal_Bool bRet;
910 bRet = InsertEmbeddedObject( xObj, rName );
911 if ( bRet )
912 TryToCopyGraphReplacement( rSrc, aName, rName );
914 catch ( uno::Exception& e )
916 (void)e;
917 OSL_ENSURE( sal_False, "Failed to insert embedded object into storage!" );
918 bRet = sal_False;
921 if ( bRet )
923 // now remove the object from the former container
924 bRet = sal_False;
925 EmbeddedObjectContainerNameMap::iterator aIt = rSrc.pImpl->maObjectContainer.begin();
926 while ( aIt != rSrc.pImpl->maObjectContainer.end() )
928 if ( (*aIt).second == xObj )
930 rSrc.pImpl->maObjectContainer.erase( aIt );
931 bRet = sal_True;
932 break;
935 aIt++;
938 OSL_ENSURE( bRet, "Object not found for removal!" );
939 if ( xPersist.is() )
941 // now it's time to remove the storage from the container storage
944 if ( xPersist.is() )
945 rSrc.pImpl->mxStorage->removeElement( aName );
947 catch ( uno::Exception& )
949 OSL_ENSURE( sal_False, "Failed to remove object from storage!" );
950 bRet = sal_False;
954 // rSrc.RemoveGraphicStream( aName );
957 return bRet;
960 sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const ::rtl::OUString& rName, sal_Bool bClose )
962 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Name )" );
964 uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( rName );
965 if ( xObj.is() )
966 return RemoveEmbeddedObject( xObj, bClose );
967 else
968 return sal_False;
971 sal_Bool EmbeddedObjectContainer::MoveEmbeddedObject( const ::rtl::OUString& rName, EmbeddedObjectContainer& rCnt )
973 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Name )" );
975 // find object entry
976 EmbeddedObjectContainerNameMap::iterator aIt2 = rCnt.pImpl->maObjectContainer.find( rName );
977 OSL_ENSURE( aIt2 == rCnt.pImpl->maObjectContainer.end(), "Object does already exist in target container!" );
979 if ( aIt2 != rCnt.pImpl->maObjectContainer.end() )
980 return sal_False;
982 uno::Reference < embed::XEmbeddedObject > xObj;
983 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
984 if ( aIt != pImpl->maObjectContainer.end() )
986 xObj = (*aIt).second;
989 if ( xObj.is() )
991 // move object
992 ::rtl::OUString aName( rName );
993 rCnt.InsertEmbeddedObject( xObj, aName );
994 pImpl->maObjectContainer.erase( aIt );
995 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
996 if ( xPersist.is() )
997 pImpl->mxStorage->removeElement( rName );
999 else
1001 // copy storages; object *must* have persistence!
1002 uno::Reference < embed::XStorage > xOld = pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READ );
1003 uno::Reference < embed::XStorage > xNew = rCnt.pImpl->mxStorage->openStorageElement( rName, embed::ElementModes::READWRITE );
1004 xOld->copyToStorage( xNew );
1007 rCnt.TryToCopyGraphReplacement( *this, rName, rName );
1008 // RemoveGraphicStream( rName );
1010 return sal_True;
1012 catch ( uno::Exception& )
1014 OSL_ENSURE(0,"Could not move object!");
1015 return sal_False;
1019 else
1020 OSL_ENSURE(0,"Unknown object!");
1021 return sal_False;
1024 sal_Bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Bool bClose )
1026 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Object )" );
1028 uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1029 ::rtl::OUString aName;
1030 if ( xPersist.is() )
1031 aName = xPersist->getEntryName();
1033 #if OSL_DEBUG_LEVEL > 1
1034 uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
1035 uno::Reference < embed::XLinkageSupport > xLink( xPersist, uno::UNO_QUERY );
1036 sal_Bool bIsNotEmbedded = !xPersist.is() || xLink.is() && xLink->isLink();
1038 // if the object has a persistance and the object is not a link than it must have persistence entry in the storage
1039 OSL_ENSURE( bIsNotEmbedded || xAccess->hasByName(aName), "Removing element not present in storage!" );
1040 #endif
1042 // try to close it if permitted
1043 if ( bClose )
1045 uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
1048 xClose->close( sal_True );
1050 catch ( util::CloseVetoException& )
1052 bClose = sal_False;
1056 if ( !bClose )
1058 // somebody still needs the object, so we must assign a temporary persistence
1061 if ( xPersist.is() )
1064 //TODO/LATER: needs storage handling! Why not letting the object do it?!
1065 if ( !pImpl->mxTempStorage.is() )
1066 pImpl->mxTempStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
1067 uno::Sequence < beans::PropertyValue > aSeq;
1069 ::rtl::OUString aTmpPersistName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Object ") );
1070 aTmpPersistName += ::rtl::OUString::valueOf( (sal_Int32) pImpl->maTempObjectContainer.size() );
1072 xPersist->storeAsEntry( pImpl->mxTempStorage, aTmpPersistName, aSeq, aSeq );
1073 xPersist->saveCompleted( sal_True );
1075 pImpl->maTempObjectContainer[ aTmpPersistName ] = uno::Reference < embed::XEmbeddedObject >();
1078 if ( !pImpl->mpTempObjectContainer )
1080 pImpl->mpTempObjectContainer = new EmbeddedObjectContainer();
1083 // TODO/LATER: in future probably the temporary container will have two storages ( of two formats )
1084 // the media type will be provided with object insertion
1085 ::rtl::OUString aOrigStorMediaType;
1086 uno::Reference< beans::XPropertySet > xStorProps( pImpl->mxStorage, uno::UNO_QUERY_THROW );
1087 static const ::rtl::OUString s_sMediaType(RTL_CONSTASCII_USTRINGPARAM("MediaType"));
1088 xStorProps->getPropertyValue( s_sMediaType ) >>= aOrigStorMediaType;
1090 OSL_ENSURE( aOrigStorMediaType.getLength(), "No valuable media type in the storage!\n" );
1092 uno::Reference< beans::XPropertySet > xTargetStorProps(
1093 pImpl->mpTempObjectContainer->pImpl->mxStorage,
1094 uno::UNO_QUERY_THROW );
1095 xTargetStorProps->setPropertyValue( s_sMediaType,uno::makeAny( aOrigStorMediaType ) );
1097 catch( uno::Exception& )
1099 OSL_ENSURE( sal_False, "Can not set the new media type to a storage!\n" );
1103 ::rtl::OUString aTempName, aMediaType;
1104 pImpl->mpTempObjectContainer->InsertEmbeddedObject( xObj, aTempName );
1106 uno::Reference < io::XInputStream > xStream = GetGraphicStream( xObj, &aMediaType );
1107 if ( xStream.is() )
1108 pImpl->mpTempObjectContainer->InsertGraphicStream( xStream, aTempName, aMediaType );
1110 // object is stored, so at least it can be set to loaded state
1111 xObj->changeState( embed::EmbedStates::LOADED );
1113 else
1114 // objects without persistence need to stay in running state if they shall not be closed
1115 xObj->changeState( embed::EmbedStates::RUNNING );
1117 catch ( uno::Exception& )
1119 return sal_False;
1123 sal_Bool bFound = sal_False;
1124 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
1125 while ( aIt != pImpl->maObjectContainer.end() )
1127 if ( (*aIt).second == xObj )
1129 pImpl->maObjectContainer.erase( aIt );
1130 bFound = sal_True;
1131 uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
1132 if ( xChild.is() )
1133 xChild->setParent( uno::Reference < uno::XInterface >() );
1134 break;
1137 aIt++;
1140 OSL_ENSURE( bFound, "Object not found for removal!" );
1141 if ( xPersist.is() )
1143 // remove replacement image (if there is one)
1144 RemoveGraphicStream( aName );
1146 // now it's time to remove the storage from the container storage
1149 #if OSL_DEBUG_LEVEL > 1
1150 // if the object has a persistance and the object is not a link than it must have persistence entry in storage
1151 OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" );
1152 #endif
1153 if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) )
1154 pImpl->mxStorage->removeElement( aName );
1156 catch ( uno::Exception& )
1158 OSL_ENSURE( sal_False, "Failed to remove object from storage!" );
1159 return sal_False;
1163 return sal_True;
1166 sal_Bool EmbeddedObjectContainer::CloseEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj )
1168 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CloseEmbeddedObject" );
1170 // disconnect the object from the container and close it if possible
1172 sal_Bool bFound = sal_False;
1173 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
1174 while ( aIt != pImpl->maObjectContainer.end() )
1176 if ( (*aIt).second == xObj )
1178 pImpl->maObjectContainer.erase( aIt );
1179 bFound = sal_True;
1180 break;
1183 aIt++;
1186 if ( bFound )
1188 uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
1191 xClose->close( sal_True );
1193 catch ( uno::Exception& )
1195 // it is no problem if the object is already closed
1196 // TODO/LATER: what if the object can not be closed?
1200 return bFound;
1203 uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::rtl::OUString& aName, rtl::OUString* pMediaType )
1205 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Name )" );
1207 uno::Reference < io::XInputStream > xStream;
1209 OSL_ENSURE( aName.getLength(), "Retrieving graphic for unknown object!" );
1210 if ( aName.getLength() )
1214 uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
1215 uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( aName, embed::ElementModes::READ );
1216 xStream = xGraphicStream->getInputStream();
1217 if ( pMediaType )
1219 uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
1220 if ( xSet.is() )
1222 uno::Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("MediaType") );
1223 aAny >>= *pMediaType;
1227 catch ( uno::Exception& )
1232 return xStream;
1235 uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj, rtl::OUString* pMediaType )
1237 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Object )" );
1239 // get the object name
1240 ::rtl::OUString aName;
1241 EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.begin();
1242 while ( aIt != pImpl->maObjectContainer.end() )
1244 if ( (*aIt).second == xObj )
1246 aName = (*aIt).first;
1247 break;
1250 aIt++;
1253 // try to load it from the container storage
1254 return GetGraphicStream( aName, pMediaType );
1257 sal_Bool EmbeddedObjectContainer::InsertGraphicStream( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const ::rtl::OUString& rObjectName, const rtl::OUString& rMediaType )
1259 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStream" );
1263 uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
1265 // store it into the subfolder
1266 uno::Reference < io::XOutputStream > xOutStream;
1267 uno::Reference < io::XStream > xGraphicStream = xReplacements->openStreamElement( rObjectName,
1268 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
1269 xOutStream = xGraphicStream->getOutputStream();
1270 ::comphelper::OStorageHelper::CopyInputToOutput( rStream, xOutStream );
1271 xOutStream->flush();
1273 uno::Reference< beans::XPropertySet > xPropSet( xGraphicStream, uno::UNO_QUERY );
1274 if ( !xPropSet.is() )
1275 throw uno::RuntimeException();
1277 xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ),
1278 uno::makeAny( (sal_Bool)sal_True ) );
1279 uno::Any aAny;
1280 aAny <<= rMediaType;
1281 xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii("MediaType"), aAny );
1283 xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "Compressed" ),
1284 uno::makeAny( (sal_Bool)sal_True ) );
1286 catch( uno::Exception& )
1288 return sal_False;
1291 return sal_True;
1294 sal_Bool EmbeddedObjectContainer::InsertGraphicStreamDirectly( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream, const ::rtl::OUString& rObjectName, const rtl::OUString& rMediaType )
1296 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStreamDirectly" );
1300 uno::Reference < embed::XStorage > xReplacement = pImpl->GetReplacements();
1301 uno::Reference < embed::XOptimizedStorage > xOptRepl( xReplacement, uno::UNO_QUERY_THROW );
1303 // store it into the subfolder
1304 uno::Sequence< beans::PropertyValue > aProps( 3 );
1305 aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
1306 aProps[0].Value <<= rMediaType;
1307 aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" ) );
1308 aProps[1].Value <<= (sal_Bool)sal_True;
1309 aProps[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
1310 aProps[2].Value <<= (sal_Bool)sal_True;
1312 if ( xReplacement->hasByName( rObjectName ) )
1313 xReplacement->removeElement( rObjectName );
1315 xOptRepl->insertStreamElementDirect( rObjectName, rStream, aProps );
1317 catch( uno::Exception& )
1319 return sal_False;
1322 return sal_True;
1326 sal_Bool EmbeddedObjectContainer::RemoveGraphicStream( const ::rtl::OUString& rObjectName )
1328 RTL_LOGFILE_CONTEXT( aLog, "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveGraphicStream" );
1332 uno::Reference < embed::XStorage > xReplacements = pImpl->GetReplacements();
1333 xReplacements->removeElement( rObjectName );
1335 catch( uno::Exception& )
1337 return sal_False;
1340 return sal_True;
1342 namespace {
1343 void InsertStreamIntoPicturesStorage_Impl( const uno::Reference< embed::XStorage >& xDocStor,
1344 const uno::Reference< io::XInputStream >& xInStream,
1345 const ::rtl::OUString& aStreamName )
1347 OSL_ENSURE( aStreamName.getLength() && xInStream.is() && xDocStor.is(), "Misuse of the method!\n" );
1351 uno::Reference< embed::XStorage > xPictures = xDocStor->openStorageElement(
1352 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pictures" ) ),
1353 embed::ElementModes::READWRITE );
1354 uno::Reference< io::XStream > xObjReplStr = xPictures->openStreamElement(
1355 aStreamName,
1356 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
1357 uno::Reference< io::XOutputStream > xOutStream(
1358 xObjReplStr->getInputStream(), uno::UNO_QUERY_THROW );
1360 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xOutStream );
1361 xOutStream->closeOutput();
1363 uno::Reference< embed::XTransactedObject > xTransact( xPictures, uno::UNO_QUERY );
1364 if ( xTransact.is() )
1365 xTransact->commit();
1367 catch( uno::Exception& )
1369 OSL_ENSURE( sal_False, "The pictures storage is not available!\n" );
1374 // -----------------------------------------------------------------------------
1375 sal_Bool EmbeddedObjectContainer::StoreAsChildren(sal_Bool _bOasisFormat,sal_Bool _bCreateEmbedded,const uno::Reference < embed::XStorage >& _xStorage)
1377 sal_Bool bResult = sal_False;
1380 comphelper::EmbeddedObjectContainer aCnt( _xStorage );
1381 const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames();
1382 const ::rtl::OUString* pIter = aNames.getConstArray();
1383 const ::rtl::OUString* pEnd = pIter + aNames.getLength();
1384 for(;pIter != pEnd;++pIter)
1386 uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
1387 OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
1388 if ( xObj.is() )
1390 sal_Bool bSwitchBackToLoaded = sal_False;
1391 uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY );
1393 uno::Reference < io::XInputStream > xStream;
1394 ::rtl::OUString aMediaType;
1396 sal_Int32 nCurState = xObj->getCurrentState();
1397 if ( nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING )
1399 // means that the object is not active
1400 // copy replacement image from old to new container
1401 xStream = GetGraphicStream( xObj, &aMediaType );
1404 if ( !xStream.is() )
1406 // the image must be regenerated
1407 // TODO/LATER: another aspect could be used
1408 if ( xObj->getCurrentState() == embed::EmbedStates::LOADED )
1409 bSwitchBackToLoaded = sal_True;
1411 xStream = GetGraphicReplacementStream(
1412 embed::Aspects::MSOLE_CONTENT,
1413 xObj,
1414 &aMediaType );
1417 if ( _bOasisFormat || (xLink.is() && xLink->isLink()) )
1419 if ( xStream.is() )
1421 if ( _bOasisFormat )
1423 // if it is an embedded object or the optimized inserting fails the normal inserting should be done
1424 if ( _bCreateEmbedded
1425 || !aCnt.InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) )
1426 aCnt.InsertGraphicStream( xStream, *pIter, aMediaType );
1428 else
1430 // it is a linked object exported into SO7 format
1431 InsertStreamIntoPicturesStorage_Impl( _xStorage, xStream, *pIter );
1436 uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1437 if ( xPersist.is() )
1439 uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 );
1440 aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StoreVisualReplacement" ) );
1441 aArgs[0].Value <<= (sal_Bool)( !_bOasisFormat );
1443 // if it is an embedded object or the optimized inserting fails the normal inserting should be done
1444 aArgs[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanTryOptimization" ) );
1445 aArgs[1].Value <<= !_bCreateEmbedded;
1446 if ( !_bOasisFormat )
1448 // if object has no cached replacement it will use this one
1449 aArgs[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VisualReplacement" ) );
1450 aArgs[2].Value <<= xStream;
1453 xPersist->storeAsEntry( _xStorage,
1454 xPersist->getEntryName(),
1455 uno::Sequence< beans::PropertyValue >(),
1456 aArgs );
1459 if ( bSwitchBackToLoaded )
1460 // switch back to loaded state; that way we have a minimum cache confusion
1461 xObj->changeState( embed::EmbedStates::LOADED );
1465 bResult = aCnt.CommitImageSubStorage();
1468 catch ( uno::Exception& )
1470 // TODO/LATER: error handling
1471 bResult = sal_False;
1474 // the old SO6 format does not store graphical replacements
1475 if ( !_bOasisFormat && bResult )
1479 // the substorage still can not be locked by the embedded object conteiner
1480 ::rtl::OUString aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
1481 if ( _xStorage->hasByName( aObjReplElement ) && _xStorage->isStorageElement( aObjReplElement ) )
1482 _xStorage->removeElement( aObjReplElement );
1484 catch ( uno::Exception& )
1486 // TODO/LATER: error handling;
1487 bResult = sal_False;
1490 return bResult;
1492 // -----------------------------------------------------------------------------
1493 sal_Bool EmbeddedObjectContainer::StoreChildren(sal_Bool _bOasisFormat,sal_Bool _bObjectsOnly)
1495 sal_Bool bResult = sal_True;
1496 const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames();
1497 const ::rtl::OUString* pIter = aNames.getConstArray();
1498 const ::rtl::OUString* pEnd = pIter + aNames.getLength();
1499 for(;pIter != pEnd;++pIter)
1501 uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
1502 OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
1503 if ( xObj.is() )
1505 sal_Int32 nCurState = xObj->getCurrentState();
1506 if ( _bOasisFormat && nCurState != embed::EmbedStates::LOADED && nCurState != embed::EmbedStates::RUNNING )
1508 // means that the object is active
1509 // the image must be regenerated
1510 ::rtl::OUString aMediaType;
1512 // TODO/LATER: another aspect could be used
1513 uno::Reference < io::XInputStream > xStream =
1514 GetGraphicReplacementStream(
1515 embed::Aspects::MSOLE_CONTENT,
1516 xObj,
1517 &aMediaType );
1518 if ( xStream.is() )
1520 if ( !InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) )
1521 InsertGraphicStream( xStream, *pIter, aMediaType );
1525 // TODO/LATER: currently the object by default does not cache replacement image
1526 // that means that if somebody loads SO7 document and store its objects using
1527 // this method the images might be lost.
1528 // Currently this method is only used on storing to alien formats, that means
1529 // that SO7 documents storing does not use it, and all other filters are
1530 // based on OASIS format. But if it changes the method must be fixed. The fix
1531 // must be done only on demand since it can affect performance.
1533 uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1534 if ( xPersist.is() )
1538 //TODO/LATER: only storing if changed!
1539 xPersist->storeOwn();
1541 catch( uno::Exception& )
1543 // TODO/LATER: error handling
1544 bResult = sal_False;
1545 break;
1549 if ( !_bOasisFormat && !_bObjectsOnly )
1551 // copy replacement images for linked objects
1554 uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY );
1555 if ( xLink.is() && xLink->isLink() )
1557 ::rtl::OUString aMediaType;
1558 uno::Reference < io::XInputStream > xInStream = GetGraphicStream( xObj, &aMediaType );
1559 if ( xInStream.is() )
1560 InsertStreamIntoPicturesStorage_Impl( pImpl->mxStorage, xInStream, *pIter );
1563 catch( uno::Exception& )
1570 if ( bResult && _bOasisFormat )
1571 bResult = CommitImageSubStorage();
1573 if ( bResult && !_bObjectsOnly )
1577 ReleaseImageSubStorage();
1578 ::rtl::OUString aObjReplElement( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
1579 if ( !_bOasisFormat && pImpl->mxStorage->hasByName( aObjReplElement ) && pImpl->mxStorage->isStorageElement( aObjReplElement ) )
1580 pImpl->mxStorage->removeElement( aObjReplElement );
1582 catch( uno::Exception& )
1584 // TODO/LATER: error handling
1585 bResult = sal_False;
1588 return bResult;
1590 // -----------------------------------------------------------------------------
1591 uno::Reference< io::XInputStream > EmbeddedObjectContainer::GetGraphicReplacementStream(
1592 sal_Int64 nViewAspect,
1593 const uno::Reference< embed::XEmbeddedObject >& xObj,
1594 ::rtl::OUString* pMediaType )
1596 uno::Reference< io::XInputStream > xInStream;
1597 if ( xObj.is() )
1601 // retrieving of the visual representation can switch object to running state
1602 embed::VisualRepresentation aRep = xObj->getPreferredVisualRepresentation( nViewAspect );
1603 if ( pMediaType )
1604 *pMediaType = aRep.Flavor.MimeType;
1606 uno::Sequence < sal_Int8 > aSeq;
1607 aRep.Data >>= aSeq;
1608 xInStream = new ::comphelper::SequenceInputStream( aSeq );
1610 catch ( uno::Exception& )
1615 return xInStream;
1617 // -----------------------------------------------------------------------------
1618 sal_Bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed::XStorage >& _xStorage,bool _bClearModifedFlag)
1620 sal_Bool bError = sal_False;
1621 const uno::Sequence < ::rtl::OUString > aNames = GetObjectNames();
1622 const ::rtl::OUString* pIter = aNames.getConstArray();
1623 const ::rtl::OUString* pEnd = pIter + aNames.getLength();
1624 for(;pIter != pEnd;++pIter)
1626 uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter );
1627 OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
1628 if ( xObj.is() )
1630 uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
1631 if ( xPersist.is() )
1635 xPersist->setPersistentEntry( _xStorage,
1636 *pIter,
1637 embed::EntryInitModes::NO_INIT,
1638 uno::Sequence< beans::PropertyValue >(),
1639 uno::Sequence< beans::PropertyValue >() );
1642 catch( uno::Exception& )
1644 // TODO/LATER: error handling
1645 bError = sal_True;
1646 break;
1649 if ( _bClearModifedFlag )
1651 // if this method is used as part of SaveCompleted the object must stay unmodified after execution
1654 uno::Reference< util::XModifiable > xModif( xObj->getComponent(), uno::UNO_QUERY_THROW );
1655 if ( xModif->isModified() )
1656 xModif->setModified( sal_False );
1658 catch( uno::Exception& )
1664 return bError;