1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: opostponedtruncationstream.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
33 #include <osl/diagnose.h>
35 #include <opostponedtruncationstream.hxx>
37 using namespace ::com::sun::star
;
39 // ========================================================================
40 struct PTFStreamData_Impl
42 uno::Reference
< ucb::XSimpleFileAccess
> m_xFileAccess
;
44 ::rtl::OUString m_aURL
;
46 // the streams below are not visible from outside so there is no need to remember position
48 // original stream related members
49 uno::Reference
< io::XStream
> m_xOrigStream
;
50 uno::Reference
< io::XTruncate
> m_xOrigTruncate
;
51 uno::Reference
< io::XSeekable
> m_xOrigSeekable
;
52 uno::Reference
< io::XInputStream
> m_xOrigInStream
;
53 uno::Reference
< io::XOutputStream
> m_xOrigOutStream
;
58 sal_Bool m_bPostponedTruncate
;
62 const uno::Reference
< ucb::XSimpleFileAccess
>& xFileAccess
,
64 const ::rtl::OUString
& aURL
,
65 const uno::Reference
< io::XStream
>& xOrigStream
,
66 const uno::Reference
< io::XTruncate
>& xOrigTruncate
,
67 const uno::Reference
< io::XSeekable
>& xOrigSeekable
,
68 const uno::Reference
< io::XInputStream
>& xOrigInStream
,
69 const uno::Reference
< io::XOutputStream
>& xOrigOutStream
)
70 : m_xFileAccess( xFileAccess
)
71 , m_bDelete( bDelete
)
73 , m_xOrigStream( xOrigStream
)
74 , m_xOrigTruncate( xOrigTruncate
)
75 , m_xOrigSeekable( xOrigSeekable
)
76 , m_xOrigInStream( xOrigInStream
)
77 , m_xOrigOutStream( xOrigOutStream
)
78 , m_bInOpen( sal_False
)
79 , m_bOutOpen( sal_False
)
80 , m_bPostponedTruncate( sal_True
)
85 m_bDelete
= sal_False
;
86 m_bPostponedTruncate
= sal_False
;
90 // ========================================================================
91 // ------------------------------------------------------------------------
92 OPostponedTruncationFileStream::OPostponedTruncationFileStream(
93 const ::rtl::OUString
& aURL
,
94 const uno::Reference
< lang::XMultiServiceFactory
>& /*xFactory*/,
95 const uno::Reference
< ucb::XSimpleFileAccess
>& xFileAccess
,
96 const uno::Reference
< io::XStream
>& xOrigStream
,
98 : m_pStreamData( NULL
)
100 if ( !xFileAccess
.is() || !xOrigStream
.is() )
101 throw uno::RuntimeException();
103 uno::Reference
< io::XTruncate
> xOrigTruncate( xOrigStream
, uno::UNO_QUERY_THROW
);
104 uno::Reference
< io::XSeekable
> xOrigSeekable( xOrigStream
, uno::UNO_QUERY_THROW
);
105 uno::Reference
< io::XInputStream
> xOrigInStream
= xOrigStream
->getInputStream();
106 uno::Reference
< io::XOutputStream
> xOrigOutStream
= xOrigStream
->getOutputStream();
107 if ( !xOrigInStream
.is() || !xOrigOutStream
.is() )
108 throw uno::RuntimeException();
110 m_pStreamData
= new PTFStreamData_Impl( xFileAccess
, bDelete
, aURL
,
111 xOrigStream
, xOrigTruncate
, xOrigSeekable
, xOrigInStream
, xOrigOutStream
);
114 // ------------------------------------------------------------------------
115 OPostponedTruncationFileStream::~OPostponedTruncationFileStream()
120 // ------------------------------------------------------------------------
121 void OPostponedTruncationFileStream::CloseAll_Impl()
125 sal_Bool bDelete
= m_pStreamData
->m_bDelete
;
126 ::rtl::OUString aURL
= m_pStreamData
->m_aURL
;
127 uno::Reference
< ucb::XSimpleFileAccess
> xFileAccess
= m_pStreamData
->m_xFileAccess
;
129 delete m_pStreamData
;
130 m_pStreamData
= NULL
;
132 if ( bDelete
&& xFileAccess
.is() && aURL
.getLength() )
137 xFileAccess
->kill( aURL
);
138 } catch( uno::Exception
& )
140 OSL_ENSURE( sal_False
, "Could not remove the file!" );
146 // ------------------------------------------------------------------------
147 void OPostponedTruncationFileStream::CheckScheduledTruncation_Impl()
149 if ( !m_pStreamData
)
150 throw io::NotConnectedException();
152 if ( m_pStreamData
->m_bPostponedTruncate
)
154 // the original stream data should be provided
155 if ( !m_pStreamData
->m_xOrigTruncate
.is() )
156 throw uno::RuntimeException();
158 m_pStreamData
->m_xOrigTruncate
->truncate();
159 m_pStreamData
->NoPostponing();
163 // com::sun::star::io::XStream
164 // ------------------------------------------------------------------------
165 uno::Reference
< io::XInputStream
> SAL_CALL
OPostponedTruncationFileStream::getInputStream( )
166 throw (uno::RuntimeException
)
168 ::osl::MutexGuard
aGuard( m_aMutex
);
171 m_pStreamData
->m_bInOpen
= sal_True
;
172 return static_cast< io::XInputStream
* >( this );
176 // ------------------------------------------------------------------------
177 uno::Reference
< io::XOutputStream
> SAL_CALL
OPostponedTruncationFileStream::getOutputStream( )
178 throw (uno::RuntimeException
)
180 ::osl::MutexGuard
aGuard( m_aMutex
);
183 m_pStreamData
->m_bOutOpen
= sal_True
;
184 return static_cast< io::XOutputStream
* >( this );
189 // com::sun::star::io::XInputStream
190 // ------------------------------------------------------------------------
191 ::sal_Int32 SAL_CALL
OPostponedTruncationFileStream::readBytes( uno::Sequence
< ::sal_Int8
>& aData
, ::sal_Int32 nBytesToRead
)
192 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
194 ::osl::MutexGuard
aGuard( m_aMutex
);
196 if ( !m_pStreamData
)
197 throw io::NotConnectedException();
199 if ( m_pStreamData
->m_bPostponedTruncate
)
201 // the stream must behave as truncated one
207 // the original stream data should be provided
208 if ( !m_pStreamData
->m_xOrigInStream
.is() )
209 throw uno::RuntimeException();
211 return m_pStreamData
->m_xOrigInStream
->readBytes( aData
, nBytesToRead
);
216 // ------------------------------------------------------------------------
217 ::sal_Int32 SAL_CALL
OPostponedTruncationFileStream::readSomeBytes( uno::Sequence
< ::sal_Int8
>& aData
, ::sal_Int32 nMaxBytesToRead
)
218 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
220 ::osl::MutexGuard
aGuard( m_aMutex
);
222 if ( !m_pStreamData
)
223 throw io::NotConnectedException();
225 if ( m_pStreamData
->m_bPostponedTruncate
)
227 // the stream must behave as truncated one
233 // the original stream data should be provided
234 if ( !m_pStreamData
->m_xOrigInStream
.is() )
235 throw uno::RuntimeException();
237 return m_pStreamData
->m_xOrigInStream
->readBytes( aData
, nMaxBytesToRead
);
241 // ------------------------------------------------------------------------
242 void SAL_CALL
OPostponedTruncationFileStream::skipBytes( ::sal_Int32 nBytesToSkip
)
243 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
245 ::osl::MutexGuard
aGuard( m_aMutex
);
247 if ( !m_pStreamData
)
248 throw io::NotConnectedException();
250 if ( m_pStreamData
->m_bPostponedTruncate
)
252 // the stream must behave as truncated one
253 if ( nBytesToSkip
> 0 )
254 throw io::BufferSizeExceededException();
260 // the original stream data should be provided
261 if ( !m_pStreamData
->m_xOrigInStream
.is() )
262 throw uno::RuntimeException();
264 m_pStreamData
->m_xOrigInStream
->skipBytes( nBytesToSkip
);
269 // ------------------------------------------------------------------------
270 ::sal_Int32 SAL_CALL
OPostponedTruncationFileStream::available( )
271 throw (io::NotConnectedException
, io::IOException
, uno::RuntimeException
)
273 ::osl::MutexGuard
aGuard( m_aMutex
);
275 if ( !m_pStreamData
)
276 throw io::NotConnectedException();
278 if ( m_pStreamData
->m_bPostponedTruncate
)
280 // the stream must behave as truncated one
285 // the original stream data should be provided
286 if ( !m_pStreamData
->m_xOrigInStream
.is() )
287 throw uno::RuntimeException();
289 return m_pStreamData
->m_xOrigInStream
->available();
294 // ------------------------------------------------------------------------
295 void SAL_CALL
OPostponedTruncationFileStream::closeInput()
296 throw (io::NotConnectedException
, io::IOException
, uno::RuntimeException
)
298 ::osl::MutexGuard
aGuard( m_aMutex
);
300 if ( !m_pStreamData
)
301 throw io::NotConnectedException();
303 m_pStreamData
->m_bInOpen
= sal_False
;
304 if ( !m_pStreamData
->m_bOutOpen
)
310 // com::sun::star::io::XOutputStream
311 // ------------------------------------------------------------------------
312 void SAL_CALL
OPostponedTruncationFileStream::writeBytes( const uno::Sequence
< ::sal_Int8
>& aData
)
313 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
315 ::osl::MutexGuard
aGuard( m_aMutex
);
317 if ( !m_pStreamData
)
318 throw io::NotConnectedException();
320 // writing method must check the truncation
321 CheckScheduledTruncation_Impl();
323 // the original stream data should be provided
324 if ( !m_pStreamData
->m_xOrigOutStream
.is() )
325 throw uno::RuntimeException();
327 m_pStreamData
->m_xOrigOutStream
->writeBytes( aData
);
331 // ------------------------------------------------------------------------
332 void SAL_CALL
OPostponedTruncationFileStream::flush( )
333 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
335 ::osl::MutexGuard
aGuard( m_aMutex
);
337 if ( !m_pStreamData
)
339 OSL_ENSURE( sal_False
, "flush() call on closed stream!\n" );
341 // in future throw exception, for now some code might call flush() on closed stream
342 // since file ucp implementation allows it
343 // throw io::NotConnectedException();
346 if ( m_pStreamData
->m_bPostponedTruncate
)
348 // it is no writing call, thus must be ignored
353 // the original stream data should be provided
354 if ( !m_pStreamData
->m_xOrigOutStream
.is() )
355 throw uno::RuntimeException();
357 m_pStreamData
->m_xOrigOutStream
->flush();
362 // ------------------------------------------------------------------------
363 void SAL_CALL
OPostponedTruncationFileStream::closeOutput( )
364 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
366 ::osl::MutexGuard
aGuard( m_aMutex
);
368 if ( !m_pStreamData
)
369 throw io::NotConnectedException();
371 m_pStreamData
->m_bOutOpen
= sal_False
;
372 if ( !m_pStreamData
->m_bInOpen
)
378 // com::sun::star::io::XTruncate
379 // ------------------------------------------------------------------------
380 void SAL_CALL
OPostponedTruncationFileStream::truncate( )
381 throw (io::IOException
, uno::RuntimeException
)
383 ::osl::MutexGuard
aGuard( m_aMutex
);
385 if ( !m_pStreamData
)
386 throw io::NotConnectedException();
388 if ( m_pStreamData
->m_bPostponedTruncate
)
390 // the truncation is already scheduled, ignore
395 // the original stream data should be provided
396 if ( !m_pStreamData
->m_xOrigTruncate
.is() )
397 throw uno::RuntimeException();
399 m_pStreamData
->m_xOrigTruncate
->truncate();
405 // com::sun::star::io::XSeekable
406 // ------------------------------------------------------------------------
407 void SAL_CALL
OPostponedTruncationFileStream::seek( ::sal_Int64 location
)
408 throw (lang::IllegalArgumentException
, io::IOException
, uno::RuntimeException
)
410 ::osl::MutexGuard
aGuard( m_aMutex
);
412 if ( !m_pStreamData
)
413 throw io::NotConnectedException();
415 if ( m_pStreamData
->m_bPostponedTruncate
)
418 throw lang::IllegalArgumentException();
424 // the original stream data should be provided
425 if ( !m_pStreamData
->m_xOrigSeekable
.is() )
426 throw uno::RuntimeException();
428 m_pStreamData
->m_xOrigSeekable
->seek( location
);
433 // ------------------------------------------------------------------------
434 ::sal_Int64 SAL_CALL
OPostponedTruncationFileStream::getPosition( )
435 throw (io::IOException
, uno::RuntimeException
)
437 ::osl::MutexGuard
aGuard( m_aMutex
);
439 if ( !m_pStreamData
)
440 throw io::NotConnectedException();
442 if ( m_pStreamData
->m_bPostponedTruncate
)
448 // the original stream data should be provided
449 if ( !m_pStreamData
->m_xOrigSeekable
.is() )
450 throw uno::RuntimeException();
452 return m_pStreamData
->m_xOrigSeekable
->getPosition();
457 // ------------------------------------------------------------------------
458 ::sal_Int64 SAL_CALL
OPostponedTruncationFileStream::getLength( )
459 throw (io::IOException
, uno::RuntimeException
)
461 ::osl::MutexGuard
aGuard( m_aMutex
);
463 if ( !m_pStreamData
)
464 throw io::NotConnectedException();
466 if ( m_pStreamData
->m_bPostponedTruncate
)
472 // the original stream data should be provided
473 if ( !m_pStreamData
->m_xOrigSeekable
.is() )
474 throw uno::RuntimeException();
476 return m_pStreamData
->m_xOrigSeekable
->getLength();
480 // ------------------------------------------------------------------------
481 void SAL_CALL
OPostponedTruncationFileStream::waitForCompletion()
482 throw (::com::sun::star::io::IOException
, ::com::sun::star::uno::RuntimeException
)
484 if ( !m_pStreamData
)
485 throw io::NotConnectedException();
487 if ( m_pStreamData
->m_bPostponedTruncate
)
490 uno::Reference
< io::XAsyncOutputMonitor
> asyncOutputMonitor( m_pStreamData
->m_xOrigOutStream
, uno::UNO_QUERY
);
491 if ( asyncOutputMonitor
.is() )
492 asyncOutputMonitor
->waitForCompletion();