xref: /trunk/main/oox/source/ole/olestorage.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include "oox/ole/olestorage.hxx"
29*cdf0e10cSrcweir 
30*cdf0e10cSrcweir #include <com/sun/star/beans/PropertyValue.hpp>
31*cdf0e10cSrcweir #include <com/sun/star/container/XNameContainer.hpp>
32*cdf0e10cSrcweir #include <com/sun/star/embed/XTransactedObject.hpp>
33*cdf0e10cSrcweir #include <com/sun/star/io/XInputStream.hpp>
34*cdf0e10cSrcweir #include <com/sun/star/io/XOutputStream.hpp>
35*cdf0e10cSrcweir #include <com/sun/star/io/XSeekable.hpp>
36*cdf0e10cSrcweir #include <com/sun/star/io/XStream.hpp>
37*cdf0e10cSrcweir #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38*cdf0e10cSrcweir #include <com/sun/star/uno/XComponentContext.hpp>
39*cdf0e10cSrcweir #include <cppuhelper/implbase2.hxx>
40*cdf0e10cSrcweir #include "oox/helper/binaryinputstream.hxx"
41*cdf0e10cSrcweir #include "oox/helper/binaryoutputstream.hxx"
42*cdf0e10cSrcweir #include "oox/helper/containerhelper.hxx"
43*cdf0e10cSrcweir #include "oox/helper/helper.hxx"
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir namespace oox {
46*cdf0e10cSrcweir namespace ole {
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir // ============================================================================
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir using namespace ::com::sun::star::beans;
51*cdf0e10cSrcweir using namespace ::com::sun::star::container;
52*cdf0e10cSrcweir using namespace ::com::sun::star::embed;
53*cdf0e10cSrcweir using namespace ::com::sun::star::io;
54*cdf0e10cSrcweir using namespace ::com::sun::star::lang;
55*cdf0e10cSrcweir using namespace ::com::sun::star::uno;
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir using ::rtl::OUString;
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir // ============================================================================
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir namespace {
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir typedef ::cppu::WeakImplHelper2< XSeekable, XOutputStream > OleOutputStreamBase;
64*cdf0e10cSrcweir 
65*cdf0e10cSrcweir /** Implementation of an OLE storage output stream that inserts itself into the
66*cdf0e10cSrcweir     storage when it is closed.
67*cdf0e10cSrcweir  */
68*cdf0e10cSrcweir class OleOutputStream : public OleOutputStreamBase
69*cdf0e10cSrcweir {
70*cdf0e10cSrcweir public:
71*cdf0e10cSrcweir     explicit            OleOutputStream(
72*cdf0e10cSrcweir                             const Reference< XComponentContext >& rxContext,
73*cdf0e10cSrcweir                             const Reference< XNameContainer >& rxStorage,
74*cdf0e10cSrcweir                             const OUString& rElementName );
75*cdf0e10cSrcweir     virtual             ~OleOutputStream();
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir     virtual void SAL_CALL seek( sal_Int64 nPos ) throw( IllegalArgumentException, IOException, RuntimeException );
78*cdf0e10cSrcweir     virtual sal_Int64 SAL_CALL getPosition() throw( IOException, RuntimeException );
79*cdf0e10cSrcweir     virtual sal_Int64 SAL_CALL getLength() throw( IOException, RuntimeException );
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir     virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
82*cdf0e10cSrcweir     virtual void SAL_CALL flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
83*cdf0e10cSrcweir     virtual void SAL_CALL closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir private:
86*cdf0e10cSrcweir     void                ensureSeekable() const throw( IOException );
87*cdf0e10cSrcweir     void                ensureConnected() const throw( NotConnectedException );
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir private:
90*cdf0e10cSrcweir     Reference< XNameContainer > mxStorage;
91*cdf0e10cSrcweir     Reference< XStream > mxTempFile;
92*cdf0e10cSrcweir     Reference< XOutputStream > mxOutStrm;
93*cdf0e10cSrcweir     Reference< XSeekable > mxSeekable;
94*cdf0e10cSrcweir     OUString            maElementName;
95*cdf0e10cSrcweir };
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir // ----------------------------------------------------------------------------
98*cdf0e10cSrcweir 
99*cdf0e10cSrcweir OleOutputStream::OleOutputStream( const Reference< XComponentContext >& rxContext,
100*cdf0e10cSrcweir         const Reference< XNameContainer >& rxStorage, const OUString& rElementName ) :
101*cdf0e10cSrcweir     mxStorage( rxStorage ),
102*cdf0e10cSrcweir     maElementName( rElementName )
103*cdf0e10cSrcweir {
104*cdf0e10cSrcweir     try
105*cdf0e10cSrcweir     {
106*cdf0e10cSrcweir         Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW );
107*cdf0e10cSrcweir         mxTempFile.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW );
108*cdf0e10cSrcweir         mxOutStrm = mxTempFile->getOutputStream();
109*cdf0e10cSrcweir         mxSeekable.set( mxOutStrm, UNO_QUERY );
110*cdf0e10cSrcweir     }
111*cdf0e10cSrcweir     catch( Exception& )
112*cdf0e10cSrcweir     {
113*cdf0e10cSrcweir     }
114*cdf0e10cSrcweir }
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir OleOutputStream::~OleOutputStream()
117*cdf0e10cSrcweir {
118*cdf0e10cSrcweir }
119*cdf0e10cSrcweir 
120*cdf0e10cSrcweir void SAL_CALL OleOutputStream::seek( sal_Int64 nPos ) throw( IllegalArgumentException, IOException, RuntimeException )
121*cdf0e10cSrcweir {
122*cdf0e10cSrcweir     ensureSeekable();
123*cdf0e10cSrcweir     mxSeekable->seek( nPos );
124*cdf0e10cSrcweir }
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir sal_Int64 SAL_CALL OleOutputStream::getPosition() throw( IOException, RuntimeException )
127*cdf0e10cSrcweir {
128*cdf0e10cSrcweir     ensureSeekable();
129*cdf0e10cSrcweir     return mxSeekable->getPosition();
130*cdf0e10cSrcweir }
131*cdf0e10cSrcweir 
132*cdf0e10cSrcweir sal_Int64 SAL_CALL OleOutputStream::getLength() throw( IOException, RuntimeException )
133*cdf0e10cSrcweir {
134*cdf0e10cSrcweir     ensureSeekable();
135*cdf0e10cSrcweir     return mxSeekable->getLength();
136*cdf0e10cSrcweir }
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir void SAL_CALL OleOutputStream::writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
139*cdf0e10cSrcweir {
140*cdf0e10cSrcweir     ensureConnected();
141*cdf0e10cSrcweir     mxOutStrm->writeBytes( rData );
142*cdf0e10cSrcweir }
143*cdf0e10cSrcweir 
144*cdf0e10cSrcweir void SAL_CALL OleOutputStream::flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
145*cdf0e10cSrcweir {
146*cdf0e10cSrcweir     ensureConnected();
147*cdf0e10cSrcweir     mxOutStrm->flush();
148*cdf0e10cSrcweir }
149*cdf0e10cSrcweir 
150*cdf0e10cSrcweir void SAL_CALL OleOutputStream::closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
151*cdf0e10cSrcweir {
152*cdf0e10cSrcweir     ensureConnected();
153*cdf0e10cSrcweir     ensureSeekable();
154*cdf0e10cSrcweir     // remember the class members
155*cdf0e10cSrcweir     Reference< XOutputStream > xOutStrm = mxOutStrm;
156*cdf0e10cSrcweir     Reference< XSeekable > xSeekable = mxSeekable;
157*cdf0e10cSrcweir     // reset all class members
158*cdf0e10cSrcweir     mxOutStrm.clear();
159*cdf0e10cSrcweir     mxSeekable.clear();
160*cdf0e10cSrcweir     // close stream (and let it throw something if needed)
161*cdf0e10cSrcweir     xOutStrm->closeOutput();
162*cdf0e10cSrcweir     // on success, insert the stream into the OLE storage (must be seeked back before)
163*cdf0e10cSrcweir     xSeekable->seek( 0 );
164*cdf0e10cSrcweir     if( !ContainerHelper::insertByName( mxStorage, maElementName, Any( mxTempFile ) ) )
165*cdf0e10cSrcweir         throw IOException();
166*cdf0e10cSrcweir }
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir void OleOutputStream::ensureSeekable() const throw( IOException )
169*cdf0e10cSrcweir {
170*cdf0e10cSrcweir     if( !mxSeekable.is() )
171*cdf0e10cSrcweir         throw IOException();
172*cdf0e10cSrcweir }
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir void OleOutputStream::ensureConnected() const throw( NotConnectedException )
175*cdf0e10cSrcweir {
176*cdf0e10cSrcweir     if( !mxOutStrm.is() )
177*cdf0e10cSrcweir         throw NotConnectedException();
178*cdf0e10cSrcweir }
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir } // namespace
181*cdf0e10cSrcweir 
182*cdf0e10cSrcweir // ============================================================================
183*cdf0e10cSrcweir 
184*cdf0e10cSrcweir OleStorage::OleStorage( const Reference< XComponentContext >& rxContext,
185*cdf0e10cSrcweir         const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) :
186*cdf0e10cSrcweir     StorageBase( rxInStream, bBaseStreamAccess ),
187*cdf0e10cSrcweir     mxContext( rxContext ),
188*cdf0e10cSrcweir     mpParentStorage( 0 )
189*cdf0e10cSrcweir {
190*cdf0e10cSrcweir     OSL_ENSURE( mxContext.is(), "OleStorage::OleStorage - missing component context" );
191*cdf0e10cSrcweir     initStorage( rxInStream );
192*cdf0e10cSrcweir }
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir OleStorage::OleStorage( const Reference< XComponentContext >& rxContext,
195*cdf0e10cSrcweir         const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) :
196*cdf0e10cSrcweir     StorageBase( rxOutStream, bBaseStreamAccess ),
197*cdf0e10cSrcweir     mxContext( rxContext ),
198*cdf0e10cSrcweir     mpParentStorage( 0 )
199*cdf0e10cSrcweir {
200*cdf0e10cSrcweir     OSL_ENSURE( mxContext.is(), "OleStorage::OleStorage - missing component context" );
201*cdf0e10cSrcweir     initStorage( rxOutStream );
202*cdf0e10cSrcweir }
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir OleStorage::OleStorage( const OleStorage& rParentStorage,
205*cdf0e10cSrcweir         const Reference< XNameContainer >& rxStorage, const OUString& rElementName, bool bReadOnly ) :
206*cdf0e10cSrcweir     StorageBase( rParentStorage, rElementName, bReadOnly ),
207*cdf0e10cSrcweir     mxContext( rParentStorage.mxContext ),
208*cdf0e10cSrcweir     mxStorage( rxStorage ),
209*cdf0e10cSrcweir     mpParentStorage( &rParentStorage )
210*cdf0e10cSrcweir {
211*cdf0e10cSrcweir     OSL_ENSURE( mxStorage.is(), "OleStorage::OleStorage - missing substorage elements" );
212*cdf0e10cSrcweir }
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir OleStorage::OleStorage( const OleStorage& rParentStorage,
215*cdf0e10cSrcweir         const Reference< XStream >& rxOutStream, const OUString& rElementName ) :
216*cdf0e10cSrcweir     StorageBase( rParentStorage, rElementName, false ),
217*cdf0e10cSrcweir     mxContext( rParentStorage.mxContext ),
218*cdf0e10cSrcweir     mpParentStorage( &rParentStorage )
219*cdf0e10cSrcweir {
220*cdf0e10cSrcweir     initStorage( rxOutStream );
221*cdf0e10cSrcweir }
222*cdf0e10cSrcweir 
223*cdf0e10cSrcweir OleStorage::~OleStorage()
224*cdf0e10cSrcweir {
225*cdf0e10cSrcweir }
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir // ----------------------------------------------------------------------------
228*cdf0e10cSrcweir 
229*cdf0e10cSrcweir void OleStorage::initStorage( const Reference< XInputStream >& rxInStream )
230*cdf0e10cSrcweir {
231*cdf0e10cSrcweir     // if stream is not seekable, create temporary copy
232*cdf0e10cSrcweir     Reference< XInputStream > xInStrm = rxInStream;
233*cdf0e10cSrcweir     if( !Reference< XSeekable >( xInStrm, UNO_QUERY ).is() ) try
234*cdf0e10cSrcweir     {
235*cdf0e10cSrcweir         Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW );
236*cdf0e10cSrcweir         Reference< XStream > xTempFile( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW );
237*cdf0e10cSrcweir         {
238*cdf0e10cSrcweir             Reference< XOutputStream > xOutStrm( xTempFile->getOutputStream(), UNO_SET_THROW );
239*cdf0e10cSrcweir             /*  Pass false to both binary stream objects to keep the UNO
240*cdf0e10cSrcweir                 streams alive. Life time of these streams is controlled by the
241*cdf0e10cSrcweir                 tempfile implementation. */
242*cdf0e10cSrcweir             BinaryXOutputStream aOutStrm( xOutStrm, false );
243*cdf0e10cSrcweir             BinaryXInputStream aInStrm( xInStrm, false );
244*cdf0e10cSrcweir             aInStrm.copyToStream( aOutStrm );
245*cdf0e10cSrcweir         } // scope closes output stream of tempfile
246*cdf0e10cSrcweir         xInStrm = xTempFile->getInputStream();
247*cdf0e10cSrcweir     }
248*cdf0e10cSrcweir     catch( Exception& )
249*cdf0e10cSrcweir     {
250*cdf0e10cSrcweir         OSL_ENSURE( false, "OleStorage::initStorage - cannot create temporary copy of input stream" );
251*cdf0e10cSrcweir     }
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir     // create base storage object
254*cdf0e10cSrcweir     if( xInStrm.is() ) try
255*cdf0e10cSrcweir     {
256*cdf0e10cSrcweir         Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW );
257*cdf0e10cSrcweir         Sequence< Any > aArgs( 2 );
258*cdf0e10cSrcweir         aArgs[ 0 ] <<= xInStrm;
259*cdf0e10cSrcweir         aArgs[ 1 ] <<= true;        // true = do not create a copy of the input stream
260*cdf0e10cSrcweir         mxStorage.set( xFactory->createInstanceWithArguments(
261*cdf0e10cSrcweir             CREATE_OUSTRING( "com.sun.star.embed.OLESimpleStorage" ), aArgs ), UNO_QUERY_THROW );
262*cdf0e10cSrcweir     }
263*cdf0e10cSrcweir     catch( Exception& )
264*cdf0e10cSrcweir     {
265*cdf0e10cSrcweir     }
266*cdf0e10cSrcweir }
267*cdf0e10cSrcweir 
268*cdf0e10cSrcweir void OleStorage::initStorage( const Reference< XStream >& rxOutStream )
269*cdf0e10cSrcweir {
270*cdf0e10cSrcweir     // create base storage object
271*cdf0e10cSrcweir     if( rxOutStream.is() ) try
272*cdf0e10cSrcweir     {
273*cdf0e10cSrcweir         Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW );
274*cdf0e10cSrcweir         Sequence< Any > aArgs( 2 );
275*cdf0e10cSrcweir         aArgs[ 0 ] <<= rxOutStream;
276*cdf0e10cSrcweir         aArgs[ 1 ] <<= true;        // true = do not create a copy of the stream
277*cdf0e10cSrcweir         mxStorage.set( xFactory->createInstanceWithArguments(
278*cdf0e10cSrcweir             CREATE_OUSTRING( "com.sun.star.embed.OLESimpleStorage" ), aArgs ), UNO_QUERY_THROW );
279*cdf0e10cSrcweir     }
280*cdf0e10cSrcweir     catch( Exception& )
281*cdf0e10cSrcweir     {
282*cdf0e10cSrcweir     }
283*cdf0e10cSrcweir }
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir // StorageBase interface ------------------------------------------------------
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir bool OleStorage::implIsStorage() const
288*cdf0e10cSrcweir {
289*cdf0e10cSrcweir     if( mxStorage.is() ) try
290*cdf0e10cSrcweir     {
291*cdf0e10cSrcweir         /*  If this is not an OLE storage, hasElements() of the OLESimpleStorage
292*cdf0e10cSrcweir             implementation throws an exception. But we do not return the result
293*cdf0e10cSrcweir             of hasElements(), because an empty storage is a valid storage too. */
294*cdf0e10cSrcweir         mxStorage->hasElements();
295*cdf0e10cSrcweir         return true;
296*cdf0e10cSrcweir     }
297*cdf0e10cSrcweir     catch( Exception& )
298*cdf0e10cSrcweir     {
299*cdf0e10cSrcweir     }
300*cdf0e10cSrcweir     return false;
301*cdf0e10cSrcweir }
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir Reference< XStorage > OleStorage::implGetXStorage() const
304*cdf0e10cSrcweir {
305*cdf0e10cSrcweir     OSL_ENSURE( false, "OleStorage::getXStorage - not implemented" );
306*cdf0e10cSrcweir     return Reference< XStorage >();
307*cdf0e10cSrcweir }
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir void OleStorage::implGetElementNames( ::std::vector< OUString >& orElementNames ) const
310*cdf0e10cSrcweir {
311*cdf0e10cSrcweir     Sequence< OUString > aNames;
312*cdf0e10cSrcweir     if( mxStorage.is() ) try
313*cdf0e10cSrcweir     {
314*cdf0e10cSrcweir         aNames = mxStorage->getElementNames();
315*cdf0e10cSrcweir         if( aNames.getLength() > 0 )
316*cdf0e10cSrcweir             orElementNames.insert( orElementNames.end(), aNames.getConstArray(), aNames.getConstArray() + aNames.getLength() );
317*cdf0e10cSrcweir     }
318*cdf0e10cSrcweir     catch( Exception& )
319*cdf0e10cSrcweir     {
320*cdf0e10cSrcweir     }
321*cdf0e10cSrcweir }
322*cdf0e10cSrcweir 
323*cdf0e10cSrcweir StorageRef OleStorage::implOpenSubStorage( const OUString& rElementName, bool bCreateMissing )
324*cdf0e10cSrcweir {
325*cdf0e10cSrcweir     StorageRef xSubStorage;
326*cdf0e10cSrcweir     if( mxStorage.is() && (rElementName.getLength() > 0) )
327*cdf0e10cSrcweir     {
328*cdf0e10cSrcweir         try
329*cdf0e10cSrcweir         {
330*cdf0e10cSrcweir             Reference< XNameContainer > xSubElements( mxStorage->getByName( rElementName ), UNO_QUERY_THROW );
331*cdf0e10cSrcweir             xSubStorage.reset( new OleStorage( *this, xSubElements, rElementName, true ) );
332*cdf0e10cSrcweir         }
333*cdf0e10cSrcweir         catch( Exception& )
334*cdf0e10cSrcweir         {
335*cdf0e10cSrcweir         }
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir         /*  The OLESimpleStorage API implementation seems to be buggy in the
338*cdf0e10cSrcweir             area of writable inplace substorage (sometimes it overwrites other
339*cdf0e10cSrcweir             unrelated streams with zero bytes). We go the save way and create a
340*cdf0e10cSrcweir             new OLE storage based on a temporary file. All operations are
341*cdf0e10cSrcweir             performed on this clean storage. On committing, the storage will be
342*cdf0e10cSrcweir             completely re-inserted into the parent storage. */
343*cdf0e10cSrcweir         if( !isReadOnly() && (bCreateMissing || xSubStorage.get()) ) try
344*cdf0e10cSrcweir         {
345*cdf0e10cSrcweir             // create new storage based on a temp file
346*cdf0e10cSrcweir             Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW );
347*cdf0e10cSrcweir             Reference< XStream > xTempFile( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW );
348*cdf0e10cSrcweir             StorageRef xTempStorage( new OleStorage( *this, xTempFile, rElementName ) );
349*cdf0e10cSrcweir             // copy existing substorage into temp storage
350*cdf0e10cSrcweir             if( xSubStorage.get() )
351*cdf0e10cSrcweir                 xSubStorage->copyStorageToStorage( *xTempStorage );
352*cdf0e10cSrcweir             // return the temp storage to caller
353*cdf0e10cSrcweir             xSubStorage = xTempStorage;
354*cdf0e10cSrcweir         }
355*cdf0e10cSrcweir         catch( Exception& )
356*cdf0e10cSrcweir         {
357*cdf0e10cSrcweir         }
358*cdf0e10cSrcweir     }
359*cdf0e10cSrcweir     return xSubStorage;
360*cdf0e10cSrcweir }
361*cdf0e10cSrcweir 
362*cdf0e10cSrcweir Reference< XInputStream > OleStorage::implOpenInputStream( const OUString& rElementName )
363*cdf0e10cSrcweir {
364*cdf0e10cSrcweir     Reference< XInputStream > xInStream;
365*cdf0e10cSrcweir     if( mxStorage.is() ) try
366*cdf0e10cSrcweir     {
367*cdf0e10cSrcweir         xInStream.set( mxStorage->getByName( rElementName ), UNO_QUERY );
368*cdf0e10cSrcweir     }
369*cdf0e10cSrcweir     catch( Exception& )
370*cdf0e10cSrcweir     {
371*cdf0e10cSrcweir     }
372*cdf0e10cSrcweir     return xInStream;
373*cdf0e10cSrcweir }
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir Reference< XOutputStream > OleStorage::implOpenOutputStream( const OUString& rElementName )
376*cdf0e10cSrcweir {
377*cdf0e10cSrcweir     Reference< XOutputStream > xOutStream;
378*cdf0e10cSrcweir     if( mxStorage.is() && (rElementName.getLength() > 0) )
379*cdf0e10cSrcweir         xOutStream.set( new OleOutputStream( mxContext, mxStorage, rElementName ) );
380*cdf0e10cSrcweir     return xOutStream;
381*cdf0e10cSrcweir }
382*cdf0e10cSrcweir 
383*cdf0e10cSrcweir void OleStorage::implCommit() const
384*cdf0e10cSrcweir {
385*cdf0e10cSrcweir     try
386*cdf0e10cSrcweir     {
387*cdf0e10cSrcweir         // commit this storage (finalizes the file this storage is based on)
388*cdf0e10cSrcweir         Reference< XTransactedObject >( mxStorage, UNO_QUERY_THROW )->commit();
389*cdf0e10cSrcweir         // re-insert this storage into the parent storage
390*cdf0e10cSrcweir         if( mpParentStorage )
391*cdf0e10cSrcweir         {
392*cdf0e10cSrcweir             if( mpParentStorage->mxStorage->hasByName( getName() ) )
393*cdf0e10cSrcweir             {
394*cdf0e10cSrcweir                 // replaceByName() does not work (#i109539#)
395*cdf0e10cSrcweir                 mpParentStorage->mxStorage->removeByName( getName() );
396*cdf0e10cSrcweir                 Reference< XTransactedObject >( mpParentStorage->mxStorage, UNO_QUERY_THROW )->commit();
397*cdf0e10cSrcweir             }
398*cdf0e10cSrcweir             mpParentStorage->mxStorage->insertByName( getName(), Any( mxStorage ) );
399*cdf0e10cSrcweir             // this requires another commit(), which will be performed by the parent storage
400*cdf0e10cSrcweir         }
401*cdf0e10cSrcweir     }
402*cdf0e10cSrcweir     catch( Exception& )
403*cdf0e10cSrcweir     {
404*cdf0e10cSrcweir     }
405*cdf0e10cSrcweir }
406*cdf0e10cSrcweir 
407*cdf0e10cSrcweir // ============================================================================
408*cdf0e10cSrcweir 
409*cdf0e10cSrcweir } // namespace ole
410*cdf0e10cSrcweir } // namespace oox
411