1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
>(
29 , static_cast< Implements
>( IMPLEMENTS_PROPERTY_SET
| IMPLEMENTS_FAST_PROPERTY_SET
| IMPLEMENTS_PROPERTY_ACCESS
)
30 , com::sun::star::uno::Sequence
< rtl::OUString
>() )
32 , mbRemoveFile( sal_True
)
33 , mbInClosed( sal_False
)
34 , mbOutClosed( sal_False
)
36 , mbHasCachedPos( sal_False
)
39 mpTempFile
= new ::utl::TempFile
;
40 mpTempFile
->EnableKillingFile ( sal_True
);
43 OTempFileService::~OTempFileService ()
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
) ;
60 void SAL_CALL
OTempFileService::acquire( )
63 OTempFileBase::acquire();
65 void SAL_CALL
OTempFileService::release( )
68 OTempFileBase::release();
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();
99 sal_Bool SAL_CALL
OTempFileService::getRemoveFile()
100 throw ( ::css::uno::RuntimeException
)
102 ::osl::MutexGuard
aGuard( maMutex
);
106 // the stream is already disconnected
107 throw ::css::uno::RuntimeException();
112 void SAL_CALL
OTempFileService::setRemoveFile( sal_Bool _removefile
)
113 throw ( ::css::uno::RuntimeException
)
115 ::osl::MutexGuard
aGuard( maMutex
);
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
);
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
);
146 throw ::css::uno::RuntimeException();
149 return ::rtl::OUString( mpTempFile
->GetFileName() );
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
);
161 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
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
);
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
;
184 mpTempFile
->CloseStream();
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
);
194 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
199 if (nMaxBytesToRead
< 0)
200 throw ::css::io::BufferSizeExceededException( ::rtl::OUString(), static_cast < ::css::uno::XWeak
* >( this ) );
202 if (mpStream
->IsEof())
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
);
215 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
219 mpStream
->SeekRel(nBytesToSkip
);
222 sal_Int32 SAL_CALL
OTempFileService::available( )
223 throw ( ::css::io::NotConnectedException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
225 ::osl::MutexGuard
aGuard( maMutex
);
227 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
231 sal_uInt32 nPos
= mpStream
->Tell();
234 mpStream
->Seek(STREAM_SEEK_TO_END
);
237 sal_Int32 nAvailable
= (sal_Int32
)mpStream
->Tell() - nPos
;
238 mpStream
->Seek(nPos
);
243 void SAL_CALL
OTempFileService::closeInput( )
244 throw ( ::css::io::NotConnectedException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
246 ::osl::MutexGuard
aGuard( maMutex
);
248 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
250 mbInClosed
= sal_True
;
254 // stream will be deleted by TempFile implementation
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
);
272 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
275 sal_uInt32 nWritten
= mpStream
->Write(aData
.getConstArray(),aData
.getLength());
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
);
285 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
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
);
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? )
303 mnCachedPos
= mpStream
->Tell();
304 mbHasCachedPos
= sal_True
;
308 mpTempFile
->CloseStream();
313 // stream will be deleted by TempFile implementation
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
;
346 mpTempFile
->CloseStream();
352 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
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
);
362 if ( nLocation
< 0 || nLocation
> getLength() )
363 throw ::css::lang::IllegalArgumentException();
365 mpStream
->Seek((sal_uInt32
) nLocation
);
368 sal_Int64 SAL_CALL
OTempFileService::getPosition( )
369 throw ( ::css::io::IOException
, ::css::uno::RuntimeException
)
371 ::osl::MutexGuard
aGuard( maMutex
);
374 sal_uInt32 nPos
= mpStream
->Tell();
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
);
384 sal_uInt32 nCurrentPos
= mpStream
->Tell();
387 mpStream
->Seek(STREAM_SEEK_TO_END
);
388 sal_uInt32 nEndPos
= mpStream
->Tell();
389 mpStream
->Seek(nCurrentPos
);
393 return (sal_Int64
)nEndPos
;
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
);
413 void SAL_CALL
OTempFileService::truncate()
414 throw ( ::css::io::IOException
, ::css::uno::RuntimeException
)
416 ::osl::MutexGuard
aGuard( maMutex
);
418 // SetStreamSize() call does not change the position
420 mpStream
->SetStreamSize( 0 );
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" ) );
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*/ )
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();
491 pRet
= xFactory
.get();
496 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */