1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
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>
48 using namespace ::com::sun::star
;
53 struct hashObjectName_Impl
55 size_t operator()(const OUString Str
) const
57 return (size_t)Str
.hashCode();
61 struct eqObjectName_Impl
63 sal_Bool
operator()(const OUString Str1
, const OUString Str2
) const
65 return ( Str1
== Str2
);
69 typedef boost::unordered_map
72 ::com::sun::star::uno::Reference
< com::sun::star::embed::XEmbeddedObject
>,
76 EmbeddedObjectContainerNameMap
;
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;
90 const uno::Reference
< embed::XStorage
>& GetReplacements();
93 const uno::Reference
< embed::XStorage
>& EmbedImpl::GetReplacements()
95 if ( !mxImageStorage
.is() )
99 mxImageStorage
= mxStorage
->openStorageElement(
100 OUString("ObjectReplacements"), embed::ElementModes::READWRITE
);
102 catch (const uno::Exception
&)
104 mxImageStorage
= mxStorage
->openStorageElement(
105 OUString("ObjectReplacements"), embed::ElementModes::READ
);
109 if ( !mxImageStorage
.is() )
110 throw io::IOException();
112 return mxImageStorage
;
115 EmbeddedObjectContainer::EmbeddedObjectContainer()
117 pImpl
= new EmbedImpl
;
118 pImpl
->mxStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
119 pImpl
->bOwnsStorage
= true;
120 pImpl
->mpTempObjectContainer
= 0;
123 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference
< embed::XStorage
>& rStor
)
125 pImpl
= new EmbedImpl
;
126 pImpl
->mxStorage
= rStor
;
127 pImpl
->bOwnsStorage
= false;
128 pImpl
->mpTempObjectContainer
= 0;
131 EmbeddedObjectContainer::EmbeddedObjectContainer( const uno::Reference
< embed::XStorage
>& rStor
, const uno::Reference
< uno::XInterface
>& xModel
)
133 pImpl
= new EmbedImpl
;
134 pImpl
->mxStorage
= rStor
;
135 pImpl
->bOwnsStorage
= false;
136 pImpl
->mpTempObjectContainer
= 0;
137 pImpl
->m_xModel
= xModel
;
140 void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference
< embed::XStorage
>& rStor
)
142 ReleaseImageSubStorage();
144 if ( pImpl
->bOwnsStorage
)
145 pImpl
->mxStorage
->dispose();
147 pImpl
->mxStorage
= rStor
;
148 pImpl
->bOwnsStorage
= false;
151 sal_Bool
EmbeddedObjectContainer::CommitImageSubStorage()
153 if ( pImpl
->mxImageStorage
.is() )
157 sal_Bool bReadOnlyMode
= sal_True
;
158 uno::Reference
< beans::XPropertySet
> xSet(pImpl
->mxImageStorage
,uno::UNO_QUERY
);
161 // get the open mode from the parent storage
163 uno::Any aAny
= xSet
->getPropertyValue( OUString("OpenMode") );
164 if ( aAny
>>= nMode
)
165 bReadOnlyMode
= !(nMode
& embed::ElementModes::WRITE
);
166 } // if ( xSet.is() )
167 if ( !bReadOnlyMode
)
169 uno::Reference
< embed::XTransactedObject
> xTransact( pImpl
->mxImageStorage
, uno::UNO_QUERY_THROW
);
173 catch (const uno::Exception
&)
182 void EmbeddedObjectContainer::ReleaseImageSubStorage()
184 CommitImageSubStorage();
186 if ( pImpl
->mxImageStorage
.is() )
190 pImpl
->mxImageStorage
->dispose();
191 pImpl
->mxImageStorage
= uno::Reference
< embed::XStorage
>();
193 catch (const uno::Exception
&)
195 SAL_WARN( "comphelper.container", "Problems releasing image substorage!\n" );
200 EmbeddedObjectContainer::~EmbeddedObjectContainer()
202 ReleaseImageSubStorage();
204 if ( pImpl
->bOwnsStorage
)
205 pImpl
->mxStorage
->dispose();
207 delete pImpl
->mpTempObjectContainer
;
211 void EmbeddedObjectContainer::CloseEmbeddedObjects()
213 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
214 while ( aIt
!= pImpl
->maObjectContainer
.end() )
216 uno::Reference
< util::XCloseable
> xClose( (*aIt
).second
, uno::UNO_QUERY
);
221 xClose
->close( sal_True
);
223 catch (const uno::Exception
&)
232 OUString
EmbeddedObjectContainer::CreateUniqueObjectName()
234 OUString
aPersistName("Object ");
240 aStr
+= OUString::valueOf( i
++ );
242 while( HasEmbeddedObject( aStr
) );
243 // TODO/LATER: should we consider deleted objects?
248 uno::Sequence
< OUString
> EmbeddedObjectContainer::GetObjectNames()
250 uno::Sequence
< OUString
> aSeq( pImpl
->maObjectContainer
.size() );
251 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
253 while ( aIt
!= pImpl
->maObjectContainer
.end() )
254 aSeq
[nIdx
++] = (*aIt
++).first
;
258 sal_Bool
EmbeddedObjectContainer::HasEmbeddedObjects()
260 return pImpl
->maObjectContainer
.size() != 0;
263 sal_Bool
EmbeddedObjectContainer::HasEmbeddedObject( const OUString
& rName
)
265 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
266 if ( aIt
== pImpl
->maObjectContainer
.end() )
268 uno::Reference
< container::XNameAccess
> xAccess( pImpl
->mxStorage
, uno::UNO_QUERY
);
269 return xAccess
->hasByName(rName
);
275 sal_Bool
EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
)
277 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
278 while ( aIt
!= pImpl
->maObjectContainer
.end() )
280 if ( (*aIt
).second
== xObj
)
289 sal_Bool
EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString
& rName
)
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 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
295 return ( aIt
!= pImpl
->maObjectContainer
.end() );
298 OUString
EmbeddedObjectContainer::GetEmbeddedObjectName( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XEmbeddedObject
>& xObj
)
300 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
301 while ( aIt
!= pImpl
->maObjectContainer
.end() )
303 if ( (*aIt
).second
== xObj
)
309 SAL_WARN( "comphelper.container", "Unknown object!" );
313 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::GetEmbeddedObject( const OUString
& rName
)
315 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetEmbeddedObject" );
317 SAL_WARN_IF( rName
.isEmpty(), "comphelper.container", "Empty object name!");
319 uno::Reference
< embed::XEmbeddedObject
> xObj
;
320 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
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
)
331 OSL_ENSURE( aIt
!= pImpl
->maObjectContainer
.end() || xAccess
->hasByName(rName
), "Could not return object!" );
334 // check if object was already created
335 if ( aIt
!= pImpl
->maObjectContainer
.end() )
336 xObj
= (*aIt
).second
;
338 xObj
= Get_Impl( rName
, uno::Reference
< embed::XEmbeddedObject
>() );
343 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::Get_Impl( const OUString
& rName
, const uno::Reference
< embed::XEmbeddedObject
>& xCopy
)
345 uno::Reference
< embed::XEmbeddedObject
> xObj
;
348 // create the object from the storage
349 uno::Reference
< beans::XPropertySet
> xSet( pImpl
->mxStorage
, uno::UNO_QUERY
);
350 sal_Bool bReadOnlyMode
= sal_True
;
353 // get the open mode from the parent storage
355 uno::Any aAny
= xSet
->getPropertyValue( OUString("OpenMode") );
356 if ( aAny
>>= nMode
)
357 bReadOnlyMode
= !(nMode
& embed::ElementModes::WRITE
);
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 uno::Reference
< embed::XEmbeddedObjectCreator
> xFactory
= embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
363 uno::Sequence
< beans::PropertyValue
> aObjDescr( xCopy
.is() ? 2 : 1 );
364 aObjDescr
[0].Name
= "Parent";
365 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
368 aObjDescr
[1].Name
= "CloneFrom";
369 aObjDescr
[1].Value
<<= xCopy
;
372 uno::Sequence
< beans::PropertyValue
> aMediaDescr( 1 );
373 aMediaDescr
[0].Name
= "ReadOnly";
374 aMediaDescr
[0].Value
<<= bReadOnlyMode
;
375 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceInitFromEntry(
376 pImpl
->mxStorage
, rName
,
377 aMediaDescr
, aObjDescr
), uno::UNO_QUERY
);
379 // insert object into my list
380 AddEmbeddedObject( xObj
, rName
);
382 catch (uno::Exception
const& e
)
384 SAL_WARN("comphelper.container", "EmbeddedObjectContainer::Get_Impl: exception caught: " << e
.Message
);
390 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence
< sal_Int8
>& rClassId
,
391 const uno::Sequence
< beans::PropertyValue
>& rArgs
, OUString
& rNewName
)
393 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CreateEmbeddedObject" );
395 if ( rNewName
.isEmpty() )
396 rNewName
= CreateUniqueObjectName();
398 SAL_WARN_IF( HasEmbeddedObject(rNewName
), "comphelper.container", "Object to create already exists!");
400 // create object from classid by inserting it into storage
401 uno::Reference
< embed::XEmbeddedObject
> xObj
;
404 uno::Reference
< embed::XEmbeddedObjectCreator
> xFactory
= embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
406 uno::Sequence
< beans::PropertyValue
> aObjDescr( rArgs
.getLength() + 1 );
407 aObjDescr
[0].Name
= "Parent";
408 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
409 ::std::copy( rArgs
.getConstArray(), rArgs
.getConstArray() + rArgs
.getLength(), aObjDescr
.getArray() + 1 );
410 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceInitNew(
411 rClassId
, OUString(), pImpl
->mxStorage
, rNewName
,
412 aObjDescr
), uno::UNO_QUERY
);
414 AddEmbeddedObject( xObj
, rNewName
);
416 OSL_ENSURE( !xObj
.is() || xObj
->getCurrentState() != embed::EmbedStates::LOADED
,
417 "A freshly create object should be running always!\n" );
419 catch (uno::Exception
const& e
)
421 SAL_WARN("comphelper.container", "EmbeddedObjectContainer::CreateEmbeddedObject: exception caught: " << e
.Message
);
427 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::CreateEmbeddedObject( const uno::Sequence
< sal_Int8
>& rClassId
, OUString
& rNewName
)
429 return CreateEmbeddedObject( rClassId
, uno::Sequence
< beans::PropertyValue
>(), rNewName
);
432 void EmbeddedObjectContainer::AddEmbeddedObject( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XEmbeddedObject
>& xObj
, const OUString
& rName
)
434 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::AddEmbeddedObject" );
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 persistance 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!" );
446 // remember object - it needs to be in storage already
447 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
448 OSL_ENSURE( aIt
== pImpl
->maObjectContainer
.end(), "Element already inserted!" );
449 pImpl
->maObjectContainer
[ rName
] = xObj
;
450 uno::Reference
< container::XChild
> xChild( xObj
, uno::UNO_QUERY
);
451 if ( xChild
.is() && xChild
->getParent() != pImpl
->m_xModel
.get() )
452 xChild
->setParent( pImpl
->m_xModel
.get() );
454 // look for object in temorary container
455 if ( pImpl
->mpTempObjectContainer
)
457 aIt
= pImpl
->mpTempObjectContainer
->pImpl
->maObjectContainer
.begin();
458 while ( aIt
!= pImpl
->mpTempObjectContainer
->pImpl
->maObjectContainer
.end() )
460 if ( (*aIt
).second
== xObj
)
462 // copy replacement image from temporary container (if there is any)
463 OUString aTempName
= (*aIt
).first
;
465 uno::Reference
< io::XInputStream
> xStream
= pImpl
->mpTempObjectContainer
->GetGraphicStream( xObj
, &aMediaType
);
468 InsertGraphicStream( xStream
, rName
, aMediaType
);
470 pImpl
->mpTempObjectContainer
->RemoveGraphicStream( aTempName
);
473 // remove object from storage of temporary container
474 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
479 pImpl
->mpTempObjectContainer
->pImpl
->mxStorage
->removeElement( aTempName
);
481 catch (const uno::Exception
&)
486 // temp. container needs to forget the object
487 pImpl
->mpTempObjectContainer
->pImpl
->maObjectContainer
.erase( aIt
);
496 sal_Bool
EmbeddedObjectContainer::StoreEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
, OUString
& rName
, sal_Bool bCopy
)
498 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::StoreEmbeddedObject" );
500 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
501 if ( rName
.isEmpty() )
502 rName
= CreateUniqueObjectName();
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!");
510 // insert objects' storage into the container storage (if object has one)
515 uno::Sequence
< beans::PropertyValue
> aSeq
;
517 xPersist
->storeToEntry( pImpl
->mxStorage
, rName
, aSeq
, aSeq
);
520 //TODO/LATER: possible optimisation, don't store immediately
521 //xPersist->setPersistentEntry( pImpl->mxStorage, rName, embed::EntryInitModes::ENTRY_NO_INIT, aSeq, aSeq );
522 xPersist
->storeAsEntry( pImpl
->mxStorage
, rName
, aSeq
, aSeq
);
523 xPersist
->saveCompleted( sal_True
);
527 catch (uno::Exception
const& e
)
529 SAL_WARN("comphelper.container", "EmbeddedObjectContainer::StoreEmbeddedObject: exception caught: " << e
.Message
);
530 // TODO/LATER: better error recovery should keep storage intact
537 sal_Bool
EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
, OUString
& rName
)
539 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( Object )" );
540 // store it into the container storage
541 if ( StoreEmbeddedObject( xObj
, rName
, sal_False
) )
544 AddEmbeddedObject( xObj
, rName
);
551 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::InsertEmbeddedObject( const uno::Reference
< io::XInputStream
>& xStm
, OUString
& rNewName
)
553 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( InputStream )" );
555 if ( rNewName
.isEmpty() )
556 rNewName
= CreateUniqueObjectName();
558 // store it into the container storage
559 sal_Bool bIsStorage
= sal_False
;
562 // first try storage persistence
563 uno::Reference
< embed::XStorage
> xStore
= ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm
);
565 // storage was created from stream successfully
566 bIsStorage
= sal_True
;
568 uno::Reference
< embed::XStorage
> xNewStore
= pImpl
->mxStorage
->openStorageElement( rNewName
, embed::ElementModes::READWRITE
);
569 xStore
->copyToStorage( xNewStore
);
571 catch (const uno::Exception
&)
574 // it is storage persistence, but opening of new substorage or copying to it failed
575 return uno::Reference
< embed::XEmbeddedObject
>();
577 // stream didn't contain a storage, now try stream persistence
580 uno::Reference
< io::XStream
> xNewStream
= pImpl
->mxStorage
->openStreamElement( rNewName
, embed::ElementModes::READWRITE
);
581 ::comphelper::OStorageHelper::CopyInputToOutput( xStm
, xNewStream
->getOutputStream() );
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 uno::Reference
< beans::XPropertySet
> xProps( xNewStream
, uno::UNO_QUERY_THROW
);
587 xProps
->setPropertyValue( OUString( "MediaType" ),
588 uno::makeAny( OUString( "application/vnd.sun.star.oleobject" ) ) );
590 catch (uno::Exception
const& e
)
592 // complete disaster!
593 SAL_WARN("comphelper.container", "EmbeddedObjectContainer::InsertEmbeddedObject: exception caught: " << e
.Message
);
594 return uno::Reference
< embed::XEmbeddedObject
>();
598 // stream was copied into the container storage in either way, now try to open something form it
599 uno::Reference
< embed::XEmbeddedObject
> xRet
= GetEmbeddedObject( rNewName
);
603 // no object could be created, so withdraw insertion
604 pImpl
->mxStorage
->removeElement( rNewName
);
606 catch (const uno::Exception
&)
613 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::InsertEmbeddedObject( const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& aMedium
, OUString
& rNewName
)
615 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedObject( MediaDescriptor )" );
617 if ( rNewName
.isEmpty() )
618 rNewName
= CreateUniqueObjectName();
620 uno::Reference
< embed::XEmbeddedObject
> xObj
;
623 uno::Reference
< embed::XEmbeddedObjectCreator
> xFactory
= embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
624 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
625 aObjDescr
[0].Name
= "Parent";
626 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
627 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceInitFromMediaDescriptor(
628 pImpl
->mxStorage
, rNewName
, aMedium
, aObjDescr
), uno::UNO_QUERY
);
629 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
631 OSL_ENSURE( !xObj
.is() || xObj
->getCurrentState() != embed::EmbedStates::LOADED
,
632 "A freshly create object should be running always!\n" );
634 // possible optimization: store later!
636 xPersist
->storeOwn();
638 AddEmbeddedObject( xObj
, rNewName
);
640 catch (const uno::Exception
&)
647 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::InsertEmbeddedLink( const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& aMedium
, OUString
& rNewName
)
649 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertEmbeddedLink" );
651 if ( rNewName
.isEmpty() )
652 rNewName
= CreateUniqueObjectName();
654 uno::Reference
< embed::XEmbeddedObject
> xObj
;
657 uno::Reference
< embed::XEmbeddedObjectCreator
> xFactory
= embed::EmbeddedObjectCreator::create(::comphelper::getProcessComponentContext());
658 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
659 aObjDescr
[0].Name
= "Parent";
660 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
661 xObj
= uno::Reference
< embed::XEmbeddedObject
>( xFactory
->createInstanceLink(
662 pImpl
->mxStorage
, rNewName
, aMedium
, aObjDescr
), uno::UNO_QUERY
);
664 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
666 OSL_ENSURE( !xObj
.is() || xObj
->getCurrentState() != embed::EmbedStates::LOADED
,
667 "A freshly create object should be running always!\n" );
669 // possible optimization: store later!
671 xPersist
->storeOwn();
673 AddEmbeddedObject( xObj
, rNewName
);
675 catch (uno::Exception
const& e
)
677 SAL_WARN("comphelper", "EmbeddedObjectContainer::InsertEmbeddedLink: "
678 "exception caught: " << e
.Message
);
684 sal_Bool
EmbeddedObjectContainer::TryToCopyGraphReplacement( EmbeddedObjectContainer
& rSrc
,
685 const OUString
& aOrigName
,
686 const OUString
& aTargetName
)
688 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::TryToCopyGraphReplacement" );
690 sal_Bool bResult
= sal_False
;
692 if ( ( &rSrc
!= this || !aOrigName
.equals( aTargetName
) ) && !aOrigName
.isEmpty() && !aTargetName
.isEmpty() )
695 uno::Reference
< io::XInputStream
> xGrStream
= rSrc
.GetGraphicStream( aOrigName
, &aMediaType
);
696 if ( xGrStream
.is() )
697 bResult
= InsertGraphicStream( xGrStream
, aTargetName
, aMediaType
);
703 uno::Reference
< embed::XEmbeddedObject
> EmbeddedObjectContainer::CopyAndGetEmbeddedObject( EmbeddedObjectContainer
& rSrc
, const uno::Reference
< embed::XEmbeddedObject
>& xObj
, OUString
& rName
)
705 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CopyAndGetEmbeddedObject" );
707 uno::Reference
< embed::XEmbeddedObject
> xResult
;
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
714 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY_THROW
);
715 aOrigName
= xPersist
->getEntryName();
717 catch (const uno::Exception
&)
721 if ( rName
.isEmpty() )
722 rName
= CreateUniqueObjectName();
724 // objects without persistance are not really stored by the method
725 if ( xObj
.is() && StoreEmbeddedObject( xObj
, rName
, sal_True
) )
727 xResult
= Get_Impl( rName
, xObj
);
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
734 uno::Reference
< embed::XLinkageSupport
> xOrigLinkage( xObj
, uno::UNO_QUERY
);
735 if ( xOrigLinkage
.is() && xOrigLinkage
->isLink() )
737 // this is a OOo link, it has no persistence
738 OUString aURL
= xOrigLinkage
->getLinkURL();
739 if ( aURL
.isEmpty() )
740 throw uno::RuntimeException();
742 // create new linked object from the URL the link is based on
743 uno::Reference
< embed::XEmbeddedObjectCreator
> xCreator
=
744 embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
746 uno::Sequence
< beans::PropertyValue
> aMediaDescr( 1 );
747 aMediaDescr
[0].Name
= "URL";
748 aMediaDescr
[0].Value
<<= aURL
;
749 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
750 aObjDescr
[0].Name
= "Parent";
751 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
752 xResult
= uno::Reference
< embed::XEmbeddedObject
>(
753 xCreator
->createInstanceLink(
758 uno::UNO_QUERY_THROW
);
762 // the component is required for copying of this object
763 if ( xObj
->getCurrentState() == embed::EmbedStates::LOADED
)
764 xObj
->changeState( embed::EmbedStates::RUNNING
);
766 // this must be an object based on properties, otherwise we can not copy it currently
767 uno::Reference
< beans::XPropertySet
> xOrigProps( xObj
->getComponent(), uno::UNO_QUERY_THROW
);
769 // use object class ID to create a new one and tranfer all the properties
770 uno::Reference
< embed::XEmbeddedObjectCreator
> xCreator
=
771 embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
773 uno::Sequence
< beans::PropertyValue
> aObjDescr( 1 );
774 aObjDescr
[0].Name
= "Parent";
775 aObjDescr
[0].Value
<<= pImpl
->m_xModel
.get();
776 xResult
= uno::Reference
< embed::XEmbeddedObject
>(
777 xCreator
->createInstanceInitNew(
779 xObj
->getClassName(),
783 uno::UNO_QUERY_THROW
);
785 if ( xResult
->getCurrentState() == embed::EmbedStates::LOADED
)
786 xResult
->changeState( embed::EmbedStates::RUNNING
);
788 uno::Reference
< beans::XPropertySet
> xTargetProps( xResult
->getComponent(), uno::UNO_QUERY_THROW
);
790 // copy all the properties from xOrigProps to xTargetProps
791 uno::Reference
< beans::XPropertySetInfo
> xOrigInfo
= xOrigProps
->getPropertySetInfo();
792 if ( !xOrigInfo
.is() )
793 throw uno::RuntimeException();
795 uno::Sequence
< beans::Property
> aPropertiesList
= xOrigInfo
->getProperties();
796 for ( sal_Int32 nInd
= 0; nInd
< aPropertiesList
.getLength(); nInd
++ )
800 xTargetProps
->setPropertyValue(
801 aPropertiesList
[nInd
].Name
,
802 xOrigProps
->getPropertyValue( aPropertiesList
[nInd
].Name
) );
804 catch (const beans::PropertyVetoException
&)
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" );
814 AddEmbeddedObject( xResult
, rName
);
816 catch (const uno::Exception
&)
822 xResult
->close( sal_True
);
824 catch (const uno::Exception
&)
827 xResult
= uno::Reference
< embed::XEmbeddedObject
>();
833 SAL_WARN_IF( !xResult
.is(), "comphelper.container", "Can not copy embedded object that has no persistance!\n" );
837 // the object is successfully copied, try to copy graphical replacement
838 if ( !aOrigName
.isEmpty() )
839 TryToCopyGraphReplacement( rSrc
, aOrigName
, rName
);
841 // the object might need the size to be set
844 if ( xResult
->getStatus( embed::Aspects::MSOLE_CONTENT
) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD
)
845 xResult
->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT
,
846 xObj
->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
) );
848 catch (const uno::Exception
&)
856 sal_Bool
EmbeddedObjectContainer::MoveEmbeddedObject( EmbeddedObjectContainer
& rSrc
, const uno::Reference
< embed::XEmbeddedObject
>& xObj
, OUString
& rName
)
858 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Object )" );
860 // get the object name before(!) it is assigned to a new storage
861 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
864 aName
= xPersist
->getEntryName();
866 // now move the object to the new container; the returned name is the new persist name in this container
871 bRet
= InsertEmbeddedObject( xObj
, rName
);
873 TryToCopyGraphReplacement( rSrc
, aName
, rName
);
875 catch (const uno::Exception
&)
877 SAL_WARN( "comphelper.container", "Failed to insert embedded object into storage!" );
883 // now remove the object from the former container
885 EmbeddedObjectContainerNameMap::iterator aIt
= rSrc
.pImpl
->maObjectContainer
.begin();
886 while ( aIt
!= rSrc
.pImpl
->maObjectContainer
.end() )
888 if ( (*aIt
).second
== xObj
)
890 rSrc
.pImpl
->maObjectContainer
.erase( aIt
);
898 SAL_WARN_IF( !bRet
, "comphelper.container", "Object not found for removal!" );
901 // now it's time to remove the storage from the container storage
905 rSrc
.pImpl
->mxStorage
->removeElement( aName
);
907 catch (const uno::Exception
&)
909 SAL_WARN( "comphelper.container", "Failed to remove object from storage!" );
914 // rSrc.RemoveGraphicStream( aName );
920 // #i119941, bKeepToTempStorage: use to specify whether store the removed object to temporary storage+
921 sal_Bool
EmbeddedObjectContainer::RemoveEmbeddedObject( const OUString
& rName
, sal_Bool bClose
, sal_Bool bKeepToTempStorage
)
923 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Name )" );
925 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( rName
);
927 //return RemoveEmbeddedObject( xObj, bClose );
928 return RemoveEmbeddedObject( xObj
, bClose
, bKeepToTempStorage
);
933 sal_Bool
EmbeddedObjectContainer::MoveEmbeddedObject( const OUString
& rName
, EmbeddedObjectContainer
& rCnt
)
935 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::MoveEmbeddedObject( Name )" );
938 EmbeddedObjectContainerNameMap::iterator aIt2
= rCnt
.pImpl
->maObjectContainer
.find( rName
);
939 OSL_ENSURE( aIt2
== rCnt
.pImpl
->maObjectContainer
.end(), "Object does already exist in target container!" );
941 if ( aIt2
!= rCnt
.pImpl
->maObjectContainer
.end() )
944 uno::Reference
< embed::XEmbeddedObject
> xObj
;
945 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.find( rName
);
946 if ( aIt
!= pImpl
->maObjectContainer
.end() )
948 xObj
= (*aIt
).second
;
954 OUString
aName( rName
);
955 rCnt
.InsertEmbeddedObject( xObj
, aName
);
956 pImpl
->maObjectContainer
.erase( aIt
);
957 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
959 pImpl
->mxStorage
->removeElement( rName
);
963 // copy storages; object *must* have persistence!
964 uno::Reference
< embed::XStorage
> xOld
= pImpl
->mxStorage
->openStorageElement( rName
, embed::ElementModes::READ
);
965 uno::Reference
< embed::XStorage
> xNew
= rCnt
.pImpl
->mxStorage
->openStorageElement( rName
, embed::ElementModes::READWRITE
);
966 xOld
->copyToStorage( xNew
);
969 rCnt
.TryToCopyGraphReplacement( *this, rName
, rName
);
970 // RemoveGraphicStream( rName );
974 catch (const uno::Exception
&)
976 SAL_WARN( "comphelper.container", "Could not move object!");
982 SAL_WARN( "comphelper.container", "Unknown object!");
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 sal_Bool
EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
, sal_Bool bClose
, sal_Bool bKeepToTempStorage
)
990 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveEmbeddedObject( Object )" );
992 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
995 aName
= xPersist
->getEntryName();
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() );
1002 // if the object has a persistance 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!" );
1006 // try to close it if permitted
1009 uno::Reference
< ::util::XCloseable
> xClose( xObj
, uno::UNO_QUERY
);
1012 xClose
->close( sal_True
);
1014 catch (const util::CloseVetoException
&)
1022 // somebody still needs the object, so we must assign a temporary persistence
1025 // if ( xPersist.is() )
1026 if ( xPersist
.is() && bKeepToTempStorage
) // #i119941
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;
1034 OUString aTmpPersistName = "Object ";
1035 aTmpPersistName += OUString::valueOf( (sal_Int32) pImpl->maTempObjectContainer.size() );
1037 xPersist->storeAsEntry( pImpl->mxTempStorage, aTmpPersistName, aSeq, aSeq );
1038 xPersist->saveCompleted( sal_True );
1040 pImpl->maTempObjectContainer[ aTmpPersistName ] = uno::Reference < embed::XEmbeddedObject >();
1043 if ( !pImpl
->mpTempObjectContainer
)
1045 pImpl
->mpTempObjectContainer
= new EmbeddedObjectContainer();
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 OUString aOrigStorMediaType
;
1051 uno::Reference
< beans::XPropertySet
> xStorProps( pImpl
->mxStorage
, uno::UNO_QUERY_THROW
);
1052 static const OUString
s_sMediaType("MediaType");
1053 xStorProps
->getPropertyValue( s_sMediaType
) >>= aOrigStorMediaType
;
1055 SAL_WARN_IF( aOrigStorMediaType
.isEmpty(), "comphelper.container", "No valuable media type in the storage!\n" );
1057 uno::Reference
< beans::XPropertySet
> xTargetStorProps(
1058 pImpl
->mpTempObjectContainer
->pImpl
->mxStorage
,
1059 uno::UNO_QUERY_THROW
);
1060 xTargetStorProps
->setPropertyValue( s_sMediaType
,uno::makeAny( aOrigStorMediaType
) );
1062 catch (const uno::Exception
&)
1064 SAL_WARN( "comphelper.container", "Can not set the new media type to a storage!\n" );
1068 OUString aTempName
, aMediaType
;
1069 pImpl
->mpTempObjectContainer
->InsertEmbeddedObject( xObj
, aTempName
);
1071 uno::Reference
< io::XInputStream
> xStream
= GetGraphicStream( xObj
, &aMediaType
);
1073 pImpl
->mpTempObjectContainer
->InsertGraphicStream( xStream
, aTempName
, aMediaType
);
1075 // object is stored, so at least it can be set to loaded state
1076 xObj
->changeState( embed::EmbedStates::LOADED
);
1079 // objects without persistence need to stay in running state if they shall not be closed
1080 xObj
->changeState( embed::EmbedStates::RUNNING
);
1082 catch (const uno::Exception
&)
1088 sal_Bool bFound
= sal_False
;
1089 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
1090 while ( aIt
!= pImpl
->maObjectContainer
.end() )
1092 if ( (*aIt
).second
== xObj
)
1094 pImpl
->maObjectContainer
.erase( aIt
);
1096 uno::Reference
< container::XChild
> xChild( xObj
, uno::UNO_QUERY
);
1098 xChild
->setParent( uno::Reference
< uno::XInterface
>() );
1105 SAL_WARN_IF( !bFound
,"comphelper.container", "Object not found for removal!" );
1107 if ( xPersist
.is() && bKeepToTempStorage
) // #i119941#
1109 // remove replacement image (if there is one)
1110 RemoveGraphicStream( aName
);
1112 // now it's time to remove the storage from the container storage
1115 #if OSL_DEBUG_LEVEL > 1
1116 // if the object has a persistance 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!" );
1119 if ( xPersist
.is() && pImpl
->mxStorage
->hasByName( aName
) )
1120 pImpl
->mxStorage
->removeElement( aName
);
1122 catch (const uno::Exception
&)
1124 SAL_WARN( "comphelper.container", "Failed to remove object from storage!" );
1132 sal_Bool
EmbeddedObjectContainer::CloseEmbeddedObject( const uno::Reference
< embed::XEmbeddedObject
>& xObj
)
1134 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::CloseEmbeddedObject" );
1136 // disconnect the object from the container and close it if possible
1138 sal_Bool bFound
= sal_False
;
1139 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
1140 while ( aIt
!= pImpl
->maObjectContainer
.end() )
1142 if ( (*aIt
).second
== xObj
)
1144 pImpl
->maObjectContainer
.erase( aIt
);
1154 uno::Reference
< ::util::XCloseable
> xClose( xObj
, uno::UNO_QUERY
);
1157 xClose
->close( sal_True
);
1159 catch (const uno::Exception
&)
1161 // it is no problem if the object is already closed
1162 // TODO/LATER: what if the object can not be closed?
1169 uno::Reference
< io::XInputStream
> EmbeddedObjectContainer::GetGraphicStream( const OUString
& aName
, OUString
* pMediaType
)
1171 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Name )" );
1173 uno::Reference
< io::XInputStream
> xStream
;
1175 SAL_WARN_IF( aName
.isEmpty(), "comphelper.container", "Retrieving graphic for unknown object!" );
1176 if ( !aName
.isEmpty() )
1180 uno::Reference
< embed::XStorage
> xReplacements
= pImpl
->GetReplacements();
1181 uno::Reference
< io::XStream
> xGraphicStream
= xReplacements
->openStreamElement( aName
, embed::ElementModes::READ
);
1182 xStream
= xGraphicStream
->getInputStream();
1185 uno::Reference
< beans::XPropertySet
> xSet( xStream
, uno::UNO_QUERY
);
1188 uno::Any aAny
= xSet
->getPropertyValue( OUString("MediaType") );
1189 aAny
>>= *pMediaType
;
1193 catch (const uno::Exception
&)
1201 uno::Reference
< io::XInputStream
> EmbeddedObjectContainer::GetGraphicStream( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XEmbeddedObject
>& xObj
, OUString
* pMediaType
)
1203 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::GetGraphicStream( Object )" );
1205 // get the object name
1207 EmbeddedObjectContainerNameMap::iterator aIt
= pImpl
->maObjectContainer
.begin();
1208 while ( aIt
!= pImpl
->maObjectContainer
.end() )
1210 if ( (*aIt
).second
== xObj
)
1212 aName
= (*aIt
).first
;
1219 // try to load it from the container storage
1220 return GetGraphicStream( aName
, pMediaType
);
1223 sal_Bool
EmbeddedObjectContainer::InsertGraphicStream( const com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
>& rStream
, const OUString
& rObjectName
, const OUString
& rMediaType
)
1225 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStream" );
1229 uno::Reference
< embed::XStorage
> xReplacements
= pImpl
->GetReplacements();
1231 // store it into the subfolder
1232 uno::Reference
< io::XOutputStream
> xOutStream
;
1233 uno::Reference
< io::XStream
> xGraphicStream
= xReplacements
->openStreamElement( rObjectName
,
1234 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
1235 xOutStream
= xGraphicStream
->getOutputStream();
1236 ::comphelper::OStorageHelper::CopyInputToOutput( rStream
, xOutStream
);
1237 xOutStream
->flush();
1239 uno::Reference
< beans::XPropertySet
> xPropSet( xGraphicStream
, uno::UNO_QUERY
);
1240 if ( !xPropSet
.is() )
1241 throw uno::RuntimeException();
1243 xPropSet
->setPropertyValue( OUString("UseCommonStoragePasswordEncryption"),
1244 uno::makeAny( (sal_Bool
)sal_True
) );
1246 aAny
<<= rMediaType
;
1247 xPropSet
->setPropertyValue( OUString("MediaType"), aAny
);
1249 xPropSet
->setPropertyValue( OUString("Compressed"),
1250 uno::makeAny( (sal_Bool
)sal_True
) );
1252 catch (const uno::Exception
&)
1260 sal_Bool
EmbeddedObjectContainer::InsertGraphicStreamDirectly( const com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
>& rStream
, const OUString
& rObjectName
, const OUString
& rMediaType
)
1262 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::InsertGraphicStreamDirectly" );
1266 uno::Reference
< embed::XStorage
> xReplacement
= pImpl
->GetReplacements();
1267 uno::Reference
< embed::XOptimizedStorage
> xOptRepl( xReplacement
, uno::UNO_QUERY_THROW
);
1269 // store it into the subfolder
1270 uno::Sequence
< beans::PropertyValue
> aProps( 3 );
1271 aProps
[0].Name
= "MediaType";
1272 aProps
[0].Value
<<= rMediaType
;
1273 aProps
[1].Name
= "UseCommonStoragePasswordEncryption";
1274 aProps
[1].Value
<<= (sal_Bool
)sal_True
;
1275 aProps
[2].Name
= "Compressed";
1276 aProps
[2].Value
<<= (sal_Bool
)sal_True
;
1278 if ( xReplacement
->hasByName( rObjectName
) )
1279 xReplacement
->removeElement( rObjectName
);
1281 xOptRepl
->insertStreamElementDirect( rObjectName
, rStream
, aProps
);
1283 catch (const uno::Exception
&)
1292 sal_Bool
EmbeddedObjectContainer::RemoveGraphicStream( const OUString
& rObjectName
)
1294 SAL_INFO( "comphelper.container", "comphelper (mv76033) comphelper::EmbeddedObjectContainer::RemoveGraphicStream" );
1298 uno::Reference
< embed::XStorage
> xReplacements
= pImpl
->GetReplacements();
1299 xReplacements
->removeElement( rObjectName
);
1301 catch (const uno::Exception
&)
1309 void InsertStreamIntoPicturesStorage_Impl( const uno::Reference
< embed::XStorage
>& xDocStor
,
1310 const uno::Reference
< io::XInputStream
>& xInStream
,
1311 const OUString
& aStreamName
)
1313 OSL_ENSURE( !aStreamName
.isEmpty() && xInStream
.is() && xDocStor
.is(), "Misuse of the method!\n" );
1317 uno::Reference
< embed::XStorage
> xPictures
= xDocStor
->openStorageElement(
1318 OUString( "Pictures" ),
1319 embed::ElementModes::READWRITE
);
1320 uno::Reference
< io::XStream
> xObjReplStr
= xPictures
->openStreamElement(
1322 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
1323 uno::Reference
< io::XOutputStream
> xOutStream(
1324 xObjReplStr
->getInputStream(), uno::UNO_QUERY_THROW
);
1326 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream
, xOutStream
);
1327 xOutStream
->closeOutput();
1329 uno::Reference
< embed::XTransactedObject
> xTransact( xPictures
, uno::UNO_QUERY
);
1330 if ( xTransact
.is() )
1331 xTransact
->commit();
1333 catch (const uno::Exception
&)
1335 SAL_WARN( "comphelper.container", "The pictures storage is not available!\n" );
1340 // -----------------------------------------------------------------------------
1341 sal_Bool
EmbeddedObjectContainer::StoreAsChildren(sal_Bool _bOasisFormat
,sal_Bool _bCreateEmbedded
,const uno::Reference
< embed::XStorage
>& _xStorage
)
1343 sal_Bool bResult
= sal_False
;
1346 comphelper::EmbeddedObjectContainer
aCnt( _xStorage
);
1347 const uno::Sequence
< OUString
> aNames
= GetObjectNames();
1348 const OUString
* pIter
= aNames
.getConstArray();
1349 const OUString
* pEnd
= pIter
+ aNames
.getLength();
1350 for(;pIter
!= pEnd
;++pIter
)
1352 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( *pIter
);
1353 SAL_WARN_IF( !xObj
.is(), "comphelper.container", "An empty entry in the embedded objects list!\n" );
1356 sal_Bool bSwitchBackToLoaded
= sal_False
;
1357 uno::Reference
< embed::XLinkageSupport
> xLink( xObj
, uno::UNO_QUERY
);
1359 uno::Reference
< io::XInputStream
> xStream
;
1360 OUString aMediaType
;
1362 sal_Int32 nCurState
= xObj
->getCurrentState();
1363 if ( nCurState
== embed::EmbedStates::LOADED
|| nCurState
== embed::EmbedStates::RUNNING
)
1365 // means that the object is not active
1366 // copy replacement image from old to new container
1367 xStream
= GetGraphicStream( xObj
, &aMediaType
);
1370 if ( !xStream
.is() )
1372 // the image must be regenerated
1373 // TODO/LATER: another aspect could be used
1374 if ( xObj
->getCurrentState() == embed::EmbedStates::LOADED
)
1375 bSwitchBackToLoaded
= sal_True
;
1377 xStream
= GetGraphicReplacementStream(
1378 embed::Aspects::MSOLE_CONTENT
,
1383 if ( _bOasisFormat
|| (xLink
.is() && xLink
->isLink()) )
1387 if ( _bOasisFormat
)
1389 // if it is an embedded object or the optimized inserting fails the normal inserting should be done
1390 if ( _bCreateEmbedded
1391 || !aCnt
.InsertGraphicStreamDirectly( xStream
, *pIter
, aMediaType
) )
1392 aCnt
.InsertGraphicStream( xStream
, *pIter
, aMediaType
);
1396 // it is a linked object exported into SO7 format
1397 InsertStreamIntoPicturesStorage_Impl( _xStorage
, xStream
, *pIter
);
1402 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1403 if ( xPersist
.is() )
1405 uno::Sequence
< beans::PropertyValue
> aArgs( _bOasisFormat
? 2 : 3 );
1406 aArgs
[0].Name
= "StoreVisualReplacement";
1407 aArgs
[0].Value
<<= (sal_Bool
)( !_bOasisFormat
);
1409 // if it is an embedded object or the optimized inserting fails the normal inserting should be done
1410 aArgs
[1].Name
= "CanTryOptimization";
1411 aArgs
[1].Value
<<= !_bCreateEmbedded
;
1412 if ( !_bOasisFormat
)
1414 // if object has no cached replacement it will use this one
1415 aArgs
[2].Name
= "VisualReplacement";
1416 aArgs
[2].Value
<<= xStream
;
1421 xPersist
->storeAsEntry( _xStorage
, xPersist
->getEntryName(), uno::Sequence
< beans::PropertyValue
>(), aArgs
);
1423 catch (const embed::WrongStateException
&)
1425 SAL_WARN("comphelper.container", "failed to store '" << *pIter
<< "'");
1429 if ( bSwitchBackToLoaded
)
1430 // switch back to loaded state; that way we have a minimum cache confusion
1431 xObj
->changeState( embed::EmbedStates::LOADED
);
1435 bResult
= aCnt
.CommitImageSubStorage();
1438 catch (const uno::Exception
& e
)
1440 // TODO/LATER: error handling
1441 bResult
= sal_False
;
1442 SAL_WARN("comphelper.container", "failed. Message: " << e
.Message
);
1445 // the old SO6 format does not store graphical replacements
1446 if ( !_bOasisFormat
&& bResult
)
1450 // the substorage still can not be locked by the embedded object conteiner
1451 OUString
aObjReplElement( "ObjectReplacements" );
1452 if ( _xStorage
->hasByName( aObjReplElement
) && _xStorage
->isStorageElement( aObjReplElement
) )
1453 _xStorage
->removeElement( aObjReplElement
);
1455 catch (const uno::Exception
&)
1457 // TODO/LATER: error handling;
1458 bResult
= sal_False
;
1463 // -----------------------------------------------------------------------------
1464 sal_Bool
EmbeddedObjectContainer::StoreChildren(sal_Bool _bOasisFormat
,sal_Bool _bObjectsOnly
)
1466 sal_Bool bResult
= sal_True
;
1467 const uno::Sequence
< OUString
> aNames
= GetObjectNames();
1468 const OUString
* pIter
= aNames
.getConstArray();
1469 const OUString
* pEnd
= pIter
+ aNames
.getLength();
1470 for(;pIter
!= pEnd
;++pIter
)
1472 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( *pIter
);
1473 SAL_WARN_IF( !xObj
.is(), "comphelper.container", "An empty entry in the embedded objects list!\n" );
1476 sal_Int32 nCurState
= xObj
->getCurrentState();
1477 if ( _bOasisFormat
&& nCurState
!= embed::EmbedStates::LOADED
&& nCurState
!= embed::EmbedStates::RUNNING
)
1479 // means that the object is active
1480 // the image must be regenerated
1481 OUString aMediaType
;
1483 // TODO/LATER: another aspect could be used
1484 uno::Reference
< io::XInputStream
> xStream
=
1485 GetGraphicReplacementStream(
1486 embed::Aspects::MSOLE_CONTENT
,
1491 if ( !InsertGraphicStreamDirectly( xStream
, *pIter
, aMediaType
) )
1492 InsertGraphicStream( xStream
, *pIter
, aMediaType
);
1496 // TODO/LATER: currently the object by default does not cache replacement image
1497 // that means that if somebody loads SO7 document and store its objects using
1498 // this method the images might be lost.
1499 // Currently this method is only used on storing to alien formats, that means
1500 // that SO7 documents storing does not use it, and all other filters are
1501 // based on OASIS format. But if it changes the method must be fixed. The fix
1502 // must be done only on demand since it can affect performance.
1504 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1505 if ( xPersist
.is() )
1509 //TODO/LATER: only storing if changed!
1510 //xPersist->storeOwn(); //commented, i120168
1512 // begin:all charts will be persited as xml format on disk when saving, which is time consuming.
1513 // '_bObjectsOnly' mean we are storing to alien formats.
1514 // 'isStorageElement' mean current object is NOT an MS OLE format. (may also include in future), i120168
1515 if (_bObjectsOnly
&& (nCurState
== embed::EmbedStates::LOADED
|| nCurState
== embed::EmbedStates::RUNNING
)
1516 && (pImpl
->mxStorage
->isStorageElement( *pIter
) ))
1518 uno::Reference
< util::XModifiable
> xModifiable( xObj
->getComponent(), uno::UNO_QUERY
);
1519 if ( xModifiable
.is() && xModifiable
->isModified())
1521 xPersist
->storeOwn();
1525 //do nothing.embeded model is not modified, no need to persist.
1528 else //the embeded object is in active status, always store back it.
1530 xPersist
->storeOwn();
1534 catch (const uno::Exception
&)
1536 // TODO/LATER: error handling
1537 bResult
= sal_False
;
1542 if ( !_bOasisFormat
&& !_bObjectsOnly
)
1544 // copy replacement images for linked objects
1547 uno::Reference
< embed::XLinkageSupport
> xLink( xObj
, uno::UNO_QUERY
);
1548 if ( xLink
.is() && xLink
->isLink() )
1550 OUString aMediaType
;
1551 uno::Reference
< io::XInputStream
> xInStream
= GetGraphicStream( xObj
, &aMediaType
);
1552 if ( xInStream
.is() )
1553 InsertStreamIntoPicturesStorage_Impl( pImpl
->mxStorage
, xInStream
, *pIter
);
1556 catch (const uno::Exception
&)
1563 if ( bResult
&& _bOasisFormat
)
1564 bResult
= CommitImageSubStorage();
1566 if ( bResult
&& !_bObjectsOnly
)
1570 ReleaseImageSubStorage();
1571 OUString
aObjReplElement( "ObjectReplacements" );
1572 if ( !_bOasisFormat
&& pImpl
->mxStorage
->hasByName( aObjReplElement
) && pImpl
->mxStorage
->isStorageElement( aObjReplElement
) )
1573 pImpl
->mxStorage
->removeElement( aObjReplElement
);
1575 catch (const uno::Exception
&)
1577 // TODO/LATER: error handling
1578 bResult
= sal_False
;
1583 // -----------------------------------------------------------------------------
1584 uno::Reference
< io::XInputStream
> EmbeddedObjectContainer::GetGraphicReplacementStream(
1585 sal_Int64 nViewAspect
,
1586 const uno::Reference
< embed::XEmbeddedObject
>& xObj
,
1587 OUString
* pMediaType
)
1589 uno::Reference
< io::XInputStream
> xInStream
;
1594 // retrieving of the visual representation can switch object to running state
1595 embed::VisualRepresentation aRep
= xObj
->getPreferredVisualRepresentation( nViewAspect
);
1597 *pMediaType
= aRep
.Flavor
.MimeType
;
1599 uno::Sequence
< sal_Int8
> aSeq
;
1601 xInStream
= new ::comphelper::SequenceInputStream( aSeq
);
1603 catch (const uno::Exception
&)
1610 // -----------------------------------------------------------------------------
1611 sal_Bool
EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference
< embed::XStorage
>& _xStorage
,bool _bClearModifedFlag
)
1613 sal_Bool bError
= sal_False
;
1614 const uno::Sequence
< OUString
> aNames
= GetObjectNames();
1615 const OUString
* pIter
= aNames
.getConstArray();
1616 const OUString
* pEnd
= pIter
+ aNames
.getLength();
1617 for(;pIter
!= pEnd
;++pIter
)
1619 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObject( *pIter
);
1620 SAL_WARN_IF( !xObj
.is(), "comphelper.container", "An empty entry in the embedded objects list!\n" );
1623 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
1624 if ( xPersist
.is() )
1628 xPersist
->setPersistentEntry( _xStorage
,
1630 embed::EntryInitModes::NO_INIT
,
1631 uno::Sequence
< beans::PropertyValue
>(),
1632 uno::Sequence
< beans::PropertyValue
>() );
1635 catch (const uno::Exception
&)
1637 // TODO/LATER: error handling
1642 if ( _bClearModifedFlag
)
1644 // if this method is used as part of SaveCompleted the object must stay unmodified after execution
1647 uno::Reference
< util::XModifiable
> xModif( xObj
->getComponent(), uno::UNO_QUERY_THROW
);
1648 if ( xModif
->isModified() )
1649 xModif
->setModified( sal_False
);
1651 catch (const uno::Exception
&)
1661 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */