1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xtempfile.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #include "precompiled_unotools.hxx"
31 #include <XTempFile.hxx>
32 #include <cppuhelper/factory.hxx>
33 #include <cppuhelper/typeprovider.hxx>
34 #ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HPP
35 #include <com/sun/star/registry/XRegistryKey.hpp>
37 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP
38 #include <com/sun/star/beans/PropertyAttribute.hpp>
40 #include <unotools/tempfile.hxx>
41 #include <osl/file.hxx>
42 #include <unotools/configmgr.hxx>
43 #include <tools/urlobj.hxx>
44 #include <tools/debug.hxx>
46 namespace css
= com::sun::star
;
48 // copy define from desktop\source\app\appinit.cxx
50 #define DESKTOP_TEMPNAMEBASE_DIR "/temp/soffice.tmp"
52 OTempFileService::OTempFileService(::css::uno::Reference
< ::css::uno::XComponentContext
> const & context
)
53 : ::cppu::PropertySetMixin
< ::css::io::XTempFile
>(
55 , static_cast< Implements
>( IMPLEMENTS_PROPERTY_SET
| IMPLEMENTS_FAST_PROPERTY_SET
| IMPLEMENTS_PROPERTY_ACCESS
)
56 , com::sun::star::uno::Sequence
< rtl::OUString
>() )
58 , mbRemoveFile( sal_True
)
59 , mbInClosed( sal_False
)
60 , mbOutClosed( sal_False
)
62 , mbHasCachedPos( sal_False
)
65 mpTempFile
= new ::utl::TempFile
;
66 mpTempFile
->EnableKillingFile ( sal_True
);
69 OTempFileService::~OTempFileService ()
78 ::css::uno::Any SAL_CALL
OTempFileService::queryInterface( ::css::uno::Type
const & aType
)
79 throw ( ::css::uno::RuntimeException
)
81 ::css::uno::Any
aResult( OTempFileBase::queryInterface( aType
) );
82 if (!aResult
.hasValue())
83 aResult
= cppu::PropertySetMixin
< ::css::io::XTempFile
>::queryInterface( aType
) ;
86 void SAL_CALL
OTempFileService::acquire( )
89 OTempFileBase::acquire();
91 void SAL_CALL
OTempFileService::release( )
94 OTempFileBase::release();
99 ::css::uno::Sequence
< ::css::uno::Type
> SAL_CALL
OTempFileService::getTypes( )
100 throw ( ::css::uno::RuntimeException
)
102 static ::cppu::OTypeCollection
* pTypeCollection
= NULL
;
103 if ( pTypeCollection
== NULL
)
105 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() ) ;
107 if ( pTypeCollection
== NULL
)
109 static ::cppu::OTypeCollection
aTypeCollection(
110 ::getCppuType( ( const ::css::uno::Reference
< ::css::beans::XPropertySet
>*)NULL
)
111 ,OTempFileBase::getTypes() );
112 pTypeCollection
= &aTypeCollection
;
115 return pTypeCollection
->getTypes();
117 ::css::uno::Sequence
< sal_Int8
> SAL_CALL
OTempFileService::getImplementationId( )
118 throw ( ::css::uno::RuntimeException
)
120 return OTempFileBase::getImplementationId();
125 sal_Bool SAL_CALL
OTempFileService::getRemoveFile()
126 throw ( ::css::uno::RuntimeException
)
128 ::osl::MutexGuard
aGuard( maMutex
);
132 // the stream is already disconnected
133 throw ::css::uno::RuntimeException();
138 void SAL_CALL
OTempFileService::setRemoveFile( sal_Bool _removefile
)
139 throw ( ::css::uno::RuntimeException
)
141 ::osl::MutexGuard
aGuard( maMutex
);
145 // the stream is already disconnected
146 throw ::css::uno::RuntimeException();
149 mbRemoveFile
= _removefile
;
150 mpTempFile
->EnableKillingFile( mbRemoveFile
);
152 ::rtl::OUString SAL_CALL
OTempFileService::getUri()
153 throw ( ::css::uno::RuntimeException
)
155 ::osl::MutexGuard
aGuard( maMutex
);
159 throw ::css::uno::RuntimeException();
162 return ::rtl::OUString( mpTempFile
->GetURL() );
165 ::rtl::OUString SAL_CALL
OTempFileService::getResourceName()
166 throw ( ::css::uno::RuntimeException
)
168 ::osl::MutexGuard
aGuard( maMutex
);
172 throw ::css::uno::RuntimeException();
175 return ::rtl::OUString( mpTempFile
->GetFileName() );
182 sal_Int32 SAL_CALL
OTempFileService::readBytes( ::css::uno::Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
183 throw (::css::io::NotConnectedException
, ::css::io::BufferSizeExceededException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
185 ::osl::MutexGuard
aGuard( maMutex
);
187 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
190 if (nBytesToRead
< 0)
191 throw ::css::io::BufferSizeExceededException( ::rtl::OUString(), static_cast< ::css::uno::XWeak
* >(this));
193 aData
.realloc(nBytesToRead
);
195 sal_uInt32 nRead
= mpStream
->Read(static_cast < void* > ( aData
.getArray() ), nBytesToRead
);
198 if (nRead
< static_cast < sal_uInt32
> ( nBytesToRead
) )
199 aData
.realloc( nRead
);
201 if ( sal::static_int_cast
<sal_uInt32
>(nBytesToRead
) > nRead
)
203 // usually that means that the stream was read till the end
204 // 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? )
205 mnCachedPos
= mpStream
->Tell();
206 mbHasCachedPos
= sal_True
;
210 mpTempFile
->CloseStream();
215 sal_Int32 SAL_CALL
OTempFileService::readSomeBytes( ::css::uno::Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
216 throw ( ::css::io::NotConnectedException
, ::css::io::BufferSizeExceededException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
218 ::osl::MutexGuard
aGuard( maMutex
);
220 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
225 if (nMaxBytesToRead
< 0)
226 throw ::css::io::BufferSizeExceededException( ::rtl::OUString(), static_cast < ::css::uno::XWeak
* >( this ) );
228 if (mpStream
->IsEof())
234 return readBytes(aData
, nMaxBytesToRead
);
236 void SAL_CALL
OTempFileService::skipBytes( sal_Int32 nBytesToSkip
)
237 throw ( ::css::io::NotConnectedException
, ::css::io::BufferSizeExceededException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
239 ::osl::MutexGuard
aGuard( maMutex
);
241 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
245 mpStream
->SeekRel(nBytesToSkip
);
248 sal_Int32 SAL_CALL
OTempFileService::available( )
249 throw ( ::css::io::NotConnectedException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
251 ::osl::MutexGuard
aGuard( maMutex
);
253 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
257 sal_uInt32 nPos
= mpStream
->Tell();
260 mpStream
->Seek(STREAM_SEEK_TO_END
);
263 sal_Int32 nAvailable
= (sal_Int32
)mpStream
->Tell() - nPos
;
264 mpStream
->Seek(nPos
);
269 void SAL_CALL
OTempFileService::closeInput( )
270 throw ( ::css::io::NotConnectedException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
272 ::osl::MutexGuard
aGuard( maMutex
);
274 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
276 mbInClosed
= sal_True
;
280 // stream will be deleted by TempFile implementation
293 void SAL_CALL
OTempFileService::writeBytes( const ::css::uno::Sequence
< sal_Int8
>& aData
)
294 throw ( ::css::io::NotConnectedException
, ::css::io::BufferSizeExceededException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
296 ::osl::MutexGuard
aGuard( maMutex
);
298 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
301 sal_uInt32 nWritten
= mpStream
->Write(aData
.getConstArray(),aData
.getLength());
303 if ( nWritten
!= (sal_uInt32
)aData
.getLength())
304 throw ::css::io::BufferSizeExceededException( ::rtl::OUString(),static_cast < ::css::uno::XWeak
* > ( this ) );
306 void SAL_CALL
OTempFileService::flush( )
307 throw ( ::css::io::NotConnectedException
, ::css::io::BufferSizeExceededException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
309 ::osl::MutexGuard
aGuard( maMutex
);
311 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
317 void SAL_CALL
OTempFileService::closeOutput( )
318 throw ( ::css::io::NotConnectedException
, ::css::io::BufferSizeExceededException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
320 ::osl::MutexGuard
aGuard( maMutex
);
322 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
324 mbOutClosed
= sal_True
;
326 // 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? )
329 mnCachedPos
= mpStream
->Tell();
330 mbHasCachedPos
= sal_True
;
334 mpTempFile
->CloseStream();
339 // stream will be deleted by TempFile implementation
351 void OTempFileService::checkError () const
353 if (!mpStream
|| mpStream
->SvStream::GetError () != ERRCODE_NONE
)
354 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
356 void OTempFileService::checkConnected ()
358 if (!mpStream
&& mpTempFile
)
360 mpStream
= mpTempFile
->GetStream( STREAM_STD_READWRITE
);
361 if ( mpStream
&& mbHasCachedPos
)
363 mpStream
->Seek( sal::static_int_cast
<sal_Size
>(mnCachedPos
) );
364 if ( mpStream
->SvStream::GetError () == ERRCODE_NONE
)
366 mbHasCachedPos
= sal_False
;
372 mpTempFile
->CloseStream();
378 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak
* > ( static_cast < const ::css::uno::XWeak
* > (this ) ) );
383 void SAL_CALL
OTempFileService::seek( sal_Int64 nLocation
)
384 throw ( ::css::lang::IllegalArgumentException
, ::css::io::IOException
, ::css::uno::RuntimeException
)
386 ::osl::MutexGuard
aGuard( maMutex
);
388 if ( nLocation
< 0 || nLocation
> getLength() )
389 throw ::css::lang::IllegalArgumentException();
391 mpStream
->Seek((sal_uInt32
) nLocation
);
394 sal_Int64 SAL_CALL
OTempFileService::getPosition( )
395 throw ( ::css::io::IOException
, ::css::uno::RuntimeException
)
397 ::osl::MutexGuard
aGuard( maMutex
);
400 sal_uInt32 nPos
= mpStream
->Tell();
402 return (sal_Int64
)nPos
;
404 sal_Int64 SAL_CALL
OTempFileService::getLength( )
405 throw ( ::css::io::IOException
, ::css::uno::RuntimeException
)
407 ::osl::MutexGuard
aGuard( maMutex
);
410 sal_uInt32 nCurrentPos
= mpStream
->Tell();
413 mpStream
->Seek(STREAM_SEEK_TO_END
);
414 sal_uInt32 nEndPos
= mpStream
->Tell();
415 mpStream
->Seek(nCurrentPos
);
419 return (sal_Int64
)nEndPos
;
425 ::css::uno::Reference
< ::css::io::XInputStream
> SAL_CALL
OTempFileService::getInputStream()
426 throw ( ::css::uno::RuntimeException
)
428 return ::css::uno::Reference
< ::css::io::XInputStream
>( *this, ::css::uno::UNO_QUERY
);
431 ::css::uno::Reference
< ::css::io::XOutputStream
> SAL_CALL
OTempFileService::getOutputStream()
432 throw ( ::css::uno::RuntimeException
)
434 return ::css::uno::Reference
< ::css::io::XOutputStream
>( *this, ::css::uno::UNO_QUERY
);
439 void SAL_CALL
OTempFileService::truncate()
440 throw ( ::css::io::IOException
, ::css::uno::RuntimeException
)
442 ::osl::MutexGuard
aGuard( maMutex
);
444 // SetStreamSize() call does not change the position
446 mpStream
->SetStreamSize( 0 );
452 ::rtl::OUString SAL_CALL
OTempFileService::getImplementationName()
453 throw ( ::css::uno::RuntimeException
)
455 return getImplementationName_Static();
458 sal_Bool SAL_CALL
OTempFileService::supportsService( ::rtl::OUString
const & rServiceName
)
459 throw ( ::css::uno::RuntimeException
)
461 ::css::uno::Sequence
< ::rtl::OUString
> aServices(getSupportedServiceNames_Static());
462 return rServiceName
== aServices
[0];
465 ::css::uno::Sequence
< ::rtl::OUString
> SAL_CALL
OTempFileService::getSupportedServiceNames()
466 throw ( ::css::uno::RuntimeException
)
468 return getSupportedServiceNames_Static();
473 ::rtl::OUString
OTempFileService::getImplementationName_Static ()
475 return ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.comp.TempFile" ) );
477 ::css::uno::Sequence
< ::rtl::OUString
> OTempFileService::getSupportedServiceNames_Static()
479 ::css::uno::Sequence
< ::rtl::OUString
> aNames ( 1 );
480 aNames
[0] = ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
483 ::css::uno::Reference
< ::css::uno::XInterface
>SAL_CALL
XTempFile_createInstance(
484 css::uno::Reference
< ::css::uno::XComponentContext
> const & context
)
485 SAL_THROW( ( css::uno::Exception
) )
487 return static_cast< ::cppu::OWeakObject
* >( new OTempFileService(context
) );
490 ::css::uno::Reference
< ::css::lang::XSingleComponentFactory
> OTempFileService::createServiceFactory_Static( ::css::uno::Reference
< ::css::lang::XMultiServiceFactory
> const & )
492 return ::cppu::createSingleComponentFactory( XTempFile_createInstance
, getImplementationName_Static(), getSupportedServiceNames_Static() );
495 static sal_Bool
writeInfo( void * pRegistryKey
,
496 const ::rtl::OUString
& rImplementationName
,
497 ::css::uno::Sequence
< ::rtl::OUString
> const & rServiceNames
)
499 ::rtl::OUString
aKeyName( RTL_CONSTASCII_USTRINGPARAM ( "/" ) );
500 aKeyName
+= rImplementationName
;
501 aKeyName
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "/UNO/SERVICES" ) );
503 ::css::uno::Reference
< ::css::registry::XRegistryKey
> xKey
;
506 xKey
= static_cast< ::css::registry::XRegistryKey
* >(
507 pRegistryKey
)->createKey( aKeyName
);
509 catch ( ::css::registry::InvalidRegistryException
const & )
516 sal_Bool bSuccess
= sal_True
;
518 for ( sal_Int32 n
= 0; n
< rServiceNames
.getLength(); ++n
)
522 xKey
->createKey( rServiceNames
[ n
] );
524 catch ( ::css::registry::InvalidRegistryException
const & )
526 bSuccess
= sal_False
;
532 // C functions to implement this as a component
534 extern "C" SAL_DLLPUBLIC_EXPORT
void SAL_CALL
component_getImplementationEnvironment(
535 const sal_Char
** ppEnvTypeName
, uno_Environment
** /*ppEnv*/ )
537 *ppEnvTypeName
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
541 * This function creates an implementation section in the registry and another subkey
542 * for each supported service.
543 * @param pServiceManager generic uno interface providing a service manager
544 * @param pRegistryKey generic uno interface providing registry key to write
546 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL
component_writeInfo( void* /*pServiceManager*/, void* pRegistryKey
)
548 return pRegistryKey
&&
549 writeInfo (pRegistryKey
,
550 OTempFileService::getImplementationName_Static(),
551 OTempFileService::getSupportedServiceNames_Static() );
556 * This function is called to get service factories for an implementation.
557 * @param pImplName name of implementation
558 * @param pServiceManager generic uno interface providing a service manager to instantiate components
559 * @param pRegistryKey registry data key to read and write component persistent data
560 * @return a component factory (generic uno interface)
562 extern "C" SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
component_getFactory(
563 const sal_Char
* pImplName
, void * pServiceManager
, void * /*pRegistryKey*/ )
566 ::css::uno::Reference
< ::css::lang::XMultiServiceFactory
> xSMgr(
567 reinterpret_cast< ::css::lang::XMultiServiceFactory
* >( pServiceManager
) );
568 ::css::uno::Reference
< ::css::lang::XSingleComponentFactory
> xFactory
;
570 if (OTempFileService::getImplementationName_Static().compareToAscii( pImplName
) == 0)
571 xFactory
= OTempFileService::createServiceFactory_Static ( xSMgr
);
576 pRet
= xFactory
.get();