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/.
10 #include "diagnose_ex.h"
11 #include "MNSProfileDiscover.hxx"
12 #include "MConnection.hxx"
13 #include "MDriver.hxx"
14 #include "MDatabaseMetaData.hxx"
15 #include "MCatalog.hxx"
16 #include "MPreparedStatement.hxx"
17 #include "MorkParser.hxx"
19 #include <connectivity/dbcharset.hxx>
20 #include <connectivity/dbexception.hxx>
21 #include <connectivity/sqlerror.hxx>
23 #include "resource/mork_res.hrc"
24 #include "resource/common_res.hrc"
26 #include <com/sun/star/sdbc/ColumnValue.hpp>
27 #include <com/sun/star/sdbc/XRow.hpp>
28 #include <com/sun/star/sdbc/TransactionIsolation.hpp>
30 #include <comphelper/officeresourcebundle.hxx>
31 #include <comphelper/processfactory.hxx>
33 using namespace dbtools
;
36 using namespace com::sun::star::uno
;
37 using namespace com::sun::star::lang
;
38 using namespace com::sun::star::beans
;
39 using namespace com::sun::star::sdbc
;
40 using namespace com::sun::star::sdbcx
;
43 namespace connectivity
{ namespace mork
{
45 static const int defaultScope
= 0x80;
49 OConnection::OConnection(MorkDriver
* _pDriver
)
50 :OSubComponent
<OConnection
, OConnection_BASE
>((::cppu::OWeakObject
*)_pDriver
, this)
52 ,m_aColumnAlias( _pDriver
->getFactory() )
55 m_pProfileAccess
= new ProfileAccess();
56 m_pBook
= new MorkParser();
57 m_pHistory
= new MorkParser();
60 OConnection::~OConnection()
66 delete m_pProfileAccess
;
71 void SAL_CALL
OConnection::release() throw()
77 void OConnection::construct(const OUString
& url
,const Sequence
< PropertyValue
>& info
) throw(SQLException
)
79 (void) info
; // avoid warnings
80 SAL_INFO("connectivity.mork", "=> OConnection::construct()" );
84 // Skip 'sdbc:mozab: part of URL
86 sal_Int32 nLen
= url
.indexOf(':');
87 nLen
= url
.indexOf(':',nLen
+1);
88 OSL_ENSURE( url
.copy( 0, nLen
) == "sdbc:address", "OConnection::construct: invalid start of the URI - should never have survived XDriver::acceptsURL!" );
90 OUString
aAddrbookURI(url
.copy(nLen
+1));
92 nLen
= aAddrbookURI
.indexOf(':');
93 OUString aAddrbookScheme
;
94 OUString sAdditionalInfo
;
97 // There isn't any subschema: - but could be just subschema
98 if ( !aAddrbookURI
.isEmpty() )
100 aAddrbookScheme
= aAddrbookURI
;
104 SAL_WARN("connectivity.mork", "No subschema given!!!");
105 throwGenericSQLException( STR_URI_SYNTAX_ERROR
, *this );
110 aAddrbookScheme
= aAddrbookURI
.copy(0, nLen
);
111 sAdditionalInfo
= aAddrbookURI
.copy( nLen
+ 1 );
114 SAL_INFO("connectivity.mork", "URI = " << aAddrbookURI
);
115 SAL_INFO("connectivity.mork", "Scheme = " << aAddrbookScheme
);
119 const OUString UNITTEST_URL
= "thunderbird:unittest:";
120 sal_Int32 unittestIndex
= url
.indexOf(UNITTEST_URL
);
123 if (unittestIndex
== -1)
125 OUString defaultProfile
= m_pProfileAccess
->getDefaultProfile(::com::sun::star::mozilla::MozillaProductType_Thunderbird
);
126 OUString path
= m_pProfileAccess
->getProfilePath(::com::sun::star::mozilla::MozillaProductType_Thunderbird
, defaultProfile
);
127 SAL_INFO("connectivity.mork", "DefaultProfile: " << defaultProfile
);
128 SAL_INFO("connectivity.mork", "ProfilePath: " << path
);
129 abook
= path
+ "/abook.mab";
130 history
= path
+ "/history.mab";
131 SAL_INFO("connectivity.mork", "AdressbookPath (abook): " << abook
);
132 SAL_INFO("connectivity.mork", "AdressbookPath (history): " << history
);
136 abook
= aAddrbookURI
.replaceFirst(UNITTEST_URL
, "");
137 SAL_INFO("connectivity.mork", "unit test: " << abook
);
140 OString strPath
= OUStringToOString(abook
, RTL_TEXTENCODING_UTF8
);
142 // Open and parse mork file
143 if (!m_pBook
->open(strPath
.getStr()))
145 SAL_WARN("connectivity.mork", "Can not parse abook mork file: " << strPath
);
146 throwGenericSQLException( STR_COULD_NOT_LOAD_FILE
, *this );
149 // read history only in production
150 if (unittestIndex
== -1)
152 strPath
= OUStringToOString(history
, RTL_TEXTENCODING_UTF8
);
153 if (!m_pHistory
->open(strPath
.getStr()))
155 SAL_WARN("connectivity.mork", "Can not parse history mork file: " << strPath
);
156 throwGenericSQLException( STR_COULD_NOT_LOAD_FILE
, *this );
160 // check that we can retrieve the tables:
161 MorkTableMap
*Tables
= m_pBook
->getTables( defaultScope
);
162 MorkTableMap::iterator tableIter
;
165 // Iterate all tables
166 for ( tableIter
= Tables
->begin(); tableIter
!= Tables
->end(); ++tableIter
)
168 if ( 0 == tableIter
->first
) continue;
169 SAL_INFO("connectivity.mork", "table->first : " << tableIter
->first
);
176 IMPLEMENT_SERVICE_INFO(OConnection
, "com.sun.star.sdbc.drivers.mork.OConnection", "com.sun.star.sdbc.Connection")
179 Reference
< XStatement
> SAL_CALL
OConnection::createStatement( ) throw(SQLException
, RuntimeException
, std::exception
)
181 SAL_INFO("connectivity.mork", "=> OConnection::createStatement()" );
183 ::osl::MutexGuard
aGuard( m_aMutex
);
184 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
186 // create a statement
187 // the statement can only be executed once
188 Reference
< XStatement
> xReturn
= new OStatement(this);
189 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
193 Reference
< XPreparedStatement
> SAL_CALL
OConnection::prepareStatement( const OUString
& _sSql
) throw(SQLException
, RuntimeException
, std::exception
)
195 SAL_INFO("connectivity.mork", "=> OConnection::prepareStatement()" );
196 SAL_INFO("connectivity.mork", "OConnection::prepareStatement( " << _sSql
<< " )");
199 ::osl::MutexGuard
aGuard( m_aMutex
);
200 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
203 // create a statement
204 // the statement can only be executed more than once
205 OPreparedStatement
* pPrepared
= new OPreparedStatement(this,_sSql
);
206 Reference
< XPreparedStatement
> xReturn
= pPrepared
;
207 pPrepared
->lateInit();
209 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
213 Reference
< XPreparedStatement
> SAL_CALL
OConnection::prepareCall( const OUString
& _sSql
) throw(SQLException
, RuntimeException
, std::exception
)
215 SAL_INFO("connectivity.mork", "=> OConnection::prepareCall()" );
216 SAL_INFO("connectivity.mork", "sql: " << _sSql
);
218 ::dbtools::throwFeatureNotImplementedException( "XConnection::prepareCall", *this );
219 SAL_INFO("connectivity.mork", "OConnection::prepareCall( " << _sSql
<< " )");
223 OUString SAL_CALL
OConnection::nativeSQL( const OUString
& _sSql
) throw(SQLException
, RuntimeException
, std::exception
)
225 SAL_INFO("connectivity.mork", "=> OConnection::nativeSQL()" );
226 SAL_INFO("connectivity.mork", "sql: " << _sSql
);
228 ::osl::MutexGuard
aGuard( m_aMutex
);
229 // when you need to transform SQL92 to you driver specific you can do it here
230 SAL_INFO("connectivity.mork", "OConnection::nativeSQL(" << _sSql
<< " )" );
235 void SAL_CALL
OConnection::setAutoCommit( sal_Bool
/*autoCommit*/ ) throw(SQLException
, RuntimeException
, std::exception
)
237 ::dbtools::throwFeatureNotImplementedException( "XConnection::setAutoCommit", *this );
240 sal_Bool SAL_CALL
OConnection::getAutoCommit( ) throw(SQLException
, RuntimeException
, std::exception
)
242 // you have to distinguish which if you are in autocommit mode or not
243 // at normal case true should be fine here
248 void SAL_CALL
OConnection::commit( ) throw(SQLException
, RuntimeException
, std::exception
)
250 // when you database does support transactions you should commit here
253 void SAL_CALL
OConnection::rollback( ) throw(SQLException
, RuntimeException
, std::exception
)
255 // same as commit but for the other case
258 sal_Bool SAL_CALL
OConnection::isClosed( ) throw(SQLException
, RuntimeException
, std::exception
)
260 ::osl::MutexGuard
aGuard( m_aMutex
);
262 // just simple -> we are close when we are disposed that means someone called dispose(); (XComponent)
263 return OConnection_BASE::rBHelper
.bDisposed
;
266 Reference
< XDatabaseMetaData
> SAL_CALL
OConnection::getMetaData( ) throw(SQLException
, RuntimeException
, std::exception
)
268 SAL_INFO("connectivity.mork", "=> OConnection::getMetaData()" );
270 ::osl::MutexGuard
aGuard( m_aMutex
);
271 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
273 // here we have to create the class with biggest interface
274 // The answer is 42 :-)
275 Reference
< XDatabaseMetaData
> xMetaData
= m_xMetaData
;
278 xMetaData
= new ODatabaseMetaData(this); // need the connection because it can return it
279 m_xMetaData
= xMetaData
;
285 void SAL_CALL
OConnection::setReadOnly( sal_Bool
/*readOnly*/ ) throw(SQLException
, RuntimeException
, std::exception
)
287 ::dbtools::throwFeatureNotImplementedException( "XConnection::setReadOnly", *this );
290 sal_Bool SAL_CALL
OConnection::isReadOnly( ) throw(SQLException
, RuntimeException
, std::exception
)
292 // return if your connection to readonly
296 void SAL_CALL
OConnection::setCatalog( const OUString
& /*catalog*/ ) throw(SQLException
, RuntimeException
, std::exception
)
298 ::dbtools::throwFeatureNotImplementedException( "XConnection::setCatalog", *this );
301 OUString SAL_CALL
OConnection::getCatalog( ) throw(SQLException
, RuntimeException
, std::exception
)
306 void SAL_CALL
OConnection::setTransactionIsolation( sal_Int32
/*level*/ ) throw(SQLException
, RuntimeException
, std::exception
)
308 ::dbtools::throwFeatureNotImplementedException( "XConnection::setTransactionIsolation", *this );
311 sal_Int32 SAL_CALL
OConnection::getTransactionIsolation( ) throw(SQLException
, RuntimeException
, std::exception
)
313 // please have a look at @see com.sun.star.sdbc.TransactionIsolation
314 return TransactionIsolation::NONE
;
317 Reference
< ::com::sun::star::container::XNameAccess
> SAL_CALL
OConnection::getTypeMap( ) throw(SQLException
, RuntimeException
, std::exception
)
319 // if your driver has special database types you can return it here
323 void SAL_CALL
OConnection::setTypeMap( const Reference
< ::com::sun::star::container::XNameAccess
>& /*typeMap*/ ) throw(SQLException
, RuntimeException
, std::exception
)
325 ::dbtools::throwFeatureNotImplementedException( "XConnection::setTypeMap", *this );
329 void SAL_CALL
OConnection::close( ) throw(SQLException
, RuntimeException
, std::exception
)
331 // we just dispose us
333 ::osl::MutexGuard
aGuard( m_aMutex
);
334 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
341 Any SAL_CALL
OConnection::getWarnings( ) throw(SQLException
, RuntimeException
, std::exception
)
343 // when you collected some warnings -> return it
347 void SAL_CALL
OConnection::clearWarnings( ) throw(SQLException
, RuntimeException
, std::exception
)
349 // you should clear your collected warnings here
352 void OConnection::disposing()
354 // we noticed that we should be destroied in near future so we have to dispose our statements
355 ::osl::MutexGuard
aGuard(m_aMutex
);
360 Reference
< XTablesSupplier
> SAL_CALL
OConnection::createCatalog()
362 OSL_TRACE("IN OConnection::createCatalog()" );
363 ::osl::MutexGuard
aGuard( m_aMutex
);
364 Reference
< XTablesSupplier
> xTab
= m_xCatalog
;
367 OCatalog
*pCat
= new OCatalog(this);
371 OSL_TRACE( "\tOUT OConnection::createCatalog()" );
377 void OConnection::throwSQLException( const ErrorDescriptor
& _rError
, const Reference
< XInterface
>& _rxContext
)
379 if ( _rError
.getResId() != 0 )
381 OSL_ENSURE( ( _rError
.getErrorCondition() == 0 ),
382 "OConnection::throwSQLException: unsupported error code combination!" );
384 OUString
sParameter( _rError
.getParameter() );
385 if ( !sParameter
.isEmpty() )
387 const OUString
sError( getResources().getResourceStringWithSubstitution(
391 ::dbtools::throwGenericSQLException( sError
, _rxContext
);
392 OSL_FAIL( "OConnection::throwSQLException: unreachable (1)!" );
395 throwGenericSQLException( _rError
.getResId(), _rxContext
);
396 OSL_FAIL( "OConnection::throwSQLException: unreachable (2)!" );
399 if ( _rError
.getErrorCondition() != 0 )
401 SQLError
aErrorHelper( comphelper::getComponentContext(getDriver()->getFactory()) );
402 OUString
sParameter( _rError
.getParameter() );
403 if ( !sParameter
.isEmpty() )
404 aErrorHelper
.raiseException( _rError
.getErrorCondition(), _rxContext
, sParameter
);
406 aErrorHelper
.raiseException( _rError
.getErrorCondition(), _rxContext
);
407 OSL_FAIL( "OConnection::throwSQLException: unreachable (3)!" );
410 throwGenericSQLException( STR_UNSPECIFIED_ERROR
, _rxContext
);
414 void OConnection::throwSQLException( const sal_uInt16 _nErrorResourceId
, const Reference
< XInterface
>& _rxContext
)
416 ErrorDescriptor aError
;
417 aError
.setResId( _nErrorResourceId
);
418 throwSQLException( aError
, _rxContext
);
421 } } // namespace connectivity::mork
423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */