Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / unotools / source / ucbhelper / xtempfile.cxx
blob62d4fb77ddb80a43015228c4ab3093ddbd58cc79
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include <XTempFile.hxx>
20 #include <cppuhelper/factory.hxx>
21 #include <cppuhelper/typeprovider.hxx>
22 #include <unotools/tempfile.hxx>
23 #include <osl/file.hxx>
24 #include <unotools/configmgr.hxx>
26 OTempFileService::OTempFileService(::css::uno::Reference< ::css::uno::XComponentContext > const & context)
27 : ::cppu::PropertySetMixin< ::css::io::XTempFile >(
28 context
29 , static_cast< Implements >( IMPLEMENTS_PROPERTY_SET | IMPLEMENTS_FAST_PROPERTY_SET | IMPLEMENTS_PROPERTY_ACCESS )
30 , com::sun::star::uno::Sequence< rtl::OUString >() )
31 , mpStream( NULL )
32 , mbRemoveFile( sal_True )
33 , mbInClosed( sal_False )
34 , mbOutClosed( sal_False )
35 , mnCachedPos( 0 )
36 , mbHasCachedPos( sal_False )
39 mpTempFile = new ::utl::TempFile;
40 mpTempFile->EnableKillingFile ( sal_True );
43 OTempFileService::~OTempFileService ()
45 if ( mpTempFile )
46 delete mpTempFile;
50 // XInterface
52 ::css::uno::Any SAL_CALL OTempFileService::queryInterface( ::css::uno::Type const & aType )
53 throw ( ::css::uno::RuntimeException )
55 ::css::uno::Any aResult( OTempFileBase::queryInterface( aType ) );
56 if (!aResult.hasValue())
57 aResult = cppu::PropertySetMixin< ::css::io::XTempFile >::queryInterface( aType ) ;
58 return aResult;
60 void SAL_CALL OTempFileService::acquire( )
61 throw ()
63 OTempFileBase::acquire();
65 void SAL_CALL OTempFileService::release( )
66 throw ()
68 OTempFileBase::release();
71 // XTypeProvider
73 ::css::uno::Sequence< ::css::uno::Type > SAL_CALL OTempFileService::getTypes( )
74 throw ( ::css::uno::RuntimeException )
76 static ::cppu::OTypeCollection* pTypeCollection = NULL;
77 if ( pTypeCollection == NULL )
79 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ;
81 if ( pTypeCollection == NULL )
83 static ::cppu::OTypeCollection aTypeCollection(
84 ::getCppuType( ( const ::css::uno::Reference< ::css::beans::XPropertySet >*)NULL )
85 ,OTempFileBase::getTypes() );
86 pTypeCollection = &aTypeCollection;
89 return pTypeCollection->getTypes();
91 ::css::uno::Sequence< sal_Int8 > SAL_CALL OTempFileService::getImplementationId( )
92 throw ( ::css::uno::RuntimeException )
94 return OTempFileBase::getImplementationId();
97 // XTempFile
99 sal_Bool SAL_CALL OTempFileService::getRemoveFile()
100 throw ( ::css::uno::RuntimeException )
102 ::osl::MutexGuard aGuard( maMutex );
104 if ( !mpTempFile )
106 // the stream is already disconnected
107 throw ::css::uno::RuntimeException();
110 return mbRemoveFile;
112 void SAL_CALL OTempFileService::setRemoveFile( sal_Bool _removefile )
113 throw ( ::css::uno::RuntimeException )
115 ::osl::MutexGuard aGuard( maMutex );
117 if ( !mpTempFile )
119 // the stream is already disconnected
120 throw ::css::uno::RuntimeException();
123 mbRemoveFile = _removefile;
124 mpTempFile->EnableKillingFile( mbRemoveFile );
126 ::rtl::OUString SAL_CALL OTempFileService::getUri()
127 throw ( ::css::uno::RuntimeException )
129 ::osl::MutexGuard aGuard( maMutex );
131 if ( !mpTempFile )
133 throw ::css::uno::RuntimeException();
136 return ::rtl::OUString( mpTempFile->GetURL() );
139 ::rtl::OUString SAL_CALL OTempFileService::getResourceName()
140 throw ( ::css::uno::RuntimeException )
142 ::osl::MutexGuard aGuard( maMutex );
144 if ( !mpTempFile )
146 throw ::css::uno::RuntimeException();
149 return ::rtl::OUString( mpTempFile->GetFileName() );
154 // XInputStream
156 sal_Int32 SAL_CALL OTempFileService::readBytes( ::css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
157 throw (::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
159 ::osl::MutexGuard aGuard( maMutex );
160 if ( mbInClosed )
161 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
163 checkConnected();
164 if (nBytesToRead < 0)
165 throw ::css::io::BufferSizeExceededException( ::rtl::OUString(), static_cast< ::css::uno::XWeak * >(this));
167 aData.realloc(nBytesToRead);
169 sal_uInt32 nRead = mpStream->Read(static_cast < void* > ( aData.getArray() ), nBytesToRead);
170 checkError();
172 if (nRead < static_cast < sal_uInt32 > ( nBytesToRead ) )
173 aData.realloc( nRead );
175 if ( sal::static_int_cast<sal_uInt32>(nBytesToRead) > nRead )
177 // usually that means that the stream was read till the end
178 // TODO/LATER: it is better to get rid of this optimization by avoiding using of multiple temporary files ( there should be only one temporary file? )
179 mnCachedPos = mpStream->Tell();
180 mbHasCachedPos = sal_True;
182 mpStream = NULL;
183 if ( mpTempFile )
184 mpTempFile->CloseStream();
187 return nRead;
189 sal_Int32 SAL_CALL OTempFileService::readSomeBytes( ::css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
190 throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
192 ::osl::MutexGuard aGuard( maMutex );
193 if ( mbInClosed )
194 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
196 checkConnected();
197 checkError();
199 if (nMaxBytesToRead < 0)
200 throw ::css::io::BufferSizeExceededException( ::rtl::OUString(), static_cast < ::css::uno::XWeak * >( this ) );
202 if (mpStream->IsEof())
204 aData.realloc(0);
205 return 0;
207 else
208 return readBytes(aData, nMaxBytesToRead);
210 void SAL_CALL OTempFileService::skipBytes( sal_Int32 nBytesToSkip )
211 throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
213 ::osl::MutexGuard aGuard( maMutex );
214 if ( mbInClosed )
215 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
217 checkConnected();
218 checkError();
219 mpStream->SeekRel(nBytesToSkip);
220 checkError();
222 sal_Int32 SAL_CALL OTempFileService::available( )
223 throw ( ::css::io::NotConnectedException, ::css::io::IOException, ::css::uno::RuntimeException )
225 ::osl::MutexGuard aGuard( maMutex );
226 if ( mbInClosed )
227 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
229 checkConnected();
231 sal_uInt32 nPos = mpStream->Tell();
232 checkError();
234 mpStream->Seek(STREAM_SEEK_TO_END);
235 checkError();
237 sal_Int32 nAvailable = (sal_Int32)mpStream->Tell() - nPos;
238 mpStream->Seek(nPos);
239 checkError();
241 return nAvailable;
243 void SAL_CALL OTempFileService::closeInput( )
244 throw ( ::css::io::NotConnectedException, ::css::io::IOException, ::css::uno::RuntimeException )
246 ::osl::MutexGuard aGuard( maMutex );
247 if ( mbInClosed )
248 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
250 mbInClosed = sal_True;
252 if ( mbOutClosed )
254 // stream will be deleted by TempFile implementation
255 mpStream = NULL;
257 if ( mpTempFile )
259 delete mpTempFile;
260 mpTempFile = NULL;
265 // XOutputStream
267 void SAL_CALL OTempFileService::writeBytes( const ::css::uno::Sequence< sal_Int8 >& aData )
268 throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
270 ::osl::MutexGuard aGuard( maMutex );
271 if ( mbOutClosed )
272 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
274 checkConnected();
275 sal_uInt32 nWritten = mpStream->Write(aData.getConstArray(),aData.getLength());
276 checkError();
277 if ( nWritten != (sal_uInt32)aData.getLength())
278 throw ::css::io::BufferSizeExceededException( ::rtl::OUString(),static_cast < ::css::uno::XWeak * > ( this ) );
280 void SAL_CALL OTempFileService::flush( )
281 throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
283 ::osl::MutexGuard aGuard( maMutex );
284 if ( mbOutClosed )
285 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
287 checkConnected();
288 mpStream->Flush();
289 checkError();
291 void SAL_CALL OTempFileService::closeOutput( )
292 throw ( ::css::io::NotConnectedException, ::css::io::BufferSizeExceededException, ::css::io::IOException, ::css::uno::RuntimeException )
294 ::osl::MutexGuard aGuard( maMutex );
295 if ( mbOutClosed )
296 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
298 mbOutClosed = sal_True;
300 // TODO/LATER: it is better to get rid of this optimization by avoiding using of multiple temporary files ( there should be only one temporary file? )
301 if ( mpStream )
303 mnCachedPos = mpStream->Tell();
304 mbHasCachedPos = sal_True;
306 mpStream = NULL;
307 if ( mpTempFile )
308 mpTempFile->CloseStream();
311 if ( mbInClosed )
313 // stream will be deleted by TempFile implementation
314 mpStream = NULL;
316 if ( mpTempFile )
318 delete mpTempFile;
319 mpTempFile = NULL;
325 void OTempFileService::checkError () const
327 if (!mpStream || mpStream->SvStream::GetError () != ERRCODE_NONE )
328 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
330 void OTempFileService::checkConnected ()
332 if (!mpStream && mpTempFile)
334 mpStream = mpTempFile->GetStream( STREAM_STD_READWRITE );
335 if ( mpStream && mbHasCachedPos )
337 mpStream->Seek( sal::static_int_cast<sal_Size>(mnCachedPos) );
338 if ( mpStream->SvStream::GetError () == ERRCODE_NONE )
340 mbHasCachedPos = sal_False;
341 mnCachedPos = 0;
343 else
345 mpStream = NULL;
346 mpTempFile->CloseStream();
351 if (!mpStream)
352 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
355 // XSeekable
357 void SAL_CALL OTempFileService::seek( sal_Int64 nLocation )
358 throw ( ::css::lang::IllegalArgumentException, ::css::io::IOException, ::css::uno::RuntimeException )
360 ::osl::MutexGuard aGuard( maMutex );
361 checkConnected();
362 if ( nLocation < 0 || nLocation > getLength() )
363 throw ::css::lang::IllegalArgumentException();
365 mpStream->Seek((sal_uInt32) nLocation );
366 checkError();
368 sal_Int64 SAL_CALL OTempFileService::getPosition( )
369 throw ( ::css::io::IOException, ::css::uno::RuntimeException )
371 ::osl::MutexGuard aGuard( maMutex );
372 checkConnected();
374 sal_uInt32 nPos = mpStream->Tell();
375 checkError();
376 return (sal_Int64)nPos;
378 sal_Int64 SAL_CALL OTempFileService::getLength( )
379 throw ( ::css::io::IOException, ::css::uno::RuntimeException )
381 ::osl::MutexGuard aGuard( maMutex );
382 checkConnected();
384 sal_uInt32 nCurrentPos = mpStream->Tell();
385 checkError();
387 mpStream->Seek(STREAM_SEEK_TO_END);
388 sal_uInt32 nEndPos = mpStream->Tell();
389 mpStream->Seek(nCurrentPos);
391 checkError();
393 return (sal_Int64)nEndPos;
397 // XStream
399 ::css::uno::Reference< ::css::io::XInputStream > SAL_CALL OTempFileService::getInputStream()
400 throw ( ::css::uno::RuntimeException )
402 return ::css::uno::Reference< ::css::io::XInputStream >( *this, ::css::uno::UNO_QUERY );
405 ::css::uno::Reference< ::css::io::XOutputStream > SAL_CALL OTempFileService::getOutputStream()
406 throw ( ::css::uno::RuntimeException )
408 return ::css::uno::Reference< ::css::io::XOutputStream >( *this, ::css::uno::UNO_QUERY );
411 // XTruncate
413 void SAL_CALL OTempFileService::truncate()
414 throw ( ::css::io::IOException, ::css::uno::RuntimeException )
416 ::osl::MutexGuard aGuard( maMutex );
417 checkConnected();
418 // SetStreamSize() call does not change the position
419 mpStream->Seek( 0 );
420 mpStream->SetStreamSize( 0 );
421 checkError();
424 // XServiceInfo
426 ::rtl::OUString SAL_CALL OTempFileService::getImplementationName()
427 throw ( ::css::uno::RuntimeException )
429 return getImplementationName_Static();
432 sal_Bool SAL_CALL OTempFileService::supportsService( ::rtl::OUString const & rServiceName )
433 throw ( ::css::uno::RuntimeException )
435 ::css::uno::Sequence< ::rtl::OUString > aServices(getSupportedServiceNames_Static());
436 return rServiceName == aServices[0];
439 ::css::uno::Sequence < ::rtl::OUString > SAL_CALL OTempFileService::getSupportedServiceNames()
440 throw ( ::css::uno::RuntimeException )
442 return getSupportedServiceNames_Static();
447 ::rtl::OUString OTempFileService::getImplementationName_Static ()
449 return ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.comp.TempFile" ) );
451 ::css::uno::Sequence < ::rtl::OUString > OTempFileService::getSupportedServiceNames_Static()
453 ::css::uno::Sequence < ::rtl::OUString > aNames ( 1 );
454 aNames[0] = ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
455 return aNames;
457 ::css::uno::Reference < ::css::uno::XInterface >SAL_CALL XTempFile_createInstance(
458 css::uno::Reference< ::css::uno::XComponentContext > const & context)
459 SAL_THROW( ( css::uno::Exception ) )
461 return static_cast< ::cppu::OWeakObject * >( new OTempFileService(context) );
464 ::css::uno::Reference < ::css::lang::XSingleComponentFactory > OTempFileService::createServiceFactory_Static()
466 return ::cppu::createSingleComponentFactory( XTempFile_createInstance, getImplementationName_Static(), getSupportedServiceNames_Static() );
470 * This function is called to get service factories for an implementation.
471 * @param pImplName name of implementation
472 * @param pServiceManager generic uno interface providing a service manager to instantiate components
473 * @param pRegistryKey registry data key to read and write component persistent data
474 * @return a component factory (generic uno interface)
476 extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL utl_component_getFactory(
477 const sal_Char * pImplName, void * pServiceManager,
478 SAL_UNUSED_PARAMETER void * /*pRegistryKey*/ )
480 void * pRet = 0;
481 ::css::uno::Reference< ::css::lang::XMultiServiceFactory > xSMgr(
482 reinterpret_cast< ::css::lang::XMultiServiceFactory * >( pServiceManager ) );
483 ::css::uno::Reference< ::css::lang::XSingleComponentFactory > xFactory;
485 if (OTempFileService::getImplementationName_Static().compareToAscii( pImplName ) == 0)
486 xFactory = OTempFileService::createServiceFactory_Static();
488 if ( xFactory.is() )
490 xFactory->acquire();
491 pRet = xFactory.get();
493 return pRet;
496 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */