merge the formfield patch from ooo-build
[ooovba.git] / unotools / source / ucbhelper / xtempfile.cxx
blob9b9ba49e7bd94570cc4bd3184b19cddfc0d2630d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xtempfile.cxx,v $
10 * $Revision: 1.16 $
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>
36 #endif
37 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP
38 #include <com/sun/star/beans/PropertyAttribute.hpp>
39 #endif
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 >(
54 context
55 , static_cast< Implements >( IMPLEMENTS_PROPERTY_SET | IMPLEMENTS_FAST_PROPERTY_SET | IMPLEMENTS_PROPERTY_ACCESS )
56 , com::sun::star::uno::Sequence< rtl::OUString >() )
57 , mpStream( NULL )
58 , mbRemoveFile( sal_True )
59 , mbInClosed( sal_False )
60 , mbOutClosed( sal_False )
61 , mnCachedPos( 0 )
62 , mbHasCachedPos( sal_False )
65 mpTempFile = new ::utl::TempFile;
66 mpTempFile->EnableKillingFile ( sal_True );
69 OTempFileService::~OTempFileService ()
71 if ( mpTempFile )
72 delete mpTempFile;
76 // XInterface
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 ) ;
84 return aResult;
86 void SAL_CALL OTempFileService::acquire( )
87 throw ()
89 OTempFileBase::acquire();
91 void SAL_CALL OTempFileService::release( )
92 throw ()
94 OTempFileBase::release();
97 // XTypeProvider
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();
123 // XTempFile
125 sal_Bool SAL_CALL OTempFileService::getRemoveFile()
126 throw ( ::css::uno::RuntimeException )
128 ::osl::MutexGuard aGuard( maMutex );
130 if ( !mpTempFile )
132 // the stream is already disconnected
133 throw ::css::uno::RuntimeException();
136 return mbRemoveFile;
138 void SAL_CALL OTempFileService::setRemoveFile( sal_Bool _removefile )
139 throw ( ::css::uno::RuntimeException )
141 ::osl::MutexGuard aGuard( maMutex );
143 if ( !mpTempFile )
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 );
157 if ( !mpTempFile )
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 );
170 if ( !mpTempFile )
172 throw ::css::uno::RuntimeException();
175 return ::rtl::OUString( mpTempFile->GetFileName() );
180 // XInputStream
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 );
186 if ( mbInClosed )
187 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
189 checkConnected();
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);
196 checkError();
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;
208 mpStream = NULL;
209 if ( mpTempFile )
210 mpTempFile->CloseStream();
213 return nRead;
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 );
219 if ( mbInClosed )
220 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
222 checkConnected();
223 checkError();
225 if (nMaxBytesToRead < 0)
226 throw ::css::io::BufferSizeExceededException( ::rtl::OUString(), static_cast < ::css::uno::XWeak * >( this ) );
228 if (mpStream->IsEof())
230 aData.realloc(0);
231 return 0;
233 else
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 );
240 if ( mbInClosed )
241 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
243 checkConnected();
244 checkError();
245 mpStream->SeekRel(nBytesToSkip);
246 checkError();
248 sal_Int32 SAL_CALL OTempFileService::available( )
249 throw ( ::css::io::NotConnectedException, ::css::io::IOException, ::css::uno::RuntimeException )
251 ::osl::MutexGuard aGuard( maMutex );
252 if ( mbInClosed )
253 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
255 checkConnected();
257 sal_uInt32 nPos = mpStream->Tell();
258 checkError();
260 mpStream->Seek(STREAM_SEEK_TO_END);
261 checkError();
263 sal_Int32 nAvailable = (sal_Int32)mpStream->Tell() - nPos;
264 mpStream->Seek(nPos);
265 checkError();
267 return nAvailable;
269 void SAL_CALL OTempFileService::closeInput( )
270 throw ( ::css::io::NotConnectedException, ::css::io::IOException, ::css::uno::RuntimeException )
272 ::osl::MutexGuard aGuard( maMutex );
273 if ( mbInClosed )
274 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
276 mbInClosed = sal_True;
278 if ( mbOutClosed )
280 // stream will be deleted by TempFile implementation
281 mpStream = NULL;
283 if ( mpTempFile )
285 delete mpTempFile;
286 mpTempFile = NULL;
291 // XOutputStream
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 );
297 if ( mbOutClosed )
298 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
300 checkConnected();
301 sal_uInt32 nWritten = mpStream->Write(aData.getConstArray(),aData.getLength());
302 checkError();
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 );
310 if ( mbOutClosed )
311 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
313 checkConnected();
314 mpStream->Flush();
315 checkError();
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 );
321 if ( mbOutClosed )
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? )
327 if ( mpStream )
329 mnCachedPos = mpStream->Tell();
330 mbHasCachedPos = sal_True;
332 mpStream = NULL;
333 if ( mpTempFile )
334 mpTempFile->CloseStream();
337 if ( mbInClosed )
339 // stream will be deleted by TempFile implementation
340 mpStream = NULL;
342 if ( mpTempFile )
344 delete mpTempFile;
345 mpTempFile = NULL;
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;
367 mnCachedPos = 0;
369 else
371 mpStream = NULL;
372 mpTempFile->CloseStream();
377 if (!mpStream)
378 throw ::css::io::NotConnectedException ( ::rtl::OUString(), const_cast < ::css::uno::XWeak * > ( static_cast < const ::css::uno::XWeak * > (this ) ) );
381 // XSeekable
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 );
387 checkConnected();
388 if ( nLocation < 0 || nLocation > getLength() )
389 throw ::css::lang::IllegalArgumentException();
391 mpStream->Seek((sal_uInt32) nLocation );
392 checkError();
394 sal_Int64 SAL_CALL OTempFileService::getPosition( )
395 throw ( ::css::io::IOException, ::css::uno::RuntimeException )
397 ::osl::MutexGuard aGuard( maMutex );
398 checkConnected();
400 sal_uInt32 nPos = mpStream->Tell();
401 checkError();
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 );
408 checkConnected();
410 sal_uInt32 nCurrentPos = mpStream->Tell();
411 checkError();
413 mpStream->Seek(STREAM_SEEK_TO_END);
414 sal_uInt32 nEndPos = mpStream->Tell();
415 mpStream->Seek(nCurrentPos);
417 checkError();
419 return (sal_Int64)nEndPos;
423 // XStream
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 );
437 // XTruncate
439 void SAL_CALL OTempFileService::truncate()
440 throw ( ::css::io::IOException, ::css::uno::RuntimeException )
442 ::osl::MutexGuard aGuard( maMutex );
443 checkConnected();
444 // SetStreamSize() call does not change the position
445 mpStream->Seek( 0 );
446 mpStream->SetStreamSize( 0 );
447 checkError();
450 // XServiceInfo
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" ) );
481 return aNames;
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 & )
513 if ( !xKey.is() )
514 return sal_False;
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;
527 break;
530 return bSuccess;
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*/ )
565 void * pRet = 0;
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 );
573 if ( xFactory.is() )
575 xFactory->acquire();
576 pRet = xFactory.get();
578 return pRet;