xref: /aoo4110/main/ucb/source/ucp/file/filstr.cxx (revision b1cdbd2c)
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