xref: /AOO41X/main/comphelper/source/streaming/otransactedfilestream.cxx (revision 49b34792d04777c7048569d1e476ae6e26e03037)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_comphelper.hxx"
26 #include <osl/diagnose.h>
27 #include <com/sun/star/beans/PropertyAttribute.hpp>
28 #include <com/sun/star/io/XAsyncOutputMonitor.hpp>
29 #include <com/sun/star/embed/UseBackupException.hpp>
30 
31 #include <comphelper/otransactedfilestream.hxx>
32 #include <comphelper/storagehelper.hxx>
33 #include <cppuhelper/implbase1.hxx>
34 
35 using namespace ::com::sun::star;
36 
37 namespace comphelper
38 {
39 
40 // ========================================================================
41 class OTransactionHelper : public ::cppu::WeakImplHelper1 < embed::XTransactedObject >
42 {
43     OTruncatedTransactedFileStream* m_pFileStream;
44     uno::Reference< io::XStream > m_xStreamHolder;
45 
46 public:
OTransactionHelper(OTruncatedTransactedFileStream * pStream)47     OTransactionHelper( OTruncatedTransactedFileStream* pStream )
48     : m_pFileStream( pStream )
49     {
50         m_xStreamHolder = static_cast< io::XStream* >( pStream );
51         if ( !m_xStreamHolder.is() )
52             throw uno::RuntimeException();
53     }
54 
55     virtual void SAL_CALL commit(  ) throw (io::IOException, lang::WrappedTargetException, uno::RuntimeException);
56     virtual void SAL_CALL revert(  ) throw (io::IOException, lang::WrappedTargetException, uno::RuntimeException);
57 };
58 
59 // ------------------------------------------------------------------------
commit()60 void SAL_CALL OTransactionHelper::commit(  ) throw (io::IOException, lang::WrappedTargetException, uno::RuntimeException)
61 {
62     m_pFileStream->Commit_Impl();
63 }
64 
65 // ------------------------------------------------------------------------
revert()66 void SAL_CALL OTransactionHelper::revert(  ) throw (io::IOException, lang::WrappedTargetException, uno::RuntimeException)
67 {
68     m_pFileStream->Revert_Impl();
69 }
70 
71 // ========================================================================
72 struct TTFileStreamData_Impl
73 {
74     uno::Reference< ucb::XSimpleFileAccess > m_xFileAccess;
75     sal_Bool m_bDelete;
76     ::rtl::OUString m_aURL;
77 
78     // the streams below are not visible from outside so there is no need to remember position
79 
80     // original stream related members
81     uno::Reference< io::XStream > m_xOrigStream;
82     uno::Reference< io::XTruncate > m_xOrigTruncate;
83     uno::Reference< io::XSeekable > m_xOrigSeekable;
84     uno::Reference< io::XInputStream > m_xOrigInStream;
85     uno::Reference< io::XOutputStream > m_xOrigOutStream;
86 
87     // temporary stream related members
88     uno::Reference< io::XStream > m_xTempStream;
89     uno::Reference< io::XTruncate > m_xTempTruncate;
90     uno::Reference< io::XSeekable > m_xTempSeekable;
91     uno::Reference< io::XInputStream > m_xTempInStream;
92     uno::Reference< io::XOutputStream > m_xTempOutStream;
93 
94     sal_Bool m_bInOpen;
95     sal_Bool m_bOutOpen;
96 
97     sal_Bool m_bTransacted;
98 
99 
TTFileStreamData_Implcomphelper::TTFileStreamData_Impl100     TTFileStreamData_Impl(
101             const uno::Reference< ucb::XSimpleFileAccess >& xFileAccess,
102             sal_Bool bDelete,
103             const ::rtl::OUString& aURL,
104             const uno::Reference< io::XStream >& xOrigStream,
105             const uno::Reference< io::XTruncate >& xOrigTruncate,
106             const uno::Reference< io::XSeekable >& xOrigSeekable,
107             const uno::Reference< io::XInputStream >& xOrigInStream,
108             const uno::Reference< io::XOutputStream >& xOrigOutStream,
109             const uno::Reference< io::XStream >& xTempStream,
110             const uno::Reference< io::XTruncate >& xTempTruncate,
111             const uno::Reference< io::XSeekable >& xTempSeekable,
112             const uno::Reference< io::XInputStream >& xTempInStream,
113             const uno::Reference< io::XOutputStream >& xTempOutStream )
114     : m_xFileAccess( xFileAccess )
115     , m_bDelete( bDelete )
116     , m_aURL( aURL )
117     , m_xOrigStream( xOrigStream )
118     , m_xOrigTruncate( xOrigTruncate )
119     , m_xOrigSeekable( xOrigSeekable )
120     , m_xOrigInStream( xOrigInStream )
121     , m_xOrigOutStream( xOrigOutStream )
122     , m_xTempStream( xTempStream )
123     , m_xTempTruncate( xTempTruncate )
124     , m_xTempSeekable( xTempSeekable )
125     , m_xTempInStream( xTempInStream )
126     , m_xTempOutStream( xTempOutStream )
127     , m_bInOpen( sal_False )
128     , m_bOutOpen( sal_False )
129     , m_bTransacted( sal_True )
130     {}
131 
NoTransactioncomphelper::TTFileStreamData_Impl132     void NoTransaction()
133     {
134         m_bDelete = sal_False;
135         m_bTransacted = sal_False;
136         m_xTempStream = uno::Reference< io::XStream >();
137         m_xTempTruncate = uno::Reference< io::XTruncate >();
138         m_xTempSeekable = uno::Reference< io::XSeekable >();
139         m_xTempInStream = uno::Reference< io::XInputStream >();
140         m_xTempOutStream = uno::Reference< io::XOutputStream >();
141     }
142 
FreeOriginalcomphelper::TTFileStreamData_Impl143     void FreeOriginal()
144     {
145         m_bDelete = sal_False;
146         m_bTransacted = sal_False;
147 
148         m_xOrigStream = m_xTempStream;
149         m_xTempStream = uno::Reference< io::XStream >();
150 
151         m_xOrigTruncate = m_xTempTruncate;
152         m_xTempTruncate = uno::Reference< io::XTruncate >();
153 
154         m_xOrigSeekable = m_xTempSeekable;
155         m_xTempSeekable = uno::Reference< io::XSeekable >();
156 
157         m_xOrigInStream = m_xTempInStream;
158         m_xTempInStream = uno::Reference< io::XInputStream >();
159 
160         m_xOrigOutStream = m_xTempOutStream;
161         m_xTempOutStream = uno::Reference< io::XOutputStream >();
162     }
163 };
164 
165 // ========================================================================
166 // ------------------------------------------------------------------------
OTruncatedTransactedFileStream(const::rtl::OUString & aURL,const uno::Reference<lang::XMultiServiceFactory> & xFactory)167 OTruncatedTransactedFileStream::OTruncatedTransactedFileStream(
168         const ::rtl::OUString& aURL,
169         const uno::Reference< lang::XMultiServiceFactory >& xFactory )
170 : m_pStreamData( NULL )
171 {
172     uno::Reference< ucb::XSimpleFileAccess > xSimpleFileAccess(
173         xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.SimpleFileAccess" ) ) ),
174         uno::UNO_QUERY_THROW );
175 
176     CommonInit_Impl( aURL, xSimpleFileAccess, xFactory, sal_False );
177 }
178 
179 // ------------------------------------------------------------------------
OTruncatedTransactedFileStream(const::rtl::OUString & aURL,const uno::Reference<ucb::XSimpleFileAccess> & xFileAccess,const uno::Reference<lang::XMultiServiceFactory> & xFactory)180 OTruncatedTransactedFileStream::OTruncatedTransactedFileStream(
181         const ::rtl::OUString& aURL,
182         const uno::Reference< ucb::XSimpleFileAccess >& xFileAccess,
183         const uno::Reference< lang::XMultiServiceFactory >& xFactory )
184 : m_pStreamData( NULL )
185 {
186     CommonInit_Impl( aURL, xFileAccess, xFactory, sal_False );
187 }
188 
189 // ------------------------------------------------------------------------
OTruncatedTransactedFileStream(const::rtl::OUString & aURL,const uno::Reference<ucb::XSimpleFileAccess> & xFileAccess,const uno::Reference<lang::XMultiServiceFactory> & xFactory,sal_Bool bDeleteIfNotCommited)190 OTruncatedTransactedFileStream::OTruncatedTransactedFileStream(
191         const ::rtl::OUString& aURL,
192         const uno::Reference< ucb::XSimpleFileAccess >& xFileAccess,
193         const uno::Reference< lang::XMultiServiceFactory >& xFactory,
194         sal_Bool bDeleteIfNotCommited )
195 : m_pStreamData( NULL )
196 {
197     CommonInit_Impl( aURL, xFileAccess, xFactory, sal_True );
198     if ( m_pStreamData )
199         m_pStreamData->m_bDelete = bDeleteIfNotCommited;
200 }
201 
202 // ------------------------------------------------------------------------
~OTruncatedTransactedFileStream()203 OTruncatedTransactedFileStream::~OTruncatedTransactedFileStream()
204 {
205     CloseAll_Impl();
206 }
207 
208 // ------------------------------------------------------------------------
CloseAll_Impl()209 void OTruncatedTransactedFileStream::CloseAll_Impl()
210 {
211     ::osl::MutexGuard aGuard( m_aMutex );
212 
213     if ( m_pStreamData )
214     {
215         sal_Bool bDelete = m_pStreamData->m_bDelete;
216         ::rtl::OUString aURL = m_pStreamData->m_aURL;
217         uno::Reference< ucb::XSimpleFileAccess > xFileAccess = m_pStreamData->m_xFileAccess;
218 
219         delete m_pStreamData;
220         m_pStreamData = NULL;
221 
222         if ( bDelete && xFileAccess.is() && !aURL.isEmpty() )
223         {
224             // delete the file
225             try
226             {
227                 xFileAccess->kill( aURL );
228             } catch( uno::Exception& )
229             {
230                 OSL_ENSURE( sal_False, "Could not remove the file!" );
231             }
232         }
233     }
234 }
235 
236 // ------------------------------------------------------------------------
CommonInit_Impl(const::rtl::OUString & aURL,const uno::Reference<ucb::XSimpleFileAccess> & xFileAccess,const uno::Reference<lang::XMultiServiceFactory> & xFactory,sal_Bool bDeleteOptionIsProvided)237 void OTruncatedTransactedFileStream::CommonInit_Impl(
238         const ::rtl::OUString& aURL,
239         const uno::Reference< ucb::XSimpleFileAccess >& xFileAccess,
240         const uno::Reference< lang::XMultiServiceFactory >& xFactory,
241         sal_Bool bDeleteOptionIsProvided )
242 {
243     sal_Bool bDelete = sal_False;
244     if ( !bDeleteOptionIsProvided )
245         bDelete = !xFileAccess->exists( aURL );
246 
247     uno::Reference< io::XStream > xOrigStream = xFileAccess->openFileReadWrite( aURL );
248     uno::Reference< io::XTruncate > xOrigTruncate( xOrigStream, uno::UNO_QUERY_THROW );
249     uno::Reference< io::XSeekable > xOrigSeekable( xOrigStream, uno::UNO_QUERY_THROW );
250     uno::Reference< io::XInputStream > xOrigInStream = xOrigStream->getInputStream();
251     uno::Reference< io::XOutputStream > xOrigOutStream = xOrigStream->getOutputStream();
252     if ( !xOrigInStream.is() || !xOrigOutStream.is() )
253         throw uno::RuntimeException();
254 
255     // temporary stream related members
256     uno::Reference< io::XStream > xTempStream( xFactory->createInstance(
257         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ) ),
258         uno::UNO_QUERY_THROW );
259     uno::Reference< io::XTruncate > xTempTruncate( xTempStream, uno::UNO_QUERY_THROW );
260     uno::Reference< io::XSeekable > xTempSeekable( xTempStream, uno::UNO_QUERY_THROW );
261     uno::Reference< io::XInputStream > xTempInStream = xTempStream->getInputStream();
262     uno::Reference< io::XOutputStream > xTempOutStream = xTempStream->getOutputStream();
263     if ( !xTempInStream.is() || !xTempOutStream.is() )
264         throw uno::RuntimeException();
265 
266     m_pStreamData = new TTFileStreamData_Impl( xFileAccess, bDelete, aURL,
267                                             xOrigStream, xOrigTruncate, xOrigSeekable, xOrigInStream, xOrigOutStream,
268                                             xTempStream, xTempTruncate, xTempSeekable, xTempInStream, xTempOutStream );
269 }
270 
271 // ------------------------------------------------------------------------
Commit_Impl()272 void OTruncatedTransactedFileStream::Commit_Impl()
273 {
274     ::osl::MutexGuard aGuard( m_aMutex );
275 
276     if ( !m_pStreamData )
277         throw io::NotConnectedException();
278 
279     if ( m_pStreamData->m_bTransacted )
280     {
281         sal_Int64 nPos = m_pStreamData->m_xTempSeekable->getPosition();
282         m_pStreamData->m_xTempSeekable->seek( 0 );
283 
284         // after the following step fails the information might be lost, throw an exception with URL of temporary file
285         try
286         {
287             m_pStreamData->m_xOrigTruncate->truncate();
288             OStorageHelper::CopyInputToOutput( m_pStreamData->m_xTempInStream, m_pStreamData->m_xOrigOutStream );
289             m_pStreamData->m_xOrigOutStream->flush();
290 
291             // in case the stream is based on a file it will implement the following interface
292             // the call should be used to be sure that the contents are written to the file system
293             uno::Reference< io::XAsyncOutputMonitor > asyncOutputMonitor( m_pStreamData->m_xOrigOutStream, uno::UNO_QUERY );
294             if ( asyncOutputMonitor.is() )
295                 asyncOutputMonitor->waitForCompletion();
296         }
297         catch( uno::Exception& )
298         {
299             ::rtl::OUString aTempURL;
300             try {
301                 uno::Reference< beans::XPropertySet > xTempFile( m_pStreamData->m_xTempStream, uno::UNO_QUERY_THROW );
302                 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
303                 aUrl >>= aTempURL;
304                 xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ),
305                                             uno::makeAny( sal_False ) );
306 
307                 m_pStreamData->m_xTempSeekable->seek( nPos );
308             }
309             catch( uno::Exception& )
310             {
311                 OSL_ENSURE( sal_False, "These calls are pretty simple, they should not fail!\n" );
312             }
313 
314             m_pStreamData->FreeOriginal();
315 
316             ::rtl::OUString aErrTxt( RTL_CONSTASCII_USTRINGPARAM ( "Writing file failed!" ) );
317             embed::UseBackupException aException( aErrTxt, uno::Reference< uno::XInterface >(), aTempURL );
318             throw lang::WrappedTargetException( aErrTxt,
319                                                 static_cast < OWeakObject * > ( this ),
320                                                 uno::makeAny ( aException ) );
321         }
322 
323         m_pStreamData->m_xOrigSeekable->seek( nPos );
324         m_pStreamData->NoTransaction();
325     }
326     else
327         throw io::NotConnectedException();
328 }
329 
330 // ------------------------------------------------------------------------
Revert_Impl()331 void OTruncatedTransactedFileStream::Revert_Impl()
332 {
333     ::osl::MutexGuard aGuard( m_aMutex );
334 
335     if ( !m_pStreamData )
336         throw io::NotConnectedException();
337 
338     if ( m_pStreamData->m_bTransacted )
339         m_pStreamData->m_xTempTruncate->truncate();
340     else
341         throw io::NotConnectedException();
342 }
343 
344 // com::sun::star::io::XStream
345 // ------------------------------------------------------------------------
getInputStream()346 uno::Reference< io::XInputStream > SAL_CALL OTruncatedTransactedFileStream::getInputStream(  )
347     throw (uno::RuntimeException)
348 {
349     ::osl::MutexGuard aGuard( m_aMutex );
350 
351     if ( m_pStreamData )
352         m_pStreamData->m_bInOpen = sal_True;
353     return static_cast< io::XInputStream* >( this );
354 }
355 
356 
357 // ------------------------------------------------------------------------
getOutputStream()358 uno::Reference< io::XOutputStream > SAL_CALL OTruncatedTransactedFileStream::getOutputStream(  )
359     throw (uno::RuntimeException)
360 {
361     ::osl::MutexGuard aGuard( m_aMutex );
362 
363     if ( m_pStreamData )
364         m_pStreamData->m_bOutOpen = sal_True;
365     return static_cast< io::XOutputStream* >( this );
366 }
367 
368 
369 
370 // com::sun::star::io::XInputStream
371 // ------------------------------------------------------------------------
readBytes(uno::Sequence<::sal_Int8> & aData,::sal_Int32 nBytesToRead)372 ::sal_Int32 SAL_CALL OTruncatedTransactedFileStream::readBytes( uno::Sequence< ::sal_Int8 >& aData, ::sal_Int32 nBytesToRead )
373     throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
374 {
375     ::osl::MutexGuard aGuard( m_aMutex );
376 
377     if ( !m_pStreamData )
378         throw io::NotConnectedException();
379 
380     if ( m_pStreamData->m_bTransacted )
381     {
382         // temporary stream data should be provided
383         if ( !m_pStreamData->m_xTempInStream.is() )
384             throw uno::RuntimeException();
385 
386         return m_pStreamData->m_xTempInStream->readBytes( aData, nBytesToRead );
387     }
388     else
389     {
390         // the original stream data should be provided
391         if ( !m_pStreamData->m_xOrigInStream.is() )
392             throw uno::RuntimeException();
393 
394         return m_pStreamData->m_xOrigInStream->readBytes( aData, nBytesToRead );
395     }
396 }
397 
398 
399 // ------------------------------------------------------------------------
readSomeBytes(uno::Sequence<::sal_Int8> & aData,::sal_Int32 nMaxBytesToRead)400 ::sal_Int32 SAL_CALL OTruncatedTransactedFileStream::readSomeBytes( uno::Sequence< ::sal_Int8 >& aData, ::sal_Int32 nMaxBytesToRead )
401     throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
402 {
403     ::osl::MutexGuard aGuard( m_aMutex );
404 
405     if ( !m_pStreamData )
406         throw io::NotConnectedException();
407 
408     if ( m_pStreamData->m_bTransacted )
409     {
410         // temporary stream data should be provided
411         if ( !m_pStreamData->m_xTempInStream.is() )
412             throw uno::RuntimeException();
413 
414         return m_pStreamData->m_xTempInStream->readSomeBytes( aData, nMaxBytesToRead );
415     }
416     else
417     {
418         // the original stream data should be provided
419         if ( !m_pStreamData->m_xOrigInStream.is() )
420             throw uno::RuntimeException();
421 
422         return m_pStreamData->m_xOrigInStream->readSomeBytes( aData, nMaxBytesToRead );
423     }
424 }
425 
426 // ------------------------------------------------------------------------
skipBytes(::sal_Int32 nBytesToSkip)427 void SAL_CALL OTruncatedTransactedFileStream::skipBytes( ::sal_Int32 nBytesToSkip )
428     throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
429 {
430     ::osl::MutexGuard aGuard( m_aMutex );
431 
432     if ( !m_pStreamData )
433         throw io::NotConnectedException();
434 
435     if ( m_pStreamData->m_bTransacted )
436     {
437         // temporary stream data should be provided
438         if ( !m_pStreamData->m_xTempInStream.is() )
439             throw uno::RuntimeException();
440 
441         m_pStreamData->m_xTempInStream->skipBytes( nBytesToSkip );
442     }
443     else
444     {
445         // the original stream data should be provided
446         if ( !m_pStreamData->m_xOrigInStream.is() )
447             throw uno::RuntimeException();
448 
449         m_pStreamData->m_xOrigInStream->skipBytes( nBytesToSkip );
450     }
451 }
452 
453 
454 // ------------------------------------------------------------------------
available()455 ::sal_Int32 SAL_CALL OTruncatedTransactedFileStream::available(  )
456     throw (io::NotConnectedException, io::IOException, uno::RuntimeException)
457 {
458     ::osl::MutexGuard aGuard( m_aMutex );
459 
460     if ( !m_pStreamData )
461         throw io::NotConnectedException();
462 
463     if ( m_pStreamData->m_bTransacted )
464     {
465         // temporary stream data should be provided
466         if ( !m_pStreamData->m_xTempInStream.is() )
467             throw uno::RuntimeException();
468 
469         return m_pStreamData->m_xTempInStream->available();
470     }
471     else
472     {
473         // the original stream data should be provided
474         if ( !m_pStreamData->m_xOrigInStream.is() )
475             throw uno::RuntimeException();
476 
477         return m_pStreamData->m_xOrigInStream->available();
478     }
479 }
480 
481 
482 // ------------------------------------------------------------------------
closeInput()483 void SAL_CALL OTruncatedTransactedFileStream::closeInput()
484     throw (io::NotConnectedException, io::IOException, uno::RuntimeException)
485 {
486     ::osl::MutexGuard aGuard( m_aMutex );
487 
488     if ( !m_pStreamData )
489         throw io::NotConnectedException();
490 
491     m_pStreamData->m_bInOpen = sal_False;
492     if ( !m_pStreamData->m_bOutOpen )
493         CloseAll_Impl();
494 }
495 
496 
497 
498 // com::sun::star::io::XOutputStream
499 // ------------------------------------------------------------------------
writeBytes(const uno::Sequence<::sal_Int8> & aData)500 void SAL_CALL OTruncatedTransactedFileStream::writeBytes( const uno::Sequence< ::sal_Int8 >& aData )
501     throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
502 {
503     ::osl::MutexGuard aGuard( m_aMutex );
504 
505     if ( !m_pStreamData )
506         throw io::NotConnectedException();
507 
508     if ( m_pStreamData->m_bTransacted )
509     {
510         // temporary stream data should be provided
511         if ( !m_pStreamData->m_xTempOutStream.is() )
512             throw uno::RuntimeException();
513 
514         m_pStreamData->m_xTempOutStream->writeBytes( aData );
515     }
516     else
517     {
518         // the original stream data should be provided
519         if ( !m_pStreamData->m_xOrigOutStream.is() )
520             throw uno::RuntimeException();
521 
522         m_pStreamData->m_xOrigOutStream->writeBytes( aData );
523     }
524 }
525 
526 
527 // ------------------------------------------------------------------------
flush()528 void SAL_CALL OTruncatedTransactedFileStream::flush(  )
529     throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
530 {
531     ::osl::MutexGuard aGuard( m_aMutex );
532 
533     if ( !m_pStreamData )
534     {
535         OSL_ENSURE( sal_False, "flush() call on closed stream!\n" );
536         return;
537         // in future throw exception, for now some code might call flush() on closed stream
538         // since file ucp implementation allows it
539         // throw io::NotConnectedException();
540     }
541 
542     if ( m_pStreamData->m_bTransacted )
543     {
544         // temporary stream data should be provided
545         if ( !m_pStreamData->m_xTempOutStream.is() )
546             throw uno::RuntimeException();
547 
548         m_pStreamData->m_xTempOutStream->flush();
549     }
550     else
551     {
552         // the original stream data should be provided
553         if ( !m_pStreamData->m_xOrigOutStream.is() )
554             throw uno::RuntimeException();
555 
556         m_pStreamData->m_xOrigOutStream->flush();
557     }
558 }
559 
560 
561 // ------------------------------------------------------------------------
closeOutput()562 void SAL_CALL OTruncatedTransactedFileStream::closeOutput(  )
563     throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
564 {
565     ::osl::MutexGuard aGuard( m_aMutex );
566 
567     if ( !m_pStreamData )
568         throw io::NotConnectedException();
569 
570     m_pStreamData->m_bOutOpen = sal_False;
571     if ( !m_pStreamData->m_bInOpen )
572         CloseAll_Impl();
573 }
574 
575 
576 
577 // com::sun::star::io::XTruncate
578 // ------------------------------------------------------------------------
truncate()579 void SAL_CALL OTruncatedTransactedFileStream::truncate(  )
580     throw (io::IOException, uno::RuntimeException)
581 {
582     ::osl::MutexGuard aGuard( m_aMutex );
583 
584     if ( !m_pStreamData )
585         throw io::NotConnectedException();
586 
587     if ( m_pStreamData->m_bTransacted )
588     {
589         // temporary stream data should be provided
590         if ( !m_pStreamData->m_xTempTruncate.is() )
591             throw uno::RuntimeException();
592 
593         m_pStreamData->m_xTempTruncate->truncate();
594     }
595     else
596     {
597         // the original stream data should be provided
598         if ( !m_pStreamData->m_xOrigTruncate.is() )
599             throw uno::RuntimeException();
600 
601         m_pStreamData->m_xOrigTruncate->truncate();
602     }
603 }
604 
605 
606 
607 // com::sun::star::io::XSeekable
608 // ------------------------------------------------------------------------
seek(::sal_Int64 location)609 void SAL_CALL OTruncatedTransactedFileStream::seek( ::sal_Int64 location )
610     throw (lang::IllegalArgumentException, io::IOException, uno::RuntimeException)
611 {
612     ::osl::MutexGuard aGuard( m_aMutex );
613 
614     if ( !m_pStreamData )
615         throw io::NotConnectedException();
616 
617     if ( m_pStreamData->m_bTransacted )
618     {
619         // temporary stream data should be provided
620         if ( !m_pStreamData->m_xTempSeekable.is() )
621             throw uno::RuntimeException();
622 
623         m_pStreamData->m_xTempSeekable->seek( location );
624     }
625     else
626     {
627         // the original stream data should be provided
628         if ( !m_pStreamData->m_xOrigSeekable.is() )
629             throw uno::RuntimeException();
630 
631         m_pStreamData->m_xOrigSeekable->seek( location );
632     }
633 }
634 
635 
636 // ------------------------------------------------------------------------
getPosition()637 ::sal_Int64 SAL_CALL OTruncatedTransactedFileStream::getPosition(  )
638     throw (io::IOException, uno::RuntimeException)
639 {
640     ::osl::MutexGuard aGuard( m_aMutex );
641 
642     if ( !m_pStreamData )
643         throw io::NotConnectedException();
644 
645     if ( m_pStreamData->m_bTransacted )
646     {
647         // temporary stream data should be provided
648         if ( !m_pStreamData->m_xTempSeekable.is() )
649             throw uno::RuntimeException();
650 
651         return m_pStreamData->m_xTempSeekable->getPosition();
652     }
653     else
654     {
655         // the original stream data should be provided
656         if ( !m_pStreamData->m_xOrigSeekable.is() )
657             throw uno::RuntimeException();
658 
659         return m_pStreamData->m_xOrigSeekable->getPosition();
660     }
661 }
662 
663 
664 // ------------------------------------------------------------------------
getLength()665 ::sal_Int64 SAL_CALL OTruncatedTransactedFileStream::getLength(  )
666     throw (io::IOException, uno::RuntimeException)
667 {
668     ::osl::MutexGuard aGuard( m_aMutex );
669 
670     if ( !m_pStreamData )
671         throw io::NotConnectedException();
672 
673     if ( m_pStreamData->m_bTransacted )
674     {
675         // temporary stream data should be provided
676         if ( !m_pStreamData->m_xTempSeekable.is() )
677             throw uno::RuntimeException();
678 
679         return m_pStreamData->m_xTempSeekable->getLength();
680     }
681     else
682     {
683         // the original stream data should be provided
684         if ( !m_pStreamData->m_xOrigSeekable.is() )
685             throw uno::RuntimeException();
686 
687         return m_pStreamData->m_xOrigSeekable->getLength();
688     }
689 }
690 
691 // com::sun::star::beans::XPropertySetInfo
692 // ------------------------------------------------------------------------
getProperties()693 uno::Sequence< beans::Property > SAL_CALL OTruncatedTransactedFileStream::getProperties()
694     throw (uno::RuntimeException)
695 {
696     ::osl::MutexGuard aGuard( m_aMutex );
697 
698     uno::Sequence< beans::Property > aProps( 1 );
699     aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) );
700     aProps[0].Type = getCppuType( static_cast< uno::Reference< beans::XPropertySet >* >( NULL ) );
701     aProps[0].Attributes = beans::PropertyAttribute::TRANSIENT | beans::PropertyAttribute::READONLY;
702 
703     return aProps;
704 }
705 
706 
707 // ------------------------------------------------------------------------
getPropertyByName(const::rtl::OUString & aName)708 beans::Property SAL_CALL OTruncatedTransactedFileStream::getPropertyByName( const ::rtl::OUString& aName )
709     throw (beans::UnknownPropertyException, uno::RuntimeException)
710 {
711     ::osl::MutexGuard aGuard( m_aMutex );
712 
713     ::rtl::OUString aTransactionPropName( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) );
714 
715     if ( !aName.equals( aTransactionPropName ) )
716         throw beans::UnknownPropertyException();
717 
718     beans::Property aProp;
719     aProp.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) );
720     aProp.Type = getCppuType( static_cast< uno::Reference< beans::XPropertySet >* >( NULL ) );
721     aProp.Attributes = beans::PropertyAttribute::TRANSIENT | beans::PropertyAttribute::READONLY;
722 
723     return aProp;
724 }
725 
726 
727 // ------------------------------------------------------------------------
hasPropertyByName(const::rtl::OUString & Name)728 ::sal_Bool SAL_CALL OTruncatedTransactedFileStream::hasPropertyByName( const ::rtl::OUString& Name )
729     throw (uno::RuntimeException)
730 {
731     ::osl::MutexGuard aGuard( m_aMutex );
732 
733     ::rtl::OUString aTransactionPropName( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) );
734     return ( Name.equals( aTransactionPropName ) );
735 }
736 
737 
738 
739 // com::sun::star::beans::XPropertySet
740 // ------------------------------------------------------------------------
getPropertySetInfo()741 uno::Reference< beans::XPropertySetInfo > SAL_CALL OTruncatedTransactedFileStream::getPropertySetInfo()
742     throw (uno::RuntimeException)
743 {
744     ::osl::MutexGuard aGuard( m_aMutex );
745 
746     return static_cast< beans::XPropertySetInfo* >( this );
747 }
748 
749 
750 // ------------------------------------------------------------------------
setPropertyValue(const::rtl::OUString & aPropertyName,const uno::Any &)751 void SAL_CALL OTruncatedTransactedFileStream::setPropertyValue( const ::rtl::OUString& aPropertyName, const uno::Any& )
752     throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
753 {
754     ::osl::MutexGuard aGuard( m_aMutex );
755 
756     ::rtl::OUString aTransactionPropName( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) );
757     if ( aPropertyName.equals( aTransactionPropName ) )
758         throw beans::PropertyVetoException();
759 
760     throw beans::UnknownPropertyException();
761 }
762 
763 
764 // ------------------------------------------------------------------------
getPropertyValue(const::rtl::OUString & PropertyName)765 uno::Any SAL_CALL OTruncatedTransactedFileStream::getPropertyValue( const ::rtl::OUString& PropertyName )
766     throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
767 {
768     ::osl::MutexGuard aGuard( m_aMutex );
769 
770     if ( !m_pStreamData )
771         throw io::NotConnectedException();
772 
773     ::rtl::OUString aTransactionPropName( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) );
774     if ( PropertyName.equals( aTransactionPropName ) )
775     {
776         uno::Reference< embed::XTransactedObject > xObj;
777         if ( m_pStreamData->m_bTransacted )
778             xObj = static_cast< embed::XTransactedObject* >( new OTransactionHelper( this ) );
779 
780         return uno::makeAny( xObj );
781     }
782 
783     throw beans::UnknownPropertyException();
784 }
785 
786 
787 // ------------------------------------------------------------------------
addPropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)788 void SAL_CALL OTruncatedTransactedFileStream::addPropertyChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener >& )
789     throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
790 {
791     // not implemented
792 }
793 
794 
795 // ------------------------------------------------------------------------
removePropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)796 void SAL_CALL OTruncatedTransactedFileStream::removePropertyChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener >& )
797     throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
798 {
799     // not implemented
800 }
801 
802 
803 // ------------------------------------------------------------------------
addVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)804 void SAL_CALL OTruncatedTransactedFileStream::addVetoableChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener >& )
805     throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
806 {
807     // not implemented
808 }
809 
810 
811 // ------------------------------------------------------------------------
removeVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)812 void SAL_CALL OTruncatedTransactedFileStream::removeVetoableChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener >& )
813     throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
814 {
815     // not implemented
816 }
817 
818 
819 } // namespace comphelper
820 
821