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