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