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