4 package eu
.etaxonomy
.cdm
.database
;
6 import java
.io
.PrintWriter
;
7 import java
.net
.URISyntaxException
;
8 import java
.sql
.Connection
;
9 import java
.sql
.DatabaseMetaData
;
10 import java
.sql
.PreparedStatement
;
11 import java
.sql
.ResultSet
;
12 import java
.sql
.SQLException
;
13 import java
.sql
.SQLFeatureNotSupportedException
;
16 import javax
.sql
.DataSource
;
18 import org
.apache
.log4j
.Logger
;
19 import org
.hibernate
.cache
.spi
.RegionFactory
;
20 import org
.springframework
.beans
.factory
.config
.BeanDefinition
;
22 import com
.mchange
.v2
.c3p0
.ComboPooledDataSource
;
24 import eu
.etaxonomy
.cdm
.config
.CdmSourceException
;
25 import eu
.etaxonomy
.cdm
.model
.metadata
.CdmMetaDataPropertyName
;
28 * This class is a wrapper class to wrap an {@link javax.sql.DataSource} to an
29 * {@link ICdmDataSource}. As the former is a very limited interface it is not possible
30 * to implement all methods of {@link ICdmDataSource}. However, the aim is
31 * to implement all those methods which are usually needed to work with a datasource
32 * which represents a connection to a database such as transaction handling and
34 * Those methods which are not supported by this wrapper class will throw an xxx
41 //FIXME this class replicates lots of code in CdmDataSourceBase, we may want to merge it
42 //in a common helper class to avoid redundant code
43 public class WrappedCdmDataSource
implements ICdmDataSource
{
44 private static final Logger logger
= Logger
.getLogger(WrappedCdmDataSource
.class);
47 private final DataSource datasource
;
49 private Connection connection
;
52 public WrappedCdmDataSource(DataSource datasource
) {
53 if (datasource
== null){
54 throw new NullPointerException("datasource must not be null for WrappedCdmDataSource");
56 this.datasource
= datasource
;
60 public Connection
getConnection() throws SQLException
{
61 Connection existingConnection
= getExistingConnection();
62 if (existingConnection
!= null){
63 return existingConnection
;
65 return datasource
.getConnection();
69 public Connection
getExistingConnection(){
70 return this.connection
;
75 public Connection
getConnection(String username
, String password
) throws SQLException
{
76 Connection existingConnection
= getExistingConnection();
77 if (existingConnection
!= null){
78 return existingConnection
;
80 return datasource
.getConnection(username
, password
);
85 public PrintWriter
getLogWriter() throws SQLException
{
86 return datasource
.getLogWriter();
90 public void setLogWriter(PrintWriter out
) throws SQLException
{
91 datasource
.setLogWriter(out
);
95 public void setLoginTimeout(int seconds
) throws SQLException
{
96 datasource
.setLoginTimeout(seconds
);
100 public int getLoginTimeout() throws SQLException
{
101 return datasource
.getLoginTimeout();
105 public java
.util
.logging
.Logger
getParentLogger() throws SQLFeatureNotSupportedException
{
106 return datasource
.getParentLogger();
110 public <T
> T
unwrap(Class
<T
> iface
) throws SQLException
{
111 return datasource
.unwrap(iface
);
115 public boolean isWrapperFor(Class
<?
> iface
) throws SQLException
{
116 return datasource
.isWrapperFor(iface
);
120 public String
getName() {
121 throw new UnsupportedOperationException("getName() not supported by WrappedCdmDataSource");
125 public void setName(String name
) {
126 throw new UnsupportedOperationException("setName(String) not supported by WrappedCdmDataSource");
130 public String
getServer() {
131 //TODO we may want to use client info from connection here
132 throw new UnsupportedOperationException("getServer() not supported by WrappedCdmDataSource");
136 public void setServer(String server
) {
137 throw new UnsupportedOperationException("setServer() not supported by WrappedCdmDataSource");
141 public int getPort() {
142 //TODO we may want to use client info from connection here
143 throw new UnsupportedOperationException("getPort() not supported by WrappedCdmDataSource");
147 public void setPort(int port
) {
148 throw new UnsupportedOperationException("setPort(int) not supported by WrappedCdmDataSource");
152 public String
getDbSchemaVersion() throws CdmSourceException
{
154 return (String
)getSingleValue(CdmMetaDataPropertyName
.DB_SCHEMA_VERSION
.getSqlQuery());
155 } catch (SQLException e
) {
156 throw new CdmSourceException(e
.getMessage());
162 public boolean isDbEmpty() throws CdmSourceException
{
163 // Any CDM DB should have a schema version
164 String dbSchemaVersion
= getDbSchemaVersion();
165 return (dbSchemaVersion
== null || dbSchemaVersion
.equals(""));
169 public boolean checkConnection() throws CdmSourceException
{
171 return testConnection();
172 } catch (ClassNotFoundException e
) {
173 throw new CdmSourceException(e
.getMessage());
174 } catch (SQLException e
) {
175 throw new CdmSourceException(e
.getMessage());
180 public String
getConnectionMessage() {
182 Connection connection
= getConnection();
183 String message
= "Connecting to datasource " + connection
.getSchema() + ".";
185 } catch (SQLException e
) {
186 throw new RuntimeException(e
);
191 public void closeOpenConnections() {
193 if(connection
!= null && !connection
.isClosed()){
197 } catch (SQLException e
) {
198 logger
.error("Error closing the connection");
203 public Map
<CdmMetaDataPropertyName
, String
> getMetaDataMap() throws CdmSourceException
{
204 //TODO is it possible/required to build a meta data map here?
205 throw new UnsupportedOperationException("getMetaDataMap() not supported by WrappedCdmDataSource");
209 public BeanDefinition
getDatasourceBean() {
210 //TODO is it possible/required to build a datasource bean here?
211 throw new UnsupportedOperationException("getDatasourceBean() not supported by WrappedCdmDataSource");
215 public BeanDefinition
getHibernatePropertiesBean(DbSchemaValidation hbm2dll
) {
216 //TODO is it possible/required to build a properties bean here?
217 throw new UnsupportedOperationException("getHibernatePropertiesBean() not supported by WrappedCdmDataSource");
221 public BeanDefinition
getHibernatePropertiesBean(DbSchemaValidation hbm2dll
,
222 Boolean showSql
, Boolean formatSql
, Boolean registerSearchListener
,
223 Class
<?
extends RegionFactory
> cacheProviderClass
) {
224 //TODO is it possible/required to build a properties bean here?
225 throw new UnsupportedOperationException("getHibernatePropertiesBean() not supported by WrappedCdmDataSource");
229 public String
getFilePath() {
230 throw new UnsupportedOperationException("getFilePath() not supported by WrappedCdmDataSource");
234 public H2Mode
getMode() {
235 throw new UnsupportedOperationException("getMode() not supported by WrappedCdmDataSource");
239 public String
getUsername() {
240 //TODO maybe this can be implemented by connection meta data
241 throw new UnsupportedOperationException("getUsername() not supported by WrappedCdmDataSource");
245 public String
getPassword() {
246 throw new UnsupportedOperationException("getPassword() not supported by WrappedCdmDataSource");
250 public String
getDatabase() {
251 if(datasource
instanceof ComboPooledDataSource
) {
252 String jdbcUrl
= ((ComboPooledDataSource
)datasource
).getJdbcUrl();
254 return getDatabaseFrom(jdbcUrl
);
255 } catch (URISyntaxException e
) {
256 throw new RuntimeException(e
);
259 throw new UnsupportedOperationException("getDatabase() not implemented for " + datasource
.getClass() + " in WrappedCdmDataSource");
267 * @throws URISyntaxException
269 private String
getDatabaseFrom(String jdbcUrl
) throws URISyntaxException
{
270 DatabaseTypeEnum type
= DatabaseTypeEnum
.byConnectionString(jdbcUrl
);
274 String dbName
= type
.getDatabaseType().getDatabaseNameByConnectionString(jdbcUrl
);
280 public void setMode(H2Mode h2Mode
) {
281 throw new UnsupportedOperationException("setMode(H2Mode) not supported by WrappedCdmDataSource");
285 public void setUsername(String username
) {
286 throw new UnsupportedOperationException("setUsername(String) not supported by WrappedCdmDataSource");
290 public void setPassword(String password
) {
291 throw new UnsupportedOperationException("setPassword(String) not supported by WrappedCdmDataSource");
295 public void setDatabase(String database
) {
296 throw new UnsupportedOperationException("setDatabase(String) not supported by WrappedCdmDataSource");
300 public DatabaseTypeEnum
getDatabaseType() {
301 if (this.datasource
instanceof ICdmDataSource
){
302 return ((ICdmDataSource
)this.datasource
).getDatabaseType();
307 } catch (SQLException e1
) {
308 throw new RuntimeException("SQL Exception while trying to establish connection to datasource");
311 String driverName
= null;
312 if (connection
!= null){
313 DatabaseMetaData metaData
= null;
315 metaData
= connection
.getMetaData();
316 } catch (SQLException e
) {
317 throw new RuntimeException("SQL Exception while trying to read datasource metadata");
321 driverName
= metaData
!= null ? metaData
.getDriverName() : null;
322 } catch (SQLException e
) {
323 //throw exception at end
325 if (metaData
!= null){
326 DatabaseTypeEnum type
= DatabaseTypeEnum
.byDatabaseMetaData(metaData
);
331 throw new IllegalStateException("datasource type (MySQL, SQL Server, ...) could not be retrieved from generic datasource");
334 throw new IllegalStateException("datasource type (MySQL, SQL Server, ...) could not be retrieved from generic datasource");
338 public boolean testConnection() throws ClassNotFoundException
, SQLException
{
339 return getConnection() != null;
343 public ResultSet
executeQuery(String query
) throws SQLException
{
344 PreparedStatement a
= getConnection().prepareStatement(query
);
345 return a
.executeQuery();
349 public int executeUpdate(String sqlUpdate
) throws SQLException
{
350 PreparedStatement a
= getConnection().prepareStatement(sqlUpdate
);
351 return a
.executeUpdate();
355 public void startTransaction() {
357 Connection connection
= getConnection();
358 this.connection
= connection
;
359 connection
.setAutoCommit(false);
360 } catch (SQLException e
) {
361 throw new RuntimeException(e
);
366 public void commitTransaction() throws SQLException
{
367 getConnection().commit();
371 public void rollback() throws SQLException
{
372 getConnection().rollback();
376 public Object
getSingleValue(String query
) throws SQLException
{
377 ResultSet rs
= this.executeQuery(query
);
379 int count
= rs
.getMetaData().getColumnCount();
381 return rs
.getObject(1);
388 public DatabaseMetaData
getMetaData() {
390 return getConnection().getMetaData();
391 } catch (SQLException e
) {
392 throw new RuntimeException(e
);