update emoji autocorrect entries from po-files
[LibreOffice.git] / connectivity / source / drivers / mozab / MConnection.cxx
blobbf1fb63fd47afd1b96531d19e536b40672f9ba53
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 .
21 #include "diagnose_ex.h"
22 #include "MConnection.hxx"
23 #include "MDatabaseMetaData.hxx"
24 #include "MDriver.hxx"
25 #include "MColumnAlias.hxx"
26 #include "MStatement.hxx"
27 #include "MPreparedStatement.hxx"
29 #include <connectivity/dbcharset.hxx>
30 #include <connectivity/dbexception.hxx>
31 #include <connectivity/sqlerror.hxx>
33 #include "resource/mozab_res.hrc"
34 #include "resource/common_res.hrc"
36 #include <com/sun/star/sdbc/ColumnValue.hpp>
37 #include <com/sun/star/sdbc/XRow.hpp>
38 #include <com/sun/star/sdbc/TransactionIsolation.hpp>
40 #include <comphelper/officeresourcebundle.hxx>
41 #include <comphelper/processfactory.hxx>
43 #if OSL_DEBUG_LEVEL > 0
44 # define OUtoCStr( x ) ( OUStringToOString ( (x), RTL_TEXTENCODING_ASCII_US).getStr())
45 #else /* OSL_DEBUG_LEVEL */
46 # define OUtoCStr( x ) ("dummy")
47 #endif /* OSL_DEBUG_LEVEL */
49 extern "C" SAL_DLLPUBLIC_EXPORT void* SAL_CALL OMozabConnection_CreateInstance(
50 void* _pDriver)
52 return (new connectivity::mozab::OConnection( reinterpret_cast<connectivity::mozab::MozabDriver*>(_pDriver) ));
55 using namespace dbtools;
58 using namespace com::sun::star::uno;
59 using namespace com::sun::star::lang;
60 using namespace com::sun::star::beans;
61 using namespace com::sun::star::sdbc;
62 using namespace com::sun::star::sdbcx;
65 namespace connectivity { namespace mozab {
68 // = ConnectionImplData
70 struct ConnectionImplData
72 ::boost::shared_ptr< ::comphelper::OfficeResourceBundle > pResourceBundle;
76 #ifdef __MINGW32__
77 extern "C"
78 #endif
79 const sal_Char* getSdbcScheme( SdbcScheme _eScheme )
81 switch ( _eScheme )
83 case SDBC_MOZILLA: return "mozilla";
84 case SDBC_THUNDERBIRD: return "thunderbird";
85 case SDBC_LDAP: return "ldap";
86 case SDBC_OUTLOOK_MAPI: return "outlook";
87 case SDBC_OUTLOOK_EXPRESS: return "outlookexp";
89 return NULL;
92 OUString OConnection::getDriverImplementationName()
94 return OUString(MOZAB_DRIVER_IMPL_NAME);
98 const sal_Char* getSchemeURI( MozillaScheme _eScheme )
100 switch ( _eScheme )
102 case SCHEME_MOZILLA : return "moz-abdirectory://";
103 case SCHEME_MOZILLA_MDB : return "moz-abmdbdirectory://";
104 case SCHEME_LDAP : return "moz-abldapdirectory://";
105 case SCHEME_OUTLOOK_MAPI : return "moz-aboutlookdirectory://op/";
106 case SCHEME_OUTLOOK_EXPRESS : return "moz-aboutlookdirectory://oe/";
108 return NULL;
113 OConnection::OConnection(MozabDriver* _pDriver)
114 :OSubComponent<OConnection, OConnection_BASE>((::cppu::OWeakObject*)_pDriver, this)
115 ,m_pDriver(_pDriver)
116 ,m_pImplData( new ConnectionImplData )
117 ,m_aColumnAlias( _pDriver->getMSFactory() )
118 ,m_nMaxResultRecords( -1 )
119 ,m_aNameMapper(NULL)
120 ,m_eSDBCAddressType(SDBCAddress::Unknown)
121 ,m_bForceLoadTable(false)
123 m_pDriver->acquire();
127 OConnection::~OConnection()
129 acquire();
130 if(!isClosed())
131 close();
132 m_pDriver->release();
133 m_pDriver = NULL;
136 void SAL_CALL OConnection::release() throw()
138 relase_ChildImpl();
142 void OConnection::construct(const OUString& url,const Sequence< PropertyValue >& info) throw(SQLException)
144 OSL_TRACE("IN OConnection::construct()" );
145 // open file
146 setURL(url);
148 // Skip 'sdbc:mozab: part of URL
150 sal_Int32 nLen = url.indexOf(':');
151 nLen = url.indexOf(':',nLen+1);
152 OSL_ENSURE( url.copy( 0, nLen ) == "sdbc:address", "OConnection::construct: invalid start of the URI - should never have survived XDriver::acceptsURL!" );
154 OUString aAddrbookURI(url.copy(nLen+1));
155 // Get Scheme
156 nLen = aAddrbookURI.indexOf(':');
157 OUString aAddrbookScheme;
158 OUString sAdditionalInfo;
159 if ( nLen == -1 )
161 // There isn't any subschema: - but could be just subschema
162 if ( !aAddrbookURI.isEmpty() )
164 aAddrbookScheme= aAddrbookURI;
166 else
168 OSL_TRACE( "No subschema given!!!");
169 throwSQLException( STR_URI_SYNTAX_ERROR, *this );
172 else
174 aAddrbookScheme = aAddrbookURI.copy(0, nLen);
175 sAdditionalInfo = aAddrbookURI.copy( nLen + 1 );
178 OSL_TRACE("URI = %s", ((OUtoCStr(aAddrbookURI)) ? (OUtoCStr(aAddrbookURI)):("NULL")) );
179 OSL_TRACE("Scheme = %s\n", ((OUtoCStr(aAddrbookScheme)) ? (OUtoCStr(aAddrbookScheme)):("NULL")) );
182 // Now we have a URI convert it to a MozillaURI
184 // The Mapping being used is:
186 // * for Mozilla
187 // "sdbc:address:mozilla:" -> abdirectory://
188 // * for LDAP
189 // "sdbc:address:ldap:" -> abldapdirectory://
190 // * for Outlook (using MAPI API)
191 // "sdbc:address:outlook:" -> aboutlookdirectory://op/
192 // * for windows system address book
193 // "sdbc:address:outlookexp:" -> aboutlookdirectory://oe/
195 m_sBindDN = "";
196 m_sPassword = "";
197 m_bUseSSL = sal_False;
199 if ( aAddrbookScheme.equalsAscii( getSdbcScheme( SDBC_MOZILLA ) ) ) {
200 m_sMozillaURI = OUString::createFromAscii( getSchemeURI( SCHEME_MOZILLA ) );
201 m_eSDBCAddressType = SDBCAddress::Mozilla;
202 if(!sAdditionalInfo.isEmpty())
203 m_sMozillaProfile = sAdditionalInfo;
205 else
206 if ( aAddrbookScheme.equalsAscii( getSdbcScheme( SDBC_THUNDERBIRD ) ) ) {
207 //Yes. I am sure it is SCHEME_MOZILLA
208 m_sMozillaURI = OUString::createFromAscii( getSchemeURI( SCHEME_MOZILLA ) );
209 m_eSDBCAddressType = SDBCAddress::ThunderBird;
210 if(!sAdditionalInfo.isEmpty())
211 m_sMozillaProfile = sAdditionalInfo;
213 else if ( aAddrbookScheme.equalsAscii( getSdbcScheme( SDBC_LDAP ) ) ) {
214 OUString sBaseDN;
215 sal_Int32 nPortNumber = -1;
217 m_sMozillaURI = OUString::createFromAscii( getSchemeURI( SCHEME_LDAP ) );
218 m_eSDBCAddressType = SDBCAddress::LDAP;
220 if ( m_sHostName.isEmpty() )
222 // see whether the URI contains a hostname/port
223 if ( !sAdditionalInfo.isEmpty() )
225 sal_Int32 nPortSeparator = sAdditionalInfo.indexOf( ':' );
226 if ( nPortSeparator == -1 )
227 m_sHostName = sAdditionalInfo;
228 else
230 m_sHostName = sAdditionalInfo.copy( 0, nPortSeparator );
231 nPortNumber = sAdditionalInfo.copy( nPortSeparator + 1 ).toInt32();
232 OSL_ENSURE( nPortNumber != 0, "OConnection::construct: invalid LDAP port number in the URL!" );
233 if ( nPortNumber == 0 )
234 nPortNumber = -1;
239 const PropertyValue* pInfo = info.getConstArray();
240 const PropertyValue* pInfoEnd = pInfo + info.getLength();
242 for (; pInfo != pInfoEnd; ++pInfo)
244 OSL_TRACE( "info[%d].Name = %s", pInfo - info.getConstArray(), OUtoCStr( pInfo->Name ) );
246 if ( pInfo->Name.equalsAscii("HostName") )
248 pInfo->Value >>= m_sHostName;
250 else if ( pInfo->Name.equalsAscii("BaseDN") )
252 pInfo->Value >>= sBaseDN;
254 else if ( pInfo->Name.equalsAscii("user") )
256 pInfo->Value >>= m_sBindDN;
258 else if ( pInfo->Name.equalsAscii("password") )
260 pInfo->Value >>= m_sPassword;
262 else if ( pInfo->Name.equalsAscii("UseSSL") )
264 pInfo->Value >>= m_bUseSSL;
266 else if ( pInfo->Name.equalsAscii("PortNumber") )
268 OSL_VERIFY( pInfo->Value >>= nPortNumber );
270 else if ( pInfo->Name.equalsAscii("MaxRowCount") )
272 pInfo->Value >>= m_nMaxResultRecords;
276 if ( !m_sHostName.isEmpty() ) {
277 m_sMozillaURI += m_sHostName;
279 else
280 throwSQLException( STR_NO_HOSTNAME, *this );
282 if ( nPortNumber > 0 ) {
283 m_sMozillaURI += ":";
284 m_sMozillaURI += OUString::number( nPortNumber );
287 if ( !sBaseDN.isEmpty() ) {
288 m_sMozillaURI += "/";
289 m_sMozillaURI += sBaseDN;
291 else
292 throwSQLException( STR_NO_BASEDN, *this );
294 // Addition of a fake query to enable the Mozilla LDAP directory to work correctly.
295 m_sMozillaURI += "?(or(DisplayName,=,DontDoThisAtHome)))";
298 else if ( aAddrbookScheme.equalsAscii( getSdbcScheme( SDBC_OUTLOOK_MAPI ) ) ) {
299 m_sMozillaURI = OUString::createFromAscii( getSchemeURI( SCHEME_OUTLOOK_MAPI ) );
300 m_eSDBCAddressType = SDBCAddress::Outlook;
302 else if ( aAddrbookScheme.equalsAscii( getSdbcScheme( SDBC_OUTLOOK_EXPRESS ) ) ) {
303 m_sMozillaURI = OUString::createFromAscii( getSchemeURI( SCHEME_OUTLOOK_EXPRESS ) );
304 m_eSDBCAddressType = SDBCAddress::OutlookExp;
306 else
308 OSL_TRACE("Invalid subschema given!!!");
309 throwSQLException( STR_URI_SYNTAX_ERROR, *this );
312 OSL_TRACE("Moz URI = %s, %s", ((OUtoCStr(m_sMozillaURI)) ? (OUtoCStr(m_sMozillaURI)):("NULL")), usesFactory() ? "uses factory" : "no factory");
313 OSL_TRACE( "\tOUT OConnection::construct()\n" );
315 MDatabaseMetaDataHelper _aDbHelper;
317 // The creation of the nsIAbDirectory i/f for LDAP doesn't actually test
318 // the validity of the connection, it's normally delayed until the query
319 // is executed, but it's a bit late then to fail...
320 if ( isLDAP() )
322 if ( !_aDbHelper.testLDAPConnection( this ) )
324 OSL_TRACE("testLDAPConnection : FAILED" );
325 throwSQLException( _aDbHelper.getError(), *this );
327 else
329 OSL_TRACE("testLDAPConnection : SUCCESS" );
333 // Test connection by getting to get the Table Names
334 ::std::vector< OUString > tables;
335 ::std::vector< OUString > types;
336 if ( !_aDbHelper.getTableStrings( this, tables, types ) )
338 throwSQLException( _aDbHelper.getError(), *this );
342 // XServiceInfo
344 IMPLEMENT_SERVICE_INFO(OConnection, "com.sun.star.sdbc.drivers.mozab.OConnection", "com.sun.star.sdbc.Connection")
347 Reference< XStatement > SAL_CALL OConnection::createStatement( ) throw(SQLException, RuntimeException)
349 ::osl::MutexGuard aGuard( m_aMutex );
350 checkDisposed(OConnection_BASE::rBHelper.bDisposed);
352 // create a statement
353 // the statement can only be executed once
354 Reference< XStatement > xReturn = new OStatement(this);
355 m_aStatements.push_back(WeakReferenceHelper(xReturn));
356 return xReturn;
359 Reference< XPreparedStatement > SAL_CALL OConnection::prepareStatement( const OUString& _sSql ) throw(SQLException, RuntimeException)
361 ::osl::MutexGuard aGuard( m_aMutex );
362 checkDisposed(OConnection_BASE::rBHelper.bDisposed);
364 OSL_TRACE("OConnection::prepareStatement( %s )", OUtoCStr( _sSql ) );
365 // the pre
366 // create a statement
367 // the statement can only be executed more than once
368 OPreparedStatement* pPrepared = new OPreparedStatement(this,_sSql);
369 Reference< XPreparedStatement > xReturn = pPrepared;
370 pPrepared->lateInit();
372 m_aStatements.push_back(WeakReferenceHelper(xReturn));
373 return xReturn;
376 Reference< XPreparedStatement > SAL_CALL OConnection::prepareCall( const OUString& _sSql ) throw(SQLException, RuntimeException)
378 OSL_UNUSED( _sSql );
379 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::prepareCall", *this );
380 OSL_TRACE("OConnection::prepareCall( %s )", OUtoCStr( _sSql ) );
381 return NULL;
384 OUString SAL_CALL OConnection::nativeSQL( const OUString& _sSql ) throw(SQLException, RuntimeException)
386 ::osl::MutexGuard aGuard( m_aMutex );
387 // when you need to transform SQL92 to you driver specific you can do it here
388 OSL_TRACE("OConnection::nativeSQL( %s )", OUtoCStr( _sSql ) );
390 return _sSql;
393 void SAL_CALL OConnection::setAutoCommit( sal_Bool /*autoCommit*/ ) throw(SQLException, RuntimeException)
395 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setAutoCommit", *this );
398 sal_Bool SAL_CALL OConnection::getAutoCommit( ) throw(SQLException, RuntimeException)
400 // you have to distinguish which if you are in autocommit mode or not
401 // at normal case true should be fine here
403 return sal_True;
406 void SAL_CALL OConnection::commit( ) throw(SQLException, RuntimeException)
408 // when you database does support transactions you should commit here
411 void SAL_CALL OConnection::rollback( ) throw(SQLException, RuntimeException)
413 // same as commit but for the other case
416 sal_Bool SAL_CALL OConnection::isClosed( ) throw(SQLException, RuntimeException)
418 ::osl::MutexGuard aGuard( m_aMutex );
420 // just simple -> we are close when we are disposed that means someone called dispose(); (XComponent)
421 return OConnection_BASE::rBHelper.bDisposed;
424 Reference< XDatabaseMetaData > SAL_CALL OConnection::getMetaData( ) throw(SQLException, RuntimeException)
426 ::osl::MutexGuard aGuard( m_aMutex );
427 checkDisposed(OConnection_BASE::rBHelper.bDisposed);
429 // here we have to create the class with biggest interface
430 // The answer is 42 :-)
431 Reference< XDatabaseMetaData > xMetaData = m_xMetaData;
432 if(!xMetaData.is())
434 xMetaData = new ODatabaseMetaData(this); // need the connection because it can return it
435 m_xMetaData = xMetaData;
438 return xMetaData;
441 void SAL_CALL OConnection::setReadOnly( sal_Bool /*readOnly*/ ) throw(SQLException, RuntimeException)
443 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setReadOnly", *this );
446 sal_Bool SAL_CALL OConnection::isReadOnly( ) throw(SQLException, RuntimeException)
448 // return if your connection to readonly
449 return sal_False;
452 void SAL_CALL OConnection::setCatalog( const OUString& /*catalog*/ ) throw(SQLException, RuntimeException)
454 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setCatalog", *this );
457 OUString SAL_CALL OConnection::getCatalog( ) throw(SQLException, RuntimeException)
459 // return your current catalog
460 return OUString();
463 void SAL_CALL OConnection::setTransactionIsolation( sal_Int32 /*level*/ ) throw(SQLException, RuntimeException)
465 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTransactionIsolation", *this );
468 sal_Int32 SAL_CALL OConnection::getTransactionIsolation( ) throw(SQLException, RuntimeException)
470 // please have a look at @see com.sun.star.sdbc.TransactionIsolation
471 return TransactionIsolation::NONE;
474 Reference< ::com::sun::star::container::XNameAccess > SAL_CALL OConnection::getTypeMap( ) throw(SQLException, RuntimeException)
476 // if your driver has special database types you can return it here
477 return NULL;
480 void SAL_CALL OConnection::setTypeMap( const Reference< ::com::sun::star::container::XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException)
482 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTypeMap", *this );
485 // XCloseable
486 void SAL_CALL OConnection::close( ) throw(SQLException, RuntimeException)
488 // we just dispose us
490 ::osl::MutexGuard aGuard( m_aMutex );
491 checkDisposed(OConnection_BASE::rBHelper.bDisposed);
494 dispose();
497 // XWarningsSupplier
498 Any SAL_CALL OConnection::getWarnings( ) throw(SQLException, RuntimeException)
500 // when you collected some warnings -> return it
501 return Any();
504 void SAL_CALL OConnection::clearWarnings( ) throw(SQLException, RuntimeException)
506 // you should clear your collected warnings here
509 void OConnection::disposing()
511 // we noticed that we should be destroied in near future so we have to dispose our statements
512 ::osl::MutexGuard aGuard(m_aMutex);
514 m_pImplData->pResourceBundle.reset();
516 OConnection_BASE::disposing();
517 if ( m_aNameMapper ) {
518 MQuery::FreeNameMapper( m_aNameMapper );
519 m_aNameMapper = NULL;
522 dispose_ChildImpl();
526 Reference< XTablesSupplier > SAL_CALL OConnection::createCatalog()
528 OSL_TRACE("IN OConnection::createCatalog()" );
529 ::osl::MutexGuard aGuard( m_aMutex );
530 Reference< XTablesSupplier > xTab = m_xCatalog;
531 if(!m_xCatalog.is())
533 OCatalog *pCat = new OCatalog(this);
534 xTab = pCat;
535 m_xCatalog = xTab;
537 OSL_TRACE( "\tOUT OConnection::createCatalog()" );
538 return xTab;
542 MNameMapper* OConnection::getNameMapper ()
544 if (m_aNameMapper==NULL)
545 m_aNameMapper = MQuery::CreateNameMapper();
547 return m_aNameMapper;
551 void OConnection::throwSQLException( const ErrorDescriptor& _rError, const Reference< XInterface >& _rxContext )
553 if ( _rError.getResId() != 0 )
555 OSL_ENSURE( ( _rError.getErrorCondition() == 0 ),
556 "OConnection::throwSQLException: unsupported error code combination!" );
558 OUString sParameter( _rError.getParameter() );
559 if ( !sParameter.isEmpty() )
561 const OUString sError( getResources().getResourceStringWithSubstitution(
562 _rError.getResId(),
563 "$1$", sParameter
564 ) );
565 ::dbtools::throwGenericSQLException( sError, _rxContext );
566 OSL_FAIL( "OConnection::throwSQLException: unreachable (1)!" );
569 throwGenericSQLException( _rError.getResId(), _rxContext );
570 OSL_FAIL( "OConnection::throwSQLException: unreachable (2)!" );
573 if ( _rError.getErrorCondition() != 0 )
575 SQLError aErrorHelper( comphelper::getComponentContext(getDriver()->getMSFactory()) );
576 OUString sParameter( _rError.getParameter() );
577 if ( !sParameter.isEmpty() )
578 aErrorHelper.raiseException( _rError.getErrorCondition(), _rxContext, sParameter );
579 else
580 aErrorHelper.raiseException( _rError.getErrorCondition(), _rxContext);
581 OSL_FAIL( "OConnection::throwSQLException: unreachable (3)!" );
584 throwGenericSQLException( STR_UNSPECIFIED_ERROR, _rxContext );
588 void OConnection::throwSQLException( const sal_uInt16 _nErrorResourceId, const Reference< XInterface >& _rxContext )
590 ErrorDescriptor aError;
591 aError.setResId( _nErrorResourceId );
592 throwSQLException( aError, _rxContext );
595 } } // namespace connectivity::mozab
597 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */