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 .
22 #include <com/sun/star/io/XStream.hpp>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/embed/XTransactedObject.hpp>
25 #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
26 #include <com/sun/star/embed/XEmbedObjectFactory.hpp>
27 #include <com/sun/star/embed/ElementModes.hpp>
28 #include <com/sun/star/embed/XEmbeddedObject.hpp>
29 #include <com/sun/star/embed/XEmbedPersist.hpp>
30 #include <com/sun/star/embed/EntryInitModes.hpp>
31 #include <com/sun/star/embed/EmbedStates.hpp>
32 #include <com/sun/star/embed/Aspects.hpp>
33 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
34 #include <sot/storage.hxx>
35 #include <tools/debug.hxx>
36 #include <unotools/streamwrap.hxx>
37 #include <unotools/tempfile.hxx>
39 #include <svtools/embedhlp.hxx>
40 #include <unotools/ucbstreamhelper.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <comphelper/storagehelper.hxx>
43 #include <comphelper/embeddedobjectcontainer.hxx>
45 #include <comphelper/classids.hxx>
47 #include "svx/xmleohlp.hxx"
48 #include <boost/scoped_ptr.hpp>
50 using namespace ::osl
;
51 using namespace ::cppu
;
52 using namespace ::utl
;
53 using namespace ::com::sun::star
;
54 using namespace ::com::sun::star::document
;
55 using namespace ::com::sun::star::uno
;
56 using namespace ::com::sun::star::container
;
57 using namespace ::com::sun::star::io
;
58 using namespace ::com::sun::star::lang
;
60 #define XML_CONTAINERSTORAGE_NAME_60 "Pictures"
61 #define XML_CONTAINERSTORAGE_NAME "ObjectReplacements"
62 #define XML_EMBEDDEDOBJECT_URL_BASE "vnd.sun.star.EmbeddedObject:"
63 #define XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE "vnd.sun.star.GraphicObject:"
67 class OutputStorageWrapper_Impl
: public ::cppu::WeakImplHelper1
<XOutputStream
>
70 Reference
< XOutputStream
> xOut
;
72 bool bStreamClosed
: 1;
76 OutputStorageWrapper_Impl();
77 virtual ~OutputStorageWrapper_Impl();
79 // css::io::XOutputStream
80 virtual void SAL_CALL
writeBytes(const Sequence
< sal_Int8
>& aData
) throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
81 virtual void SAL_CALL
flush() throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
82 virtual void SAL_CALL
closeOutput() throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
84 SvStream
* GetStream();
87 OutputStorageWrapper_Impl::OutputStorageWrapper_Impl()
88 : bStreamClosed( false )
91 aTempFile
.EnableKillingFile();
92 pStream
= aTempFile
.GetStream( STREAM_READWRITE
);
93 xOut
= new OOutputStreamWrapper( *pStream
);
96 OutputStorageWrapper_Impl::~OutputStorageWrapper_Impl()
100 SvStream
*OutputStorageWrapper_Impl::GetStream()
107 void SAL_CALL
OutputStorageWrapper_Impl::writeBytes(
108 const Sequence
< sal_Int8
>& aData
)
109 throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
, std::exception
)
111 MutexGuard
aGuard( maMutex
);
112 xOut
->writeBytes( aData
);
115 void SAL_CALL
OutputStorageWrapper_Impl::flush()
116 throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
, std::exception
)
118 MutexGuard
aGuard( maMutex
);
122 void SAL_CALL
OutputStorageWrapper_Impl::closeOutput()
123 throw(NotConnectedException
, BufferSizeExceededException
, RuntimeException
, std::exception
)
125 MutexGuard
aGuard( maMutex
);
127 bStreamClosed
= true;
132 bool operator() ( const OUString
& r1
, const OUString
& r2
) const
138 SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper() :
139 WeakComponentImplHelper2
< XEmbeddedObjectResolver
, XNameAccess
>( maMutex
),
140 maReplacementGraphicsContainerStorageName( XML_CONTAINERSTORAGE_NAME
),
141 maReplacementGraphicsContainerStorageName60( XML_CONTAINERSTORAGE_NAME_60
),
143 meCreateMode( EMBEDDEDOBJECTHELPER_MODE_READ
),
148 SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper( ::comphelper::IEmbeddedHelper
& rDocPersist
, SvXMLEmbeddedObjectHelperMode eCreateMode
) :
149 WeakComponentImplHelper2
< XEmbeddedObjectResolver
, XNameAccess
>( maMutex
),
150 maReplacementGraphicsContainerStorageName( XML_CONTAINERSTORAGE_NAME
),
151 maReplacementGraphicsContainerStorageName60( XML_CONTAINERSTORAGE_NAME_60
),
153 meCreateMode( EMBEDDEDOBJECTHELPER_MODE_READ
),
156 Init( 0, rDocPersist
, eCreateMode
);
159 SvXMLEmbeddedObjectHelper::~SvXMLEmbeddedObjectHelper()
163 SvXMLEmbeddedObjectHelper_Impl::iterator aIter
= mpStreamMap
->begin();
164 SvXMLEmbeddedObjectHelper_Impl::iterator aEnd
= mpStreamMap
->end();
165 for( ; aIter
!= aEnd
; ++aIter
)
169 aIter
->second
->release();
177 void SAL_CALL
SvXMLEmbeddedObjectHelper::disposing()
182 void SvXMLEmbeddedObjectHelper::splitObjectURL(const OUString
& _aURLNoPar
,
183 OUString
& rContainerStorageName
,
184 OUString
& rObjectStorageName
)
186 DBG_ASSERT(_aURLNoPar
.isEmpty() || '#' != _aURLNoPar
[0], "invalid object URL" );
187 OUString aURLNoPar
= _aURLNoPar
;
189 sal_Int32 _nPos
= aURLNoPar
.lastIndexOf( '/' );
192 rContainerStorageName
.clear();
193 rObjectStorageName
= aURLNoPar
;
197 //eliminate 'superfluous' slashes at start and end
198 //#i103076# load objects with all allowed xlink:href syntaxes
200 //eliminate './' at start
201 sal_Int32 nStart
= 0;
202 sal_Int32 nCount
= aURLNoPar
.getLength();
203 if( aURLNoPar
.startsWith( "./" ) )
209 //eliminate '/' at end
210 sal_Int32 nEnd
= aURLNoPar
.lastIndexOf( '/' );
211 if( nEnd
== aURLNoPar
.getLength()-1 && nEnd
!= (nStart
-1) )
214 aURLNoPar
= aURLNoPar
.copy( nStart
, nCount
);
217 _nPos
= aURLNoPar
.lastIndexOf( '/' );
219 rContainerStorageName
= aURLNoPar
.copy( 0, _nPos
);
220 rObjectStorageName
= aURLNoPar
.copy( _nPos
+1 );
224 bool SvXMLEmbeddedObjectHelper::ImplGetStorageNames(
225 const OUString
& rURLStr
,
226 OUString
& rContainerStorageName
,
227 OUString
& rObjectStorageName
,
228 bool bInternalToExternal
,
230 bool *pOasisFormat
) const
232 // internal URL: vnd.sun.star.EmbeddedObject:<object-name>
233 // or: vnd.sun.star.EmbeddedObject:<path>/<object-name>
234 // internal replacement images:
235 // vnd.sun.star.EmbeddedObjectGraphic:<object-name>
236 // or: vnd.sun.star.EmbeddedObjectGraphic:<path>/<object-name>
237 // external URL: ./<path>/<object-name>
238 // or: <path>/<object-name>
240 // currently, path may only consist of a single directory name
241 // it is also possible to have additional arguments at the end of URL: <main URL>[?<name>=<value>[,<name>=<value>]*]
244 *pGraphicRepl
= false;
247 *pOasisFormat
= true; // the default value
249 if( rURLStr
.isEmpty() )
252 // get rid of arguments
253 sal_Int32 nPos
= rURLStr
.indexOf( '?' );
259 aURLNoPar
= rURLStr
.copy( 0, nPos
);
261 // check the arguments
263 while( nPos
>= 0 && nPos
< rURLStr
.getLength() )
265 OUString aToken
= rURLStr
.getToken( 0, ',', nPos
);
266 if ( aToken
.equalsIgnoreAsciiCase( "oasis=false" ) )
269 *pOasisFormat
= false;
274 DBG_ASSERT( false, "invalid arguments was found in URL!" );
279 if( bInternalToExternal
)
281 nPos
= aURLNoPar
.indexOf( ':' );
284 bool bObjUrl
= aURLNoPar
.startsWith( XML_EMBEDDEDOBJECT_URL_BASE
);
285 bool bGrUrl
= !bObjUrl
&&
286 aURLNoPar
.startsWith( XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE
);
287 if( !(bObjUrl
|| bGrUrl
) )
290 sal_Int32 nPathStart
= nPos
+ 1;
291 nPos
= aURLNoPar
.lastIndexOf( '/' );
294 rContainerStorageName
.clear();
295 rObjectStorageName
= aURLNoPar
.copy( nPathStart
);
297 else if( nPos
> nPathStart
)
299 rContainerStorageName
= aURLNoPar
.copy( nPathStart
, nPos
-nPathStart
);
300 rObjectStorageName
= aURLNoPar
.copy( nPos
+1 );
307 bool bOASIS
= mxRootStorage
.is() &&
308 ( SotStorage::GetVersion( mxRootStorage
) > SOFFICE_FILEFORMAT_60
);
309 rContainerStorageName
= bOASIS
310 ? maReplacementGraphicsContainerStorageName
311 : maReplacementGraphicsContainerStorageName60
;
314 *pGraphicRepl
= true;
321 splitObjectURL(aURLNoPar
, rContainerStorageName
, rObjectStorageName
);
324 if( -1 != rContainerStorageName
.indexOf( '/' ) )
326 OSL_FAIL( "SvXMLEmbeddedObjectHelper: invalid path name" );
333 uno::Reference
< embed::XStorage
> SvXMLEmbeddedObjectHelper::ImplGetContainerStorage(
334 const OUString
& rStorageName
)
336 DBG_ASSERT( -1 == rStorageName
.indexOf( '/' ) &&
337 -1 == rStorageName
.indexOf( '\\' ),
338 "nested embedded storages aren't supported" );
339 if( !mxContainerStorage
.is() ||
340 ( rStorageName
!= maCurContainerStorageName
) )
342 if( mxContainerStorage
.is() &&
343 !maCurContainerStorageName
.isEmpty() &&
344 EMBEDDEDOBJECTHELPER_MODE_WRITE
== meCreateMode
)
346 uno::Reference
< embed::XTransactedObject
> xTrans( mxContainerStorage
, uno::UNO_QUERY
);
351 if( !rStorageName
.isEmpty() && mxRootStorage
.is() )
353 sal_Int32 nMode
= EMBEDDEDOBJECTHELPER_MODE_WRITE
== meCreateMode
354 ? ::embed::ElementModes::READWRITE
355 : ::embed::ElementModes::READ
;
356 mxContainerStorage
= mxRootStorage
->openStorageElement( rStorageName
,
361 mxContainerStorage
= mxRootStorage
;
363 maCurContainerStorageName
= rStorageName
;
366 return mxContainerStorage
;
369 bool SvXMLEmbeddedObjectHelper::ImplReadObject(
370 const OUString
& rContainerStorageName
,
372 const SvGlobalName
*pClassId
,
377 uno::Reference
< embed::XStorage
> xDocStor( mpDocPersist
->getStorage() );
378 uno::Reference
< embed::XStorage
> xCntnrStor( ImplGetContainerStorage( rContainerStorageName
) );
380 if( !xCntnrStor
.is() && !pTemp
)
383 OUString
aSrcObjName( rObjName
);
384 comphelper::EmbeddedObjectContainer
& rContainer
= mpDocPersist
->getEmbeddedObjectContainer();
386 // Is the object name unique?
387 // if the object is already instantiated by GetEmbeddedObject
388 // that means that the duplication is being loaded
389 bool bDuplicate
= rContainer
.HasInstantiatedEmbeddedObject( rObjName
);
390 DBG_ASSERT( !bDuplicate
, "An object in the document is referenced twice!" );
392 if( xDocStor
!= xCntnrStor
|| pTemp
|| bDuplicate
)
394 // TODO/LATER: make this altogether a method in the EmbeddedObjectContainer
396 // create a unique name for the duplicate object
398 rObjName
= rContainer
.CreateUniqueObjectName();
405 uno::Reference
< io::XStream
> xStm
= xDocStor
->openStreamElement( rObjName
,
406 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
407 boost::scoped_ptr
<SvStream
> pStream(::utl::UcbStreamHelper::CreateStream( xStm
));
408 pTemp
->ReadStream( *pStream
);
411 // TODO/LATER: what to do when other types of objects are based on substream persistence?
412 // This is an ole object
413 uno::Reference
< beans::XPropertySet
> xProps( xStm
, uno::UNO_QUERY_THROW
);
414 xProps
->setPropertyValue(
415 OUString( "MediaType" ),
416 uno::makeAny( OUString( "application/vnd.sun.star.oleobject" ) ) );
418 xStm
->getOutputStream()->closeOutput();
420 catch ( uno::Exception
& )
429 xCntnrStor
->copyElementTo( aSrcObjName
, xDocStor
, rObjName
);
431 catch ( uno::Exception
& )
438 // make object known to the container
439 // TODO/LATER: could be done a little bit more efficient!
440 OUString
aName( rObjName
);
442 // TODO/LATER: The provided pClassId is ignored for now.
443 // The stream contains OLE storage internally and this storage already has a class id specifying the
444 // server that was used to create the object. pClassId could be used to specify the server that should
445 // be used for the next opening, but this information seems to be out of the file format responsibility
447 rContainer
.GetEmbeddedObject( aName
);
452 OUString
SvXMLEmbeddedObjectHelper::ImplInsertEmbeddedObjectURL(
453 const OUString
& rURLStr
)
457 OUString aContainerStorageName
, aObjectStorageName
;
458 if( !ImplGetStorageNames( rURLStr
, aContainerStorageName
,
460 EMBEDDEDOBJECTHELPER_MODE_WRITE
== meCreateMode
) )
463 if( EMBEDDEDOBJECTHELPER_MODE_READ
== meCreateMode
)
465 OutputStorageWrapper_Impl
*pOut
= 0;
466 SvXMLEmbeddedObjectHelper_Impl::iterator aIter
;
470 aIter
= mpStreamMap
->find( rURLStr
);
471 if( aIter
!= mpStreamMap
->end() && aIter
->second
)
472 pOut
= aIter
->second
;
475 SvGlobalName aClassId
, *pClassId
= 0;
476 sal_Int32 nPos
= aObjectStorageName
.lastIndexOf( '!' );
477 if( -1 != nPos
&& aClassId
.MakeId( aObjectStorageName
.copy( nPos
+1 ) ) )
479 aObjectStorageName
= aObjectStorageName
.copy( 0, nPos
);
480 pClassId
= &aClassId
;
483 ImplReadObject( aContainerStorageName
, aObjectStorageName
, pClassId
, pOut
? pOut
->GetStream() : 0 );
484 sRetURL
= XML_EMBEDDEDOBJECT_URL_BASE
;
485 sRetURL
+= aObjectStorageName
;
489 mpStreamMap
->erase( aIter
);
495 // Objects are written using ::comphelper::IEmbeddedHelper::SaveAs
497 if( !aContainerStorageName
.isEmpty() )
499 sRetURL
+= aContainerStorageName
;
502 sRetURL
+= aObjectStorageName
;
508 uno::Reference
< io::XInputStream
> SvXMLEmbeddedObjectHelper::ImplGetReplacementImage(
509 const uno::Reference
< embed::XEmbeddedObject
>& xObj
)
511 uno::Reference
< io::XInputStream
> xStream
;
517 bool bSwitchBackToLoaded
= false;
518 sal_Int32 nCurState
= xObj
->getCurrentState();
519 if ( nCurState
== embed::EmbedStates::LOADED
|| nCurState
== embed::EmbedStates::RUNNING
)
521 // means that the object is not active
522 // copy replacement image from old to new container
524 xStream
= mpDocPersist
->getEmbeddedObjectContainer().GetGraphicStream( xObj
, &aMediaType
);
529 // the image must be regenerated
530 // TODO/LATER: another aspect could be used
531 if ( nCurState
== embed::EmbedStates::LOADED
)
532 bSwitchBackToLoaded
= true;
535 xStream
= svt::EmbeddedObjectRef::GetGraphicReplacementStream(
536 embed::Aspects::MSOLE_CONTENT
,
541 if ( bSwitchBackToLoaded
)
542 // switch back to loaded state; that way we have a minimum cache confusion
543 xObj
->changeState( embed::EmbedStates::LOADED
);
545 catch( uno::Exception
& )
552 void SvXMLEmbeddedObjectHelper::Init(
553 const uno::Reference
< embed::XStorage
>& rRootStorage
,
554 ::comphelper::IEmbeddedHelper
& rPersist
,
555 SvXMLEmbeddedObjectHelperMode eCreateMode
)
557 mxRootStorage
= rRootStorage
;
558 mpDocPersist
= &rPersist
;
559 meCreateMode
= eCreateMode
;
562 SvXMLEmbeddedObjectHelper
* SvXMLEmbeddedObjectHelper::Create(
563 const uno::Reference
< embed::XStorage
>& rRootStorage
,
564 ::comphelper::IEmbeddedHelper
& rDocPersist
,
565 SvXMLEmbeddedObjectHelperMode eCreateMode
,
570 SvXMLEmbeddedObjectHelper
* pThis
= new SvXMLEmbeddedObjectHelper
;
573 pThis
->Init( rRootStorage
, rDocPersist
, eCreateMode
);
578 SvXMLEmbeddedObjectHelper
* SvXMLEmbeddedObjectHelper::Create(
579 ::comphelper::IEmbeddedHelper
& rDocPersist
,
580 SvXMLEmbeddedObjectHelperMode eCreateMode
)
582 SvXMLEmbeddedObjectHelper
* pThis
= new SvXMLEmbeddedObjectHelper
;
585 pThis
->Init( 0, rDocPersist
, eCreateMode
);
590 void SvXMLEmbeddedObjectHelper::Destroy(
591 SvXMLEmbeddedObjectHelper
* pSvXMLEmbeddedObjectHelper
)
593 if( pSvXMLEmbeddedObjectHelper
)
595 pSvXMLEmbeddedObjectHelper
->dispose();
596 pSvXMLEmbeddedObjectHelper
->release();
600 void SvXMLEmbeddedObjectHelper::Flush()
602 if( mxTempStorage
.is() )
604 Reference
< XComponent
> xComp( mxTempStorage
, UNO_QUERY
);
609 // XGraphicObjectResolver: alien objects!
610 OUString SAL_CALL
SvXMLEmbeddedObjectHelper::resolveEmbeddedObjectURL(const OUString
& rURL
)
611 throw(RuntimeException
, std::exception
)
613 MutexGuard
aGuard( maMutex
);
618 sRet
= ImplInsertEmbeddedObjectURL(rURL
);
620 catch (const RuntimeException
&)
624 catch (const Exception
& e
)
626 throw WrappedTargetRuntimeException(
627 "SvXMLEmbeddedObjectHelper::resolveEmbeddedObjectURL non-RuntimeException",
628 static_cast<uno::XWeak
*>(this), uno::makeAny(e
));
633 // XNameAccess: alien objects!
634 Any SAL_CALL
SvXMLEmbeddedObjectHelper::getByName(
635 const OUString
& rURLStr
)
636 throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
, std::exception
)
638 MutexGuard
aGuard( maMutex
);
640 if( EMBEDDEDOBJECTHELPER_MODE_READ
== meCreateMode
)
642 Reference
< XOutputStream
> xStrm
;
645 SvXMLEmbeddedObjectHelper_Impl::iterator aIter
=
646 mpStreamMap
->find( rURLStr
);
647 if( aIter
!= mpStreamMap
->end() && aIter
->second
)
648 xStrm
= aIter
->second
;
652 OutputStorageWrapper_Impl
*pOut
= new OutputStorageWrapper_Impl
;
655 mpStreamMap
= new SvXMLEmbeddedObjectHelper_Impl
;
656 (*mpStreamMap
)[rURLStr
] = pOut
;
664 bool bGraphicRepl
= false;
665 bool bOasisFormat
= true;
666 Reference
< XInputStream
> xStrm
;
667 OUString aContainerStorageName
, aObjectStorageName
;
668 if( ImplGetStorageNames( rURLStr
, aContainerStorageName
,
676 comphelper::EmbeddedObjectContainer
& rContainer
=
677 mpDocPersist
->getEmbeddedObjectContainer();
679 Reference
< embed::XEmbeddedObject
> xObj
= rContainer
.GetEmbeddedObject( aObjectStorageName
);
680 DBG_ASSERT( xObj
.is(), "Didn't get object" );
686 xStrm
= ImplGetReplacementImage( xObj
);
690 Reference
< embed::XEmbedPersist
> xPersist( xObj
, UNO_QUERY
);
693 if( !mxTempStorage
.is() )
695 comphelper::OStorageHelper::GetTemporaryStorage();
696 Sequence
< beans::PropertyValue
> aDummy( 0 ), aEmbDescr( 1 );
697 aEmbDescr
[0].Name
= "StoreVisualReplacement";
698 aEmbDescr
[0].Value
<<= !bOasisFormat
;
701 uno::Reference
< io::XInputStream
> xGrInStream
= ImplGetReplacementImage( xObj
);
702 if ( xGrInStream
.is() )
704 aEmbDescr
.realloc( 2 );
705 aEmbDescr
[1].Name
= "VisualReplacement";
706 aEmbDescr
[1].Value
<<= xGrInStream
;
710 xPersist
->storeToEntry( mxTempStorage
, aObjectStorageName
,
712 Reference
< io::XStream
> xStream
=
713 mxTempStorage
->openStreamElement(
715 embed::ElementModes::READ
);
717 xStrm
= xStream
->getInputStream();
722 catch ( uno::Exception
& )
733 Sequence
< OUString
> SAL_CALL
SvXMLEmbeddedObjectHelper::getElementNames()
734 throw (RuntimeException
, std::exception
)
736 MutexGuard
aGuard( maMutex
);
737 return Sequence
< OUString
>(0);
740 sal_Bool SAL_CALL
SvXMLEmbeddedObjectHelper::hasByName( const OUString
& rURLStr
)
741 throw (RuntimeException
, std::exception
)
743 MutexGuard
aGuard( maMutex
);
744 if( EMBEDDEDOBJECTHELPER_MODE_READ
== meCreateMode
)
750 OUString aContainerStorageName
, aObjectStorageName
;
751 if( !ImplGetStorageNames( rURLStr
, aContainerStorageName
,
756 comphelper::EmbeddedObjectContainer
& rContainer
= mpDocPersist
->getEmbeddedObjectContainer();
757 return !aObjectStorageName
.isEmpty() &&
758 rContainer
.HasEmbeddedObject( aObjectStorageName
);
763 Type SAL_CALL
SvXMLEmbeddedObjectHelper::getElementType()
764 throw (RuntimeException
, std::exception
)
766 MutexGuard
aGuard( maMutex
);
767 if( EMBEDDEDOBJECTHELPER_MODE_READ
== meCreateMode
)
768 return cppu::UnoType
<XOutputStream
>::get();
770 return cppu::UnoType
<XInputStream
>::get();
773 sal_Bool SAL_CALL
SvXMLEmbeddedObjectHelper::hasElements()
774 throw (RuntimeException
, std::exception
)
776 MutexGuard
aGuard( maMutex
);
777 if( EMBEDDEDOBJECTHELPER_MODE_READ
== meCreateMode
)
783 comphelper::EmbeddedObjectContainer
& rContainer
= mpDocPersist
->getEmbeddedObjectContainer();
784 return rContainer
.HasEmbeddedObjects();
788 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */