xref: /AOO41X/main/ucb/source/ucp/file/filstr.cxx (revision 2f86921c33504fdff5a030df6c0b258927045abb)
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_ucb.hxx"
26 #include "com/sun/star/io/IOException.hpp"
27 #include "com/sun/star/uno/RuntimeException.hpp"
28 #include "osl/diagnose.h"
29 #include "filstr.hxx"
30 #include "shell.hxx"
31 #include "prov.hxx"
32 
33 
34 using namespace fileaccess;
35 using namespace com::sun::star;
36 using namespace com::sun::star::ucb;
37 
38 
39 
40 /******************************************************************************/
41 /*                                                                            */
42 /*               XStream_impl implementation                                  */
43 /*                                                                            */
44 /******************************************************************************/
45 
46 
47 uno::Any SAL_CALL
queryInterface(const uno::Type & rType)48 XStream_impl::queryInterface(
49     const uno::Type& rType )
50     throw( uno::RuntimeException)
51 {
52     uno::Any aRet = cppu::queryInterface( rType,
53                                           SAL_STATIC_CAST( lang::XTypeProvider*,this ),
54                                           SAL_STATIC_CAST( io::XStream*,this ),
55                                           SAL_STATIC_CAST( io::XInputStream*,this ),
56                                           SAL_STATIC_CAST( io::XOutputStream*,this ),
57                                           SAL_STATIC_CAST( io::XSeekable*,this ),
58                                           SAL_STATIC_CAST( io::XTruncate*,this ),
59                                           SAL_STATIC_CAST( io::XAsyncOutputMonitor*,this ) );
60     return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
61 }
62 
63 
64 void SAL_CALL
acquire(void)65 XStream_impl::acquire(
66     void )
67     throw()
68 {
69     OWeakObject::acquire();
70 }
71 
72 
73 void SAL_CALL
release(void)74 XStream_impl::release(
75     void )
76     throw()
77 {
78     OWeakObject::release();
79 }
80 
81 
82 //////////////////////////////////////////////////////////////////////////////////////////
83 //  XTypeProvider
84 //////////////////////////////////////////////////////////////////////////////////////////
85 
86 
XTYPEPROVIDER_IMPL_7(XStream_impl,lang::XTypeProvider,io::XStream,io::XSeekable,io::XInputStream,io::XOutputStream,io::XTruncate,io::XAsyncOutputMonitor)87 XTYPEPROVIDER_IMPL_7( XStream_impl,
88                       lang::XTypeProvider,
89                       io::XStream,
90                       io::XSeekable,
91                       io::XInputStream,
92                       io::XOutputStream,
93                       io::XTruncate,
94                       io::XAsyncOutputMonitor )
95 
96 
97 
98 XStream_impl::XStream_impl( shell* pMyShell,const rtl::OUString& aUncPath, sal_Bool bLock )
99     : m_bInputStreamCalled( false ),
100       m_bOutputStreamCalled( false ),
101       m_pMyShell( pMyShell ),
102       m_xProvider( m_pMyShell->m_pProvider ),
103       m_bLock( bLock ),
104       m_aFile( aUncPath ),
105       m_nErrorCode( TASKHANDLER_NO_ERROR ),
106       m_nMinorErrorCode( TASKHANDLER_NO_ERROR )
107 {
108     sal_uInt32 nFlags = ( OpenFlag_Read | OpenFlag_Write );
109     if ( !bLock )
110         nFlags |= OpenFlag_NoLock;
111 
112     osl::FileBase::RC err = m_aFile.open( nFlags );
113     if(  err != osl::FileBase::E_None )
114     {
115         m_nIsOpen = false;
116         m_aFile.close();
117 
118         m_nErrorCode = TASKHANDLING_OPEN_FOR_STREAM;
119         m_nMinorErrorCode = err;
120     }
121     else
122         m_nIsOpen = true;
123 }
124 
125 
~XStream_impl()126 XStream_impl::~XStream_impl()
127 {
128     try
129     {
130         closeStream();
131     }
132     catch (io::IOException const &)
133     {
134         OSL_ENSURE(false, "unexpected situation");
135     }
136     catch (uno::RuntimeException const &)
137     {
138         OSL_ENSURE(false, "unexpected situation");
139     }
140 }
141 
142 
CtorSuccess()143 sal_Int32 SAL_CALL XStream_impl::CtorSuccess()
144 {
145     return m_nErrorCode;
146 }
147 
148 
149 
getMinorError()150 sal_Int32 SAL_CALL XStream_impl::getMinorError()
151 {
152     return m_nMinorErrorCode;
153 }
154 
155 
156 
157 uno::Reference< io::XInputStream > SAL_CALL
getInputStream()158 XStream_impl::getInputStream(  )
159     throw( uno::RuntimeException)
160 {
161     {
162         osl::MutexGuard aGuard( m_aMutex );
163         m_bInputStreamCalled = true;
164     }
165     return uno::Reference< io::XInputStream >( this );
166 }
167 
168 
169 uno::Reference< io::XOutputStream > SAL_CALL
getOutputStream()170 XStream_impl::getOutputStream(  )
171     throw( uno::RuntimeException )
172 {
173     {
174         osl::MutexGuard aGuard( m_aMutex );
175         m_bOutputStreamCalled = true;
176     }
177     return uno::Reference< io::XOutputStream >( this );
178 }
179 
180 
truncate(void)181 void SAL_CALL XStream_impl::truncate(void)
182     throw( io::IOException, uno::RuntimeException )
183 {
184     if (osl::FileBase::E_None != m_aFile.setSize(0))
185         throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
186 
187     if (osl::FileBase::E_None != m_aFile.setPos(Pos_Absolut,sal_uInt64(0)))
188         throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
189 }
190 
191 
192 
193 //===========================================================================
194 // XStream_impl private non interface methods
195 //===========================================================================
196 
197 sal_Int32 SAL_CALL
readBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nBytesToRead)198 XStream_impl::readBytes(
199     uno::Sequence< sal_Int8 >& aData,
200     sal_Int32 nBytesToRead )
201     throw( io::NotConnectedException,
202            io::BufferSizeExceededException,
203            io::IOException,
204            uno::RuntimeException)
205 {
206     if( ! m_nIsOpen )
207         throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
208 
209     sal_Int8 * buffer;
210     try
211     {
212         buffer = new sal_Int8[nBytesToRead];
213     }
214     catch( std::bad_alloc )
215     {
216         if( m_nIsOpen ) m_aFile.close();
217         throw io::BufferSizeExceededException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
218     }
219 
220     sal_uInt64 nrc(0);
221     if(m_aFile.read( (void* )buffer,sal_uInt64(nBytesToRead),nrc )
222        != osl::FileBase::E_None)
223     {
224         delete[] buffer;
225         throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
226     }
227     aData = uno::Sequence< sal_Int8 > ( buffer, (sal_uInt32)nrc );
228     delete[] buffer;
229     return ( sal_Int32 ) nrc;
230 }
231 
232 
233 sal_Int32 SAL_CALL
readSomeBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)234 XStream_impl::readSomeBytes(
235     uno::Sequence< sal_Int8 >& aData,
236     sal_Int32 nMaxBytesToRead )
237     throw( io::NotConnectedException,
238            io::BufferSizeExceededException,
239            io::IOException,
240            uno::RuntimeException)
241 {
242     return readBytes( aData,nMaxBytesToRead );
243 }
244 
245 
246 void SAL_CALL
skipBytes(sal_Int32 nBytesToSkip)247 XStream_impl::skipBytes(
248     sal_Int32 nBytesToSkip )
249     throw( io::NotConnectedException,
250            io::BufferSizeExceededException,
251            io::IOException,
252            uno::RuntimeException )
253 {
254     m_aFile.setPos( osl_Pos_Current, sal_uInt64( nBytesToSkip ) );
255 }
256 
257 
258 sal_Int32 SAL_CALL
available(void)259 XStream_impl::available(
260     void )
261     throw( io::NotConnectedException,
262            io::IOException,
263            uno::RuntimeException)
264 {
265     return 0;
266 }
267 
268 
269 void SAL_CALL
writeBytes(const uno::Sequence<sal_Int8> & aData)270 XStream_impl::writeBytes( const uno::Sequence< sal_Int8 >& aData )
271     throw( io::NotConnectedException,
272            io::BufferSizeExceededException,
273            io::IOException,
274            uno::RuntimeException)
275 {
276     sal_uInt32 length = aData.getLength();
277     if(length)
278     {
279         sal_uInt64 nWrittenBytes(0);
280         const sal_Int8* p = aData.getConstArray();
281         if(osl::FileBase::E_None != m_aFile.write(((void*)(p)),sal_uInt64(length),nWrittenBytes) ||
282            nWrittenBytes != length )
283             throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
284     }
285 }
286 
287 
288 void SAL_CALL
closeStream(void)289 XStream_impl::closeStream(
290     void )
291     throw( io::NotConnectedException,
292            io::IOException,
293            uno::RuntimeException )
294 {
295     if( m_nIsOpen )
296     {
297         osl::FileBase::RC err = m_aFile.close();
298 
299         if( err != osl::FileBase::E_None ) {
300             io::IOException ex;
301             ex.Message = rtl::OUString::createFromAscii(
302                 "could not close file");
303             throw ex;
304         }
305 
306         m_nIsOpen = false;
307     }
308 }
309 
310 void SAL_CALL
closeInput(void)311 XStream_impl::closeInput(
312     void )
313     throw( io::NotConnectedException,
314            io::IOException,
315            uno::RuntimeException )
316 {
317     osl::MutexGuard aGuard( m_aMutex );
318     m_bInputStreamCalled = false;
319 
320     if( ! m_bOutputStreamCalled )
321         closeStream();
322 }
323 
324 
325 void SAL_CALL
closeOutput(void)326 XStream_impl::closeOutput(
327     void )
328     throw( io::NotConnectedException,
329            io::IOException,
330            uno::RuntimeException )
331 {
332     osl::MutexGuard aGuard( m_aMutex );
333     m_bOutputStreamCalled = false;
334 
335     if( ! m_bInputStreamCalled )
336         closeStream();
337 }
338 
339 
340 void SAL_CALL
seek(sal_Int64 location)341 XStream_impl::seek(
342     sal_Int64 location )
343     throw( lang::IllegalArgumentException,
344            io::IOException,
345            uno::RuntimeException )
346 {
347     if( location < 0 )
348         throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 );
349     if( osl::FileBase::E_None != m_aFile.setPos( Pos_Absolut, sal_uInt64( location ) ) )
350         throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
351 }
352 
353 
354 sal_Int64 SAL_CALL
getPosition(void)355 XStream_impl::getPosition(
356     void )
357     throw( io::IOException,
358            uno::RuntimeException )
359 {
360     sal_uInt64 uPos;
361     if( osl::FileBase::E_None != m_aFile.getPos( uPos ) )
362         throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
363     return sal_Int64( uPos );
364 }
365 
366 sal_Int64 SAL_CALL
getLength(void)367 XStream_impl::getLength(
368     void )
369     throw( io::IOException,
370            uno::RuntimeException )
371 {
372         sal_uInt64 uEndPos;
373         if ( m_aFile.getSize(uEndPos) != osl::FileBase::E_None )
374                 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
375         else
376                 return sal_Int64( uEndPos );
377 }
378 
379 void SAL_CALL
flush()380 XStream_impl::flush()
381     throw( io::NotConnectedException,
382            io::BufferSizeExceededException,
383            io::IOException,
384            uno::RuntimeException )
385 {}
386 
waitForCompletion()387 void XStream_impl::waitForCompletion()
388     throw (io::IOException, uno::RuntimeException)
389 {
390     // At least on UNIX, to reliably learn about any errors encountered by
391     // asynchronous NFS write operations, without closing the file directly
392     // afterwards, there appears to be no cheaper way than to call fsync:
393     if (m_nIsOpen && m_aFile.sync() != osl::FileBase::E_None) {
394         throw io::IOException(
395             rtl::OUString(
396                 RTL_CONSTASCII_USTRINGPARAM(
397                     "could not synchronize file to disc")),
398             static_cast< OWeakObject * >(this));
399     }
400 }
401