GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / oox / source / ole / olestorage.cxx
blobd6d47f04c1f0cede6c14836ddf779b04980f093b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 "oox/ole/olestorage.hxx"
22 #include <com/sun/star/beans/PropertyValue.hpp>
23 #include <com/sun/star/container/XNameContainer.hpp>
24 #include <com/sun/star/embed/XTransactedObject.hpp>
25 #include <com/sun/star/io/TempFile.hpp>
26 #include <com/sun/star/io/XInputStream.hpp>
27 #include <com/sun/star/io/XOutputStream.hpp>
28 #include <com/sun/star/io/XSeekable.hpp>
29 #include <com/sun/star/io/XStream.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/uno/XComponentContext.hpp>
32 #include <cppuhelper/implbase2.hxx>
33 #include "oox/helper/binaryinputstream.hxx"
34 #include "oox/helper/binaryoutputstream.hxx"
35 #include "oox/helper/containerhelper.hxx"
36 #include "oox/helper/helper.hxx"
38 namespace oox {
39 namespace ole {
41 // ============================================================================
43 using namespace ::com::sun::star::beans;
44 using namespace ::com::sun::star::container;
45 using namespace ::com::sun::star::embed;
46 using namespace ::com::sun::star::io;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::uno;
50 // ============================================================================
52 namespace {
54 typedef ::cppu::WeakImplHelper2< XSeekable, XOutputStream > OleOutputStreamBase;
56 /** Implementation of an OLE storage output stream that inserts itself into the
57 storage when it is closed.
59 class OleOutputStream : public OleOutputStreamBase
61 public:
62 explicit OleOutputStream(
63 const Reference< XComponentContext >& rxContext,
64 const Reference< XNameContainer >& rxStorage,
65 const OUString& rElementName );
66 virtual ~OleOutputStream();
68 virtual void SAL_CALL seek( sal_Int64 nPos ) throw( IllegalArgumentException, IOException, RuntimeException );
69 virtual sal_Int64 SAL_CALL getPosition() throw( IOException, RuntimeException );
70 virtual sal_Int64 SAL_CALL getLength() throw( IOException, RuntimeException );
72 virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
73 virtual void SAL_CALL flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
74 virtual void SAL_CALL closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
76 private:
77 void ensureSeekable() const throw( IOException );
78 void ensureConnected() const throw( NotConnectedException );
80 private:
81 Reference< XNameContainer > mxStorage;
82 Reference< XStream > mxTempFile;
83 Reference< XOutputStream > mxOutStrm;
84 Reference< XSeekable > mxSeekable;
85 OUString maElementName;
88 // ----------------------------------------------------------------------------
90 OleOutputStream::OleOutputStream( const Reference< XComponentContext >& rxContext,
91 const Reference< XNameContainer >& rxStorage, const OUString& rElementName ) :
92 mxStorage( rxStorage ),
93 maElementName( rElementName )
95 try
97 mxTempFile.set( TempFile::create(rxContext), UNO_QUERY_THROW );
98 mxOutStrm = mxTempFile->getOutputStream();
99 mxSeekable.set( mxOutStrm, UNO_QUERY );
101 catch(const Exception& )
106 OleOutputStream::~OleOutputStream()
110 void SAL_CALL OleOutputStream::seek( sal_Int64 nPos ) throw( IllegalArgumentException, IOException, RuntimeException )
112 ensureSeekable();
113 mxSeekable->seek( nPos );
116 sal_Int64 SAL_CALL OleOutputStream::getPosition() throw( IOException, RuntimeException )
118 ensureSeekable();
119 return mxSeekable->getPosition();
122 sal_Int64 SAL_CALL OleOutputStream::getLength() throw( IOException, RuntimeException )
124 ensureSeekable();
125 return mxSeekable->getLength();
128 void SAL_CALL OleOutputStream::writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
130 ensureConnected();
131 mxOutStrm->writeBytes( rData );
134 void SAL_CALL OleOutputStream::flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
136 ensureConnected();
137 mxOutStrm->flush();
140 void SAL_CALL OleOutputStream::closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
142 ensureConnected();
143 ensureSeekable();
144 // remember the class members
145 Reference< XOutputStream > xOutStrm = mxOutStrm;
146 Reference< XSeekable > xSeekable = mxSeekable;
147 // reset all class members
148 mxOutStrm.clear();
149 mxSeekable.clear();
150 // close stream (and let it throw something if needed)
151 xOutStrm->closeOutput();
152 // on success, insert the stream into the OLE storage (must be seeked back before)
153 xSeekable->seek( 0 );
154 if( !ContainerHelper::insertByName( mxStorage, maElementName, Any( mxTempFile ) ) )
155 throw IOException();
158 void OleOutputStream::ensureSeekable() const throw( IOException )
160 if( !mxSeekable.is() )
161 throw IOException();
164 void OleOutputStream::ensureConnected() const throw( NotConnectedException )
166 if( !mxOutStrm.is() )
167 throw NotConnectedException();
170 } // namespace
172 // ============================================================================
174 OleStorage::OleStorage( const Reference< XComponentContext >& rxContext,
175 const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) :
176 StorageBase( rxInStream, bBaseStreamAccess ),
177 mxContext( rxContext ),
178 mpParentStorage( 0 )
180 OSL_ENSURE( mxContext.is(), "OleStorage::OleStorage - missing component context" );
181 initStorage( rxInStream );
184 OleStorage::OleStorage( const Reference< XComponentContext >& rxContext,
185 const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) :
186 StorageBase( rxOutStream, bBaseStreamAccess ),
187 mxContext( rxContext ),
188 mpParentStorage( 0 )
190 OSL_ENSURE( mxContext.is(), "OleStorage::OleStorage - missing component context" );
191 initStorage( rxOutStream );
194 OleStorage::OleStorage( const OleStorage& rParentStorage,
195 const Reference< XNameContainer >& rxStorage, const OUString& rElementName, bool bReadOnly ) :
196 StorageBase( rParentStorage, rElementName, bReadOnly ),
197 mxContext( rParentStorage.mxContext ),
198 mxStorage( rxStorage ),
199 mpParentStorage( &rParentStorage )
201 OSL_ENSURE( mxStorage.is(), "OleStorage::OleStorage - missing substorage elements" );
204 OleStorage::OleStorage( const OleStorage& rParentStorage,
205 const Reference< XStream >& rxOutStream, const OUString& rElementName ) :
206 StorageBase( rParentStorage, rElementName, false ),
207 mxContext( rParentStorage.mxContext ),
208 mpParentStorage( &rParentStorage )
210 initStorage( rxOutStream );
213 OleStorage::~OleStorage()
217 // ----------------------------------------------------------------------------
219 void OleStorage::initStorage( const Reference< XInputStream >& rxInStream )
221 // if stream is not seekable, create temporary copy
222 Reference< XInputStream > xInStrm = rxInStream;
223 if( !Reference< XSeekable >( xInStrm, UNO_QUERY ).is() ) try
225 Reference< XStream > xTempFile( TempFile::create(mxContext), UNO_QUERY_THROW );
227 Reference< XOutputStream > xOutStrm( xTempFile->getOutputStream(), UNO_SET_THROW );
228 /* Pass false to both binary stream objects to keep the UNO
229 streams alive. Life time of these streams is controlled by the
230 tempfile implementation. */
231 BinaryXOutputStream aOutStrm( xOutStrm, false );
232 BinaryXInputStream aInStrm( xInStrm, false );
233 aInStrm.copyToStream( aOutStrm );
234 } // scope closes output stream of tempfile
235 xInStrm = xTempFile->getInputStream();
237 catch(const Exception& )
239 OSL_FAIL( "OleStorage::initStorage - cannot create temporary copy of input stream" );
242 // create base storage object
243 if( xInStrm.is() ) try
245 Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW );
246 Sequence< Any > aArgs( 2 );
247 aArgs[ 0 ] <<= xInStrm;
248 aArgs[ 1 ] <<= true; // true = do not create a copy of the input stream
249 mxStorage.set( xFactory->createInstanceWithArguments("com.sun.star.embed.OLESimpleStorage", aArgs ), UNO_QUERY_THROW );
251 catch(const Exception& )
256 void OleStorage::initStorage( const Reference< XStream >& rxOutStream )
258 // create base storage object
259 if( rxOutStream.is() ) try
261 Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW );
262 Sequence< Any > aArgs( 2 );
263 aArgs[ 0 ] <<= rxOutStream;
264 aArgs[ 1 ] <<= true; // true = do not create a copy of the stream
265 mxStorage.set( xFactory->createInstanceWithArguments("com.sun.star.embed.OLESimpleStorage", aArgs ), UNO_QUERY_THROW );
267 catch(const Exception& )
272 // StorageBase interface ------------------------------------------------------
274 bool OleStorage::implIsStorage() const
276 if( mxStorage.is() ) try
278 /* If this is not an OLE storage, hasElements() of the OLESimpleStorage
279 implementation throws an exception. But we do not return the result
280 of hasElements(), because an empty storage is a valid storage too. */
281 mxStorage->hasElements();
282 return true;
284 catch(const Exception& )
287 return false;
290 Reference< XStorage > OleStorage::implGetXStorage() const
292 OSL_FAIL( "OleStorage::getXStorage - not implemented" );
293 return Reference< XStorage >();
296 void OleStorage::implGetElementNames( ::std::vector< OUString >& orElementNames ) const
298 Sequence< OUString > aNames;
299 if( mxStorage.is() ) try
301 aNames = mxStorage->getElementNames();
302 if( aNames.getLength() > 0 )
303 orElementNames.insert( orElementNames.end(), aNames.getConstArray(), aNames.getConstArray() + aNames.getLength() );
305 catch(const Exception& )
310 StorageRef OleStorage::implOpenSubStorage( const OUString& rElementName, bool bCreateMissing )
312 StorageRef xSubStorage;
313 if( mxStorage.is() && !rElementName.isEmpty() )
317 Reference< XNameContainer > xSubElements( mxStorage->getByName( rElementName ), UNO_QUERY_THROW );
318 xSubStorage.reset( new OleStorage( *this, xSubElements, rElementName, true ) );
320 catch(const Exception& )
324 /* The OLESimpleStorage API implementation seems to be buggy in the
325 area of writable inplace substorage (sometimes it overwrites other
326 unrelated streams with zero bytes). We go the save way and create a
327 new OLE storage based on a temporary file. All operations are
328 performed on this clean storage. On committing, the storage will be
329 completely re-inserted into the parent storage. */
330 if( !isReadOnly() && (bCreateMissing || xSubStorage.get()) ) try
332 // create new storage based on a temp file
333 Reference< XStream > xTempFile( TempFile::create(mxContext), UNO_QUERY_THROW );
334 StorageRef xTempStorage( new OleStorage( *this, xTempFile, rElementName ) );
335 // copy existing substorage into temp storage
336 if( xSubStorage.get() )
337 xSubStorage->copyStorageToStorage( *xTempStorage );
338 // return the temp storage to caller
339 xSubStorage = xTempStorage;
341 catch(const Exception& )
345 return xSubStorage;
348 Reference< XInputStream > OleStorage::implOpenInputStream( const OUString& rElementName )
350 Reference< XInputStream > xInStream;
351 if( mxStorage.is() ) try
353 xInStream.set( mxStorage->getByName( rElementName ), UNO_QUERY );
355 catch(const Exception& )
358 return xInStream;
361 Reference< XOutputStream > OleStorage::implOpenOutputStream( const OUString& rElementName )
363 Reference< XOutputStream > xOutStream;
364 if( mxStorage.is() && !rElementName.isEmpty() )
365 xOutStream.set( new OleOutputStream( mxContext, mxStorage, rElementName ) );
366 return xOutStream;
369 void OleStorage::implCommit() const
373 // commit this storage (finalizes the file this storage is based on)
374 Reference< XTransactedObject >( mxStorage, UNO_QUERY_THROW )->commit();
375 // re-insert this storage into the parent storage
376 if( mpParentStorage )
378 if( mpParentStorage->mxStorage->hasByName( getName() ) )
380 // replaceByName() does not work (#i109539#)
381 mpParentStorage->mxStorage->removeByName( getName() );
382 Reference< XTransactedObject >( mpParentStorage->mxStorage, UNO_QUERY_THROW )->commit();
384 mpParentStorage->mxStorage->insertByName( getName(), Any( mxStorage ) );
385 // this requires another commit(), which will be performed by the parent storage
388 catch(const Exception& )
393 // ============================================================================
395 } // namespace ole
396 } // namespace oox
398 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */