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 "MConnection.hxx"
11 #include "MDriver.hxx"
12 #include "MDatabaseMetaData.hxx"
13 #include "MCatalog.hxx"
14 #include "MPreparedStatement.hxx"
15 #include "MorkParser.hxx"
17 #include <connectivity/dbexception.hxx>
19 #include "resource/mork_res.hrc"
20 #include "resource/common_res.hrc"
22 #include <com/sun/star/sdbc/TransactionIsolation.hpp>
24 #include <comphelper/processfactory.hxx>
26 using namespace dbtools
;
29 using namespace com::sun::star::uno
;
30 using namespace com::sun::star::lang
;
31 using namespace com::sun::star::beans
;
32 using namespace com::sun::star::sdbc
;
33 using namespace com::sun::star::sdbcx
;
36 namespace connectivity
{ namespace mork
{
38 static const int defaultScope
= 0x80;
41 OConnection::OConnection(MorkDriver
* _pDriver
)
42 :OSubComponent
<OConnection
, OConnection_BASE
>(static_cast<cppu::OWeakObject
*>(_pDriver
), this)
44 ,m_aColumnAlias( _pDriver
->getFactory() )
46 m_pBook
= new MorkParser();
47 m_pHistory
= new MorkParser();
50 OConnection::~OConnection()
58 void SAL_CALL
OConnection::release() throw()
64 void OConnection::construct(const OUString
& url
,const Sequence
< PropertyValue
>& info
) throw(SQLException
)
66 (void) info
; // avoid warnings
67 SAL_INFO("connectivity.mork", "=> OConnection::construct()" );
71 // Skip 'sdbc:mozab: part of URL
73 sal_Int32 nLen
= url
.indexOf(':');
74 nLen
= url
.indexOf(':',nLen
+1);
75 OSL_ENSURE( url
.copy( 0, nLen
) == "sdbc:address", "OConnection::construct: invalid start of the URI - should never have survived XDriver::acceptsURL!" );
77 OUString
aAddrbookURI(url
.copy(nLen
+1));
79 nLen
= aAddrbookURI
.indexOf(':');
80 OUString aAddrbookScheme
;
81 OUString sAdditionalInfo
;
84 // There isn't any subschema: - but could be just subschema
85 if ( !aAddrbookURI
.isEmpty() )
87 aAddrbookScheme
= aAddrbookURI
;
91 SAL_WARN("connectivity.mork", "No subschema given!!!");
92 throwGenericSQLException( STR_URI_SYNTAX_ERROR
, *this );
97 aAddrbookScheme
= aAddrbookURI
.copy(0, nLen
);
98 sAdditionalInfo
= aAddrbookURI
.copy( nLen
+ 1 );
101 SAL_INFO("connectivity.mork", "URI = " << aAddrbookURI
);
102 SAL_INFO("connectivity.mork", "Scheme = " << aAddrbookScheme
);
106 const OUString UNITTEST_URL
= "thunderbird:unittest:";
107 sal_Int32 unittestIndex
= url
.indexOf(UNITTEST_URL
);
110 if (unittestIndex
== -1)
112 OUString path
= m_xDriver
->getProfilePath();
113 SAL_INFO("connectivity.mork", "ProfilePath: " << path
);
114 abook
= path
+ "/abook.mab";
115 history
= path
+ "/history.mab";
116 SAL_INFO("connectivity.mork", "AdressbookPath (abook): " << abook
);
117 SAL_INFO("connectivity.mork", "AdressbookPath (history): " << history
);
121 abook
= aAddrbookURI
.replaceFirst(UNITTEST_URL
, "");
122 SAL_INFO("connectivity.mork", "unit test: " << abook
);
125 OString strPath
= OUStringToOString(abook
, RTL_TEXTENCODING_UTF8
);
127 // Open and parse mork file
128 if (!m_pBook
->open(strPath
.getStr()))
130 SAL_WARN("connectivity.mork", "Can not parse abook mork file: " << strPath
);
131 const OUString
sError( getResources().getResourceStringWithSubstitution(
132 STR_COULD_NOT_LOAD_FILE
, "$filename$", abook
));
133 ::dbtools::throwGenericSQLException( sError
, *this );
136 // read history only in production
137 if (unittestIndex
== -1)
139 strPath
= OUStringToOString(history
, RTL_TEXTENCODING_UTF8
);
140 if (!m_pHistory
->open(strPath
.getStr()))
142 SAL_WARN("connectivity.mork", "Can not parse history mork file: " << strPath
);
143 const OUString
sError( getResources().getResourceStringWithSubstitution(
144 STR_COULD_NOT_LOAD_FILE
, "$filename$", history
));
145 ::dbtools::throwGenericSQLException( sError
, *this );
149 // check that we can retrieve the tables:
150 MorkTableMap
*Tables
= m_pBook
->getTables( defaultScope
);
151 MorkTableMap::Map::const_iterator tableIter
;
154 // Iterate all tables
155 for ( tableIter
= Tables
->map
.begin(); tableIter
!= Tables
->map
.end(); ++tableIter
)
157 if ( 0 == tableIter
->first
) continue;
158 SAL_INFO("connectivity.mork", "table->first : " << tableIter
->first
);
161 // check that we can retrieve the history tables:
162 MorkTableMap
*Tables_hist
= m_pHistory
->getTables( defaultScope
);
165 // Iterate all tables
166 for ( tableIter
= Tables_hist
->map
.begin(); tableIter
!= Tables_hist
->map
.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
<< " )");
198 ::osl::MutexGuard
aGuard( m_aMutex
);
199 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
202 // create a statement
203 // the statement can only be executed more than once
204 OPreparedStatement
* pPrepared
= new OPreparedStatement(this,_sSql
);
205 Reference
< XPreparedStatement
> xReturn
= pPrepared
;
206 pPrepared
->lateInit();
208 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
212 Reference
< XPreparedStatement
> SAL_CALL
OConnection::prepareCall( const OUString
& _sSql
) throw(SQLException
, RuntimeException
, std::exception
)
214 SAL_INFO("connectivity.mork", "=> OConnection::prepareCall()" );
215 SAL_INFO("connectivity.mork", "sql: " << _sSql
);
216 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::prepareCall", *this );
217 SAL_INFO("connectivity.mork", "OConnection::prepareCall( " << _sSql
<< " )");
221 OUString SAL_CALL
OConnection::nativeSQL( const OUString
& _sSql
) throw(SQLException
, RuntimeException
, std::exception
)
223 SAL_INFO("connectivity.mork", "=> OConnection::nativeSQL()" );
224 SAL_INFO("connectivity.mork", "sql: " << _sSql
);
226 ::osl::MutexGuard
aGuard( m_aMutex
);
227 // when you need to transform SQL92 to you driver specific you can do it here
228 SAL_INFO("connectivity.mork", "OConnection::nativeSQL(" << _sSql
<< " )" );
233 void SAL_CALL
OConnection::setAutoCommit( sal_Bool
/*autoCommit*/ ) throw(SQLException
, RuntimeException
, std::exception
)
235 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setAutoCommit", *this );
238 sal_Bool SAL_CALL
OConnection::getAutoCommit( ) throw(SQLException
, RuntimeException
, std::exception
)
240 // you have to distinguish which if you are in autocommit mode or not
241 // at normal case true should be fine here
246 void SAL_CALL
OConnection::commit( ) throw(SQLException
, RuntimeException
, std::exception
)
248 // when you database does support transactions you should commit here
251 void SAL_CALL
OConnection::rollback( ) throw(SQLException
, RuntimeException
, std::exception
)
253 // same as commit but for the other case
256 sal_Bool SAL_CALL
OConnection::isClosed( ) throw(SQLException
, RuntimeException
, std::exception
)
258 ::osl::MutexGuard
aGuard( m_aMutex
);
260 // just simple -> we are close when we are disposed that means someone called dispose(); (XComponent)
261 return OConnection_BASE::rBHelper
.bDisposed
;
264 Reference
< XDatabaseMetaData
> SAL_CALL
OConnection::getMetaData( ) throw(SQLException
, RuntimeException
, std::exception
)
266 SAL_INFO("connectivity.mork", "=> OConnection::getMetaData()" );
268 ::osl::MutexGuard
aGuard( m_aMutex
);
269 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
271 // here we have to create the class with biggest interface
272 // The answer is 42 :-)
273 Reference
< XDatabaseMetaData
> xMetaData
= m_xMetaData
;
276 xMetaData
= new ODatabaseMetaData(this); // need the connection because it can return it
277 m_xMetaData
= xMetaData
;
283 void SAL_CALL
OConnection::setReadOnly( sal_Bool
/*readOnly*/ ) throw(SQLException
, RuntimeException
, std::exception
)
285 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setReadOnly", *this );
288 sal_Bool SAL_CALL
OConnection::isReadOnly( ) throw(SQLException
, RuntimeException
, std::exception
)
290 // return if your connection to readonly
294 void SAL_CALL
OConnection::setCatalog( const OUString
& /*catalog*/ ) throw(SQLException
, RuntimeException
, std::exception
)
296 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setCatalog", *this );
299 OUString SAL_CALL
OConnection::getCatalog( ) throw(SQLException
, RuntimeException
, std::exception
)
304 void SAL_CALL
OConnection::setTransactionIsolation( sal_Int32
/*level*/ ) throw(SQLException
, RuntimeException
, std::exception
)
306 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTransactionIsolation", *this );
309 sal_Int32 SAL_CALL
OConnection::getTransactionIsolation( ) throw(SQLException
, RuntimeException
, std::exception
)
311 // please have a look at @see com.sun.star.sdbc.TransactionIsolation
312 return TransactionIsolation::NONE
;
315 Reference
< css::container::XNameAccess
> SAL_CALL
OConnection::getTypeMap( ) throw(SQLException
, RuntimeException
, std::exception
)
317 // if your driver has special database types you can return it here
321 void SAL_CALL
OConnection::setTypeMap( const Reference
< css::container::XNameAccess
>& /*typeMap*/ ) throw(SQLException
, RuntimeException
, std::exception
)
323 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTypeMap", *this );
327 void SAL_CALL
OConnection::close( ) throw(SQLException
, RuntimeException
, std::exception
)
329 // we just dispose us
331 ::osl::MutexGuard
aGuard( m_aMutex
);
332 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
339 Any SAL_CALL
OConnection::getWarnings( ) throw(SQLException
, RuntimeException
, std::exception
)
341 // when you collected some warnings -> return it
345 void SAL_CALL
OConnection::clearWarnings( ) throw(SQLException
, RuntimeException
, std::exception
)
347 // you should clear your collected warnings here
350 void OConnection::disposing()
352 // we noticed that we should be destroied in near future so we have to dispose our statements
353 ::osl::MutexGuard
aGuard(m_aMutex
);
359 Reference
< XTablesSupplier
> SAL_CALL
OConnection::createCatalog()
361 OSL_TRACE("IN OConnection::createCatalog()" );
362 ::osl::MutexGuard
aGuard( m_aMutex
);
363 Reference
< XTablesSupplier
> xTab
= m_xCatalog
;
366 OCatalog
*pCat
= new OCatalog(this);
370 OSL_TRACE( "\tOUT OConnection::createCatalog()" );
375 void OConnection::throwSQLException( const ErrorDescriptor
& _rError
, const Reference
< XInterface
>& _rxContext
)
377 if ( _rError
.getResId() != 0 )
379 OSL_ENSURE( ( _rError
.getErrorCondition() == 0 ),
380 "OConnection::throwSQLException: unsupported error code combination!" );
382 const OUString
& sParameter( _rError
.getParameter() );
383 if ( !sParameter
.isEmpty() )
385 const OUString
sError( getResources().getResourceStringWithSubstitution(
389 ::dbtools::throwGenericSQLException( sError
, _rxContext
);
390 OSL_FAIL( "OConnection::throwSQLException: unreachable (1)!" );
393 throwGenericSQLException( _rError
.getResId(), _rxContext
);
394 OSL_FAIL( "OConnection::throwSQLException: unreachable (2)!" );
397 if ( _rError
.getErrorCondition() != 0 )
399 SQLError
aErrorHelper( comphelper::getComponentContext(getDriver()->getFactory()) );
400 const OUString
& sParameter( _rError
.getParameter() );
401 if ( !sParameter
.isEmpty() )
402 aErrorHelper
.raiseException( _rError
.getErrorCondition(), _rxContext
, sParameter
);
404 aErrorHelper
.raiseException( _rError
.getErrorCondition(), _rxContext
);
405 OSL_FAIL( "OConnection::throwSQLException: unreachable (3)!" );
408 throwGenericSQLException( STR_UNSPECIFIED_ERROR
, _rxContext
);
412 void OConnection::throwSQLException( const sal_uInt16 _nErrorResourceId
, const Reference
< XInterface
>& _rxContext
)
414 ErrorDescriptor aError
;
415 aError
.setResId( _nErrorResourceId
);
416 throwSQLException( aError
, _rxContext
);
419 } } // namespace connectivity::mork
421 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */