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: LDriver.cxx,v $
10 * $Revision: 1.10.42.1 $
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 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
33 #include "LDriver.hxx"
34 #include "LConnection.hxx"
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include "connectivity/dbexception.hxx"
37 #include "LConfigAccess.hxx"
38 #include <osl/file.hxx>
39 #include "osl/security.hxx"
40 #include <comphelper/processfactory.hxx>
41 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
42 #include <ucbhelper/content.hxx>
43 #include <tools/debug.hxx>
44 #include "resource/common_res.hrc"
45 #include "resource/sharedresources.hxx"
49 using namespace connectivity::evoab
;
50 using namespace connectivity::file
;
51 using namespace ::com::sun::star::uno
;
52 using namespace ::com::sun::star::beans
;
53 using namespace ::com::sun::star::sdbcx
;
54 using namespace ::com::sun::star::sdbc
;
55 using namespace ::com::sun::star::lang
;
56 using namespace ::com::sun::star::ucb
;
58 // --------------------------------------------------------------------------------
59 OEvoabDriver::OEvoabDriver(const Reference
< XMultiServiceFactory
>& _rxFactory
) : OFileDriver(_rxFactory
)
60 ,m_aTempDir(NULL
, sal_True
)
61 ,m_aFolderListName(::rtl::OUString::createFromAscii(getEVOAB_FOLDERLIST_FILE_NAME()))
62 ,m_aVersionName(::rtl::OUString::createFromAscii(getEVOAB_VERSION_FILE_NAME()))
63 ,m_aFileExt(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(getEVOAB_META_FILE_EXT())))
64 ,m_bWorkingDirCreated(sal_False
)
65 ,m_eSupportedEvoVersion( eUnknown
)
67 m_aEvoab_CLI_FullPathCommand
= getFullPathExportingCommand(_rxFactory
);
69 if ( m_aEvoab_CLI_FullPathCommand
.getLength() == 0 )
70 m_aEvoab_CLI_FullPathCommand
= ::rtl::OUString::createFromAscii(getEVOAB_CLI_FULLPATHCOMMAND());
71 if ( m_aEvoab_CLI_FullPathCommand
.copy(0,7) != ::rtl::OUString::createFromAscii("file://") && m_aEvoab_CLI_FullPathCommand
.copy(0,1) == ::rtl::OUString::createFromAscii("/"))
72 m_aEvoab_CLI_FullPathCommand
= ::rtl::OUString::createFromAscii("file://") + m_aEvoab_CLI_FullPathCommand
;
73 m_aEvoab_CLI_EffectiveCommand
= m_aEvoab_CLI_FullPathCommand
;
74 m_aTempDir
.EnableKillingFile();
76 EVO_TRACE_STRING("OEvoabDriver::OEvoabDriver()::m_aEvoab_CLI_FullPathCommand = %s", m_aEvoab_CLI_FullPathCommand
);
79 //------------------------------------------------------------------------------
80 rtl::OUString
OEvoabDriver::getImplementationName_Static( ) throw(RuntimeException
)
82 return rtl::OUString::createFromAscii(EVOAB_DRIVER_IMPL_NAME
);
85 //------------------------------------------------------------------
86 ::rtl::OUString SAL_CALL
OEvoabDriver::getImplementationName( ) throw(RuntimeException
)
88 return getImplementationName_Static();
91 //------------------------------------------------------------------
92 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> SAL_CALL
connectivity::evoab::OEvoabDriver_CreateInstance(const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
>& _rxFactory
) throw( ::com::sun::star::uno::Exception
)
94 return *(new OEvoabDriver(_rxFactory
));
96 // --------------------------------------------------------------------------------
97 Reference
< XConnection
> SAL_CALL
OEvoabDriver::connect( const ::rtl::OUString
& url
, const Sequence
< PropertyValue
>& info
) throw(SQLException
, RuntimeException
)
99 ::osl::MutexGuard
aGuard( m_aMutex
);
100 if (ODriver_BASE::rBHelper
.bDisposed
)
101 throw DisposedException();
103 if ( ! acceptsURL(url
) )
106 OEvoabConnection
* pCon
= new OEvoabConnection(this);
107 pCon
->construct(url
,info
);
108 Reference
< XConnection
> xCon
= pCon
;
109 m_xConnections
.push_back(WeakReferenceHelper(*pCon
));
113 // --------------------------------------------------------------------------------
116 ::rtl::OUString
lcl_translateProcessErrorMessage( oslProcessError nProcErr
)
118 ::rtl::OUString sProcErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" not executed!."));
121 case osl_Process_E_None
:
122 sProcErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed sucessful!"));
124 case osl_Process_E_NotFound
:
125 sProcErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: not found!"));
127 case osl_Process_E_NoPermission
:
128 sProcErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: has no permission!"));
130 case osl_Process_E_TimedOut
:
131 sProcErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: time out!"));
133 case osl_Process_E_Unknown
:
134 sProcErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: unkown reason!"));
136 case osl_Process_E_InvalidError
:
137 sProcErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: invalid error!"));
140 sProcErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: other reason!"));
144 oslProcessError
lcl_execute( const ::rtl::OUString
& _rCommand
, ::rtl::OUString
& _rArgument
,
145 const ::rtl::OUString
& _rWorkingDir
, oslProcessOption _nOptions
, oslFileHandle
& /*[out]*/ _hStdOut
)
147 oslProcessError nError
= osl_Process_E_None
;
149 EVO_TRACE_STRING("LDriver.cxx::lcl_execute: command : %s", _rCommand
);
150 EVO_TRACE_STRING("LDriver.cxx::lcl_execute: argument : %s", _rArgument
);
151 EVO_TRACE_STRING("LDriver.cxx::lcl_execute: working dir: %s", _rWorkingDir
);
153 oslProcess
hProcess( 0 );
155 nError
= osl_executeProcess_WithRedirectedIO(
169 ::rtl::OUString sError
= _rCommand
+ lcl_translateProcessErrorMessage( nError
);
170 EVO_TRACE_STRING( "%s", sError
);
172 if ( nError
== osl_Process_E_None
)
174 TimeValue aFiveSeconds
;
175 aFiveSeconds
.Seconds
= 5;
176 aFiveSeconds
.Nanosec
= 0;
177 oslProcessError nWaitForProcessError
= osl_joinProcessWithTimeout( hProcess
, &aFiveSeconds
);
178 if ( osl_Process_E_None
!= nWaitForProcessError
)
180 nError
= nWaitForProcessError
;
181 // TODO: kill the running process?
183 osl_freeProcessHandle( hProcess
);
189 // --------------------------------------------------------------------------------
190 sal_Bool SAL_CALL
OEvoabDriver::acceptsURL( const ::rtl::OUString
& url
)
191 throw(SQLException
, RuntimeException
)
195 // here we have to look if we support this url format
196 if(acceptsURL_Stat(url
))
198 if ( m_eSupportedEvoVersion
!= eUnknown
)
199 return m_eSupportedEvoVersion
== eTrue
? sal_True
: sal_False
;
201 if(!m_bWorkingDirCreated
)
203 String sTempDirURL
= getTempDirURL();
204 //EVO_TRACE_STRING("OEvoabDriver::acceptsURL()::sTempDirURL = %s", sTempDirURL );
206 ::rtl::OUString
aTempDirURL(sTempDirURL
);
207 m_aWorkingDirURL
= aTempDirURL
;
208 m_bWorkingDirCreated
= sal_True
;
211 ::rtl::OUString aCLICommand
= getEvoab_CLI_EffectiveCommand();
212 ::rtl::OUString aWorkingDirURL
= getWorkingDirURL();
213 ::rtl::OUString aArgVersion
= ::rtl::OUString::createFromAscii(getEVOAB_CLI_ARG_VERSION());
215 oslFileHandle hStdout
= NULL
;
216 oslProcessError nProcErr
= lcl_execute( aCLICommand
, aArgVersion
, aWorkingDirURL
, 0, hStdout
);
217 if(nProcErr
!= osl_Process_E_None
)
219 if(doesEvoab_CLI_HavePath())
220 aCLICommand
= getEvoab_CLI_Command();
222 aCLICommand
= getEvoab_CLI_Path() + getEvoab_CLI_Command();
223 nProcErr
= lcl_execute( aCLICommand
, aArgVersion
, aWorkingDirURL
, osl_Process_SEARCHPATH
| osl_Process_HIDDEN
, hStdout
);
224 if ( nProcErr
== osl_Process_E_None
)
225 m_aEvoab_CLI_EffectiveCommand
= aCLICommand
;
228 if ( hStdout
!= NULL
)
230 OSL_ASSERT( hStdout
);
231 sal_Char pBuffer
[256];
232 sal_uInt64 nBytesRead
;
233 oslFileError nFileErr
= osl_File_E_None
;
234 nFileErr
= osl_readFile( hStdout
, pBuffer
, 256, &nBytesRead
);
235 if ( nFileErr
!= osl_File_E_None
)
237 ::rtl::OUString sErr
= translateFileErrorMessage( nFileErr
);
238 OSL_ENSURE(false, ::rtl::OUStringToOString( sErr
, RTL_TEXTENCODING_ASCII_US
).getStr());
240 ::rtl::OUString aVersionInfo
;
241 if ( nFileErr
== osl_File_E_None
&& nBytesRead
> 0 && nBytesRead
<= 256)
243 OSL_TRACE("OEvoabDriver::acceptsURL()::osl_readFile(),nBytesRead = %u",nBytesRead
);
245 ::rtl::OUString( ( const sal_Char
* )pBuffer
,
246 (sal_Int32
)nBytesRead
,
247 RTL_TEXTENCODING_UTF8
);
248 EVO_TRACE_STRING("OEvoabDriver::acceptsURL()::aVersionInfo = %s", aVersionInfo
);
249 sal_Int32 nIndex
= 0;
250 sal_Bool bNumRetrieved
= sal_False
;
251 ::rtl::OUString aToken
;
254 for ( i
= 0; i
< 4; i
++ )
258 aToken
= aVersionInfo
.getToken( 0, ' ', nIndex
);
259 //OSL_TRACE("OEvoabDriver::acceptsURL()::Token:%d", nIndex );
260 //EVO_TRACE_STRING("OEvoabDriver::acceptsURL()::aToken = %s", aToken );
261 if( aToken
.toChar() >= '0' && aToken
.toChar() <= '9' )
263 bNumRetrieved
= sal_True
;
264 sal_Int32 nIndex1
= 0;
265 ::rtl::OUString aNum
;
266 for(i
= 0; i
< 4 ; i
++)
270 aNum
= aToken
.getToken( 0, '.', nIndex1
);
271 aVer
[i
] = aNum
.toInt32();
272 OSL_TRACE("OEvoabDriver::acceptsURL()::Ver[%u]=%u", i
, aVer
[i
] );
277 while ( nIndex
>= 0 && !bNumRetrieved
);
279 if((aVer
[0]>1)||(aVer
[0]==1 && aVer
[1]>3)||(aVer
[0]==1 && aVer
[1]==3 && aVer
[2]>2)||(aVer
[0]==1 && aVer
[1]==3 && aVer
[2]==2 && aVer
[3]>=99))
287 osl_closeFile( hStdout
);
289 m_eSupportedEvoVersion
= bRet
? eTrue
: eFalse
;
291 EVO_TRACE_STRING("OEvoabDriver::acceptsURL()::return, return value = %s", ::rtl::OUString::valueOf(bRet
) );
296 // --------------------------------------------------------------------------------
297 sal_Bool
OEvoabDriver::acceptsURL_Stat( const ::rtl::OUString
& url
)
300 EVO_TRACE_STRING("OEvoabDriver::acceptsURL_Stat()::Scheme = %s", url
);
301 // Skip 'sdbc:address: part of URL
303 sal_Int32 nLen
= url
.indexOf(':');
304 nLen
= url
.indexOf(':',nLen
+1);
305 ::rtl::OUString
aAddrbookURI(url
.copy(nLen
+1));
308 nLen
= aAddrbookURI
.indexOf(':');
309 ::rtl::OUString aAddrbookScheme
;
312 // There isn't any subschema: - but could be just subschema
313 if ( aAddrbookURI
.getLength() > 0 )
314 aAddrbookScheme
= aAddrbookURI
;
315 else if(url
== ::rtl::OUString::createFromAscii("sdbc:address:") )
316 return sal_True
; // special case here
321 aAddrbookScheme
= aAddrbookURI
.copy(0, nLen
);
324 EVO_TRACE_STRING("OEvoabDriver::acceptsURL_Stat()::URI = %s", aAddrbookURI
);
325 EVO_TRACE_STRING("OEvoabDriver::acceptsURL_Stat()::Scheme = %s", aAddrbookScheme
);
327 return aAddrbookScheme
.compareToAscii( getSDBC_SCHEME_EVOLUTION() ) == 0 ;
329 // -------------------------------------------------------------------------
330 const rtl::OUString
OEvoabDriver::getEvoab_CLI_Command() const
332 rtl::OUString aEvoab_CLI_Command
;
333 sal_Int32 nLen
= m_aEvoab_CLI_FullPathCommand
.lastIndexOf('/');
336 aEvoab_CLI_Command
= m_aEvoab_CLI_FullPathCommand
;
338 aEvoab_CLI_Command
= m_aEvoab_CLI_FullPathCommand
.copy(nLen
+1);
340 EVO_TRACE_STRING( "OEvoabDriver::getEvoab_CLI_Command()::aEvoab_CLI_Command = %s", aEvoab_CLI_Command
);
342 return aEvoab_CLI_Command
;
344 // -------------------------------------------------------------------------
345 const rtl::OUString
OEvoabDriver::getEvoab_CLI_Path() const
347 rtl::OUString aEvoab_CLI_Path
;
348 sal_Int32 nLen
= m_aEvoab_CLI_FullPathCommand
.lastIndexOf('/');
352 rtl::OUString aDefault_CLI_FullPathCommand
;
353 aDefault_CLI_FullPathCommand
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(OEvoabDriver::getEVOAB_CLI_FULLPATHCOMMAND()));
354 sal_Int32 nLength
= aDefault_CLI_FullPathCommand
.lastIndexOf('/');
355 aEvoab_CLI_Path
= aDefault_CLI_FullPathCommand
.copy(0, nLength
+1);
358 aEvoab_CLI_Path
= m_aEvoab_CLI_FullPathCommand
.copy(0, nLen
+1);
359 EVO_TRACE_STRING( "OEvoabDriver::getEvoab_CLI_Path()::aEvoab_CLI_Path = %s", aEvoab_CLI_Path
);
361 return aEvoab_CLI_Path
;
363 // -------------------------------------------------------------------------
364 const rtl::OUString
OEvoabDriver::getWorkingDirPath() const
366 ::rtl::OUString aWorkingDirPath
;
367 if(m_bWorkingDirCreated
)
368 osl::File::getSystemPathFromFileURL( m_aWorkingDirURL
, aWorkingDirPath
);
369 return aWorkingDirPath
;
371 // -------------------------------------------------------------------------
372 const String
OEvoabDriver::getEvoFolderListFileURL() const
375 ::rtl::OUString aEvoFolderListFileURL
;
376 aEvoFolderListFileURL
= getWorkingDirURL() + getEvoFolderListFileName();
378 EVO_TRACE_STRING("OEvoabDriver::getEvoFolderListFileURL(): aEvoFolderListFileURL = %s", aEvoFolderListFileURL
);
379 return aEvoFolderListFileURL
.getStr();
382 // -------------------------------------------------------------------------
383 String
OEvoabDriver::getTempDirURL() const
385 ::rtl::OUString aTempDirURL
;
386 aTempDirURL
= m_aTempDir
.GetURL();
387 if((aTempDirURL
.lastIndexOf( '/')) != (aTempDirURL
.getLength( ) - 1))
388 aTempDirURL
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
390 EVO_TRACE_STRING("OEvoabDriver::getTempDirURL(): aTempDirURL = %s", aTempDirURL
);
391 return aTempDirURL
.getStr();
393 //-------------------------------------------------------------------------
394 sal_Bool
OEvoabDriver::fileExists(const ::rtl::OUString
& _rURL
, sal_Bool _bIsDir
) const
396 ::ucbhelper::Content aCheckExistence
;
397 sal_Bool bExists
= sal_False
;
400 aCheckExistence
= ::ucbhelper::Content(_rURL
, Reference
< XCommandEnvironment
>());
402 bExists
= aCheckExistence
.isFolder();
404 bExists
= aCheckExistence
.isDocument();
406 catch(const Exception
&) { }
410 // -----------------------------------------------------------------------------
411 const sal_Char
* OEvoabDriver::getSDBC_SCHEME_EVOLUTION()
413 static const sal_Char
* SDBC_SCHEME_EVOLUTION
= EVOAB_EVOLUTION_SCHEMA
;
414 return SDBC_SCHEME_EVOLUTION
;
416 const sal_Char
* OEvoabDriver::getEVOAB_FOLDERLIST_FILE_NAME()
418 static const sal_Char
* EVOAB_FOLDERLIST_FILE_NAME
= "FolderList";
419 return EVOAB_FOLDERLIST_FILE_NAME
;
421 const sal_Char
* OEvoabDriver::getEVOAB_VERSION_FILE_NAME()
423 static const sal_Char
* EVOAB_VERSION_FILE_NAME
= "EvoVersion";
424 return EVOAB_VERSION_FILE_NAME
;
426 const sal_Char
* OEvoabDriver::getEVOAB_META_FILE_EXT()
428 static const sal_Char
* EVOAB_META_FILE_EXT
= "csv";
429 return EVOAB_META_FILE_EXT
;
431 const sal_Char
* OEvoabDriver::getEVOAB_CLI_FULLPATHCOMMAND()
433 static const sal_Char
* EVOAB_CLI_FULLPATHCOMMAND
= "file:///home/evoab/extra/share/evolution/*/tools/evolution-addressbook-export";
434 return EVOAB_CLI_FULLPATHCOMMAND
;
436 const sal_Char
* OEvoabDriver::getEVOAB_CLI_ARG_LIST_FOLDERS()
438 static const sal_Char
* EVOAB_CLI_ARG_LIST_FOLDERS
= "-l";
439 return EVOAB_CLI_ARG_LIST_FOLDERS
;
441 const sal_Char
* OEvoabDriver::getEVOAB_CLI_ARG_OUTPUT_FILE_PREFIX()
443 static const sal_Char
* EVOAB_CLI_ARG_OUTPUT_FILE_PREFIX
= "--output=";
444 return EVOAB_CLI_ARG_OUTPUT_FILE_PREFIX
;
446 const sal_Char
* OEvoabDriver::getEVOAB_CLI_ARG_OUTPUT_FORMAT()
448 static const sal_Char
* EVOAB_CLI_ARG_OUTPUT_FORMAT
= "--format=csv";
449 return EVOAB_CLI_ARG_OUTPUT_FORMAT
;
451 const sal_Char
* OEvoabDriver::getEVOAB_CLI_ARG_VERSION()
453 static const sal_Char
* EVOAB_CLI_ARG_VERSION
= "--version";
454 return EVOAB_CLI_ARG_VERSION
;
456 const sal_Char
* OEvoabDriver::getEVOAB_CLI_ARG_OUTPUT_REDIRECT()
458 static const sal_Char
* EVOAB_CLI_ARG_OUTPUT_REDIRECT
= ">";
459 return EVOAB_CLI_ARG_OUTPUT_REDIRECT
;
461 rtl::OUString
OEvoabDriver::translateFileErrorMessage( oslFileError nFileErr
)
463 ::rtl::OUString sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" no file operation!."));
466 case osl_File_E_None
:
467 sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation succeeded!"));
469 case osl_File_E_INVAL
:
470 sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: the format of the parameters was not valid!"));
472 case osl_File_E_INTR
:
473 sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: function call was interrupted!"));
476 sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: I/O errors!"));
478 case osl_File_E_ISDIR
:
479 sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: is a directory!"));
481 case osl_File_E_BADF
:
482 sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: bad file!"));
484 case osl_File_E_FAULT
:
485 sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: bad address!"));
487 case osl_File_E_AGAIN
:
488 sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: operation would block!"));
490 case osl_File_E_NOLINK
:
491 sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: link has been severed!"));
494 sFileErr
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: other reason!"));
498 // -----------------------------------------------------------------------------
499 Sequence
< DriverPropertyInfo
> SAL_CALL
OEvoabDriver::getPropertyInfo( const ::rtl::OUString
& url
, const Sequence
< PropertyValue
>& /*info*/ ) throw(SQLException
, RuntimeException
)
501 if ( !acceptsURL(url
) )
503 ::connectivity::SharedResources aResources
;
504 const ::rtl::OUString sMessage
= aResources
.getResourceString(STR_URI_SYNTAX_ERROR
);
505 ::dbtools::throwGenericSQLException(sMessage
,*this);
506 } // if ( !acceptsURL(url) )
507 return Sequence
< DriverPropertyInfo
>();