2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License VeresultSetion 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.database
;
12 import java
.io
.PrintWriter
;
13 import java
.sql
.Connection
;
14 import java
.sql
.DatabaseMetaData
;
15 import java
.sql
.DriverManager
;
16 import java
.sql
.ResultSet
;
17 import java
.sql
.SQLException
;
18 import java
.sql
.Statement
;
19 import java
.util
.HashMap
;
21 import java
.util
.Properties
;
23 import org
.apache
.logging
.log4j
.LogManager
;
24 import org
.apache
.logging
.log4j
.Logger
;
25 import org
.hibernate
.cache
.spi
.RegionFactory
;
26 import org
.hibernate
.envers
.boot
.internal
.EnversIntegrator
;
27 import org
.springframework
.beans
.MutablePropertyValues
;
28 import org
.springframework
.beans
.factory
.config
.PropertiesFactoryBean
;
29 import org
.springframework
.beans
.factory
.support
.AbstractBeanDefinition
;
30 import org
.springframework
.beans
.factory
.support
.RootBeanDefinition
;
32 import eu
.etaxonomy
.cdm
.config
.CdmSource
;
33 import eu
.etaxonomy
.cdm
.config
.CdmSourceException
;
34 import eu
.etaxonomy
.cdm
.database
.types
.IDatabaseType
;
35 import eu
.etaxonomy
.cdm
.model
.metadata
.CdmMetaDataPropertyName
;
36 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.HibernateConfiguration
;
42 public abstract class CdmDataSourceBase
extends CdmSource
implements ICdmDataSource
{
44 private static final Logger logger
= LogManager
.getLogger();
47 // private static final int TIMEOUT = 10;
48 private Connection connection
;
52 public Connection
getConnection() throws SQLException
{
53 return getConnection(getUsername(), getPassword());
58 public Connection
getConnection(String username
, String password
) throws SQLException
{
60 if(connection
!= null){
61 boolean isValid
= true;
63 // isValid = connection.isValid(TIMEOUT);
64 // } catch (java.lang.AbstractMethodError e){
65 // logger.error("Problems with Connection.isValid method\n" + "Exception: " + e.toString());
71 IDatabaseType dbType
= getDatabaseType().getDatabaseType();
72 String classString
= dbType
.getClassString();
73 Class
.forName(classString
);
74 String mUrl
= dbType
.getConnectionString(this);
75 Connection connection
= DriverManager
.getConnection(mUrl
, username
, password
);
78 } catch (ClassNotFoundException e
) {
79 throw new RuntimeException("Database driver class could not be loaded\n" + "Exception: " + e
.toString(),e
);
80 } catch(SQLException e
) {
81 throw new RuntimeException("Problems with database connection\n" + "Exception: " + e
.toString(), e
);
87 public boolean testConnection() throws ClassNotFoundException
, SQLException
{
89 IDatabaseType dbType
= getDatabaseType().getDatabaseType();
90 String classString
= dbType
.getClassString();
91 Class
.forName(classString
);
92 String mUrl
= dbType
.getConnectionString(this);
93 if(logger
.isDebugEnabled()){
94 logger
.debug("testConnection() : " + mUrl
);
97 if(logger
.isDebugEnabled()){
98 logger
.debug("testConnection() : " + mUrl
+ " : service is available");
100 // try to connect to the database server
101 Connection connection
= DriverManager
.getConnection(mUrl
, getUsername(), getPassword());
102 if (connection
!= null){
103 if(logger
.isDebugEnabled()){
104 logger
.debug("testConnection() : " + mUrl
+ " : jdbc connect successful");
109 if(logger
.isDebugEnabled()){
110 logger
.debug("testConnection() : " + mUrl
+ " : FAIL");
116 public boolean checkConnection() throws CdmSourceException
{
118 return testConnection();
119 } catch (ClassNotFoundException e
) {
120 throw new CdmSourceException(e
.getMessage());
121 } catch (SQLException e
) {
122 throw new CdmSourceException(e
.getMessage());
127 public String
getConnectionMessage() {
129 if (getDatabaseType().equals(DatabaseTypeEnum
.H2
)) {
130 message
= " local CDM Store ";
132 message
= " CDM Community Store ";
134 message
+= "'" + getName() + "'";
136 message
= "Connecting to" + message
+ ".";
142 public Object
getSingleValue(String query
) throws SQLException
{
143 String queryString
= query
== null?
"(null)": query
;
144 ResultSet resultSet
= executeQuery(query
);
145 if (resultSet
== null || resultSet
.next() == false){
146 logger
.info("No record returned for query " + queryString
);
149 if (resultSet
.getMetaData().getColumnCount() != 1){
150 logger
.info("More than one column selected in query" + queryString
);
151 //first value will be taken
153 Object object
= resultSet
.getObject(1);
154 if (resultSet
.next()){
155 logger
.info("Multiple results for query " + queryString
);
156 //first row will be taken
162 public String
getDbSchemaVersion() throws CdmSourceException
{
164 return (String
)getSingleValue(CdmMetaDataPropertyName
.DB_SCHEMA_VERSION
.getSqlQuery());
165 } catch (SQLException e
) {
167 return (String
)getSingleValue(CdmMetaDataPropertyName
.DB_SCHEMA_VERSION
.getSqlQueryOld());
168 } catch (SQLException e1
) {
169 throw new CdmSourceException(e1
.getMessage());
175 public boolean isDbEmpty() throws CdmSourceException
{
176 // Any CDM DB should have a schema version
177 String dbSchemaVersion
= getDbSchemaVersion();
179 return (dbSchemaVersion
== null || dbSchemaVersion
.equals(""));
182 * Executes a query and returns the ResultSet.
183 * @return ResultSet for the query.
184 * @throws SQLException
187 public ResultSet
executeQuery (String query
) throws SQLException
{
194 Connection connection
= getConnection();
195 if (connection
!= null){
196 Statement statement
= connection
.createStatement();
197 resultSet
= statement
.executeQuery(query
);
199 throw new RuntimeException("Could not establish connection to database");
206 public int executeUpdate (String sqlUpdate
) throws SQLException
{
209 Connection connection
= null;
211 if (sqlUpdate
== null){
214 connection
= getConnection();
215 Statement statement
= connection
.createStatement();
216 result
= statement
.executeUpdate(sqlUpdate
);
218 } catch(SQLException e
) {
220 if (connection
!= null && ! connection
.getAutoCommit()){
221 connection
.rollback();
223 }catch (SQLException ex
){
224 //do nothing - maybe throw RuntimeException in future
225 throw new RuntimeException(ex
);
227 logger
.error("Problems when executing update\n " + sqlUpdate
+ " \n" + "Exception: " + e
);
233 public void startTransaction() {
235 Connection connection
= getConnection();
236 this.connection
= connection
;
237 connection
.setAutoCommit(false);
239 } catch(SQLException e
) {
240 logger
.error("Problems when starting transaction \n" + "Exception: " + e
);
246 public void commitTransaction() throws SQLException
{
248 Connection connection
= getConnection();
250 } catch(SQLException e
) {
251 logger
.error("Problems when commiting transaction \n" + "Exception: " + e
);
257 public void rollback() throws SQLException
{
259 Connection connection
= getConnection();
260 connection
.rollback();
261 } catch(SQLException e
) {
262 logger
.error("Problems when rolling back transaction \n" + "Exception: " + e
);
269 public DatabaseMetaData
getMetaData() {
270 Connection connection
= null;
272 connection
= getConnection();
273 return connection
.getMetaData();
274 } catch (SQLException e
) {
275 logger
.error("Could not get metadata for datasource", e
);
281 public void closeOpenConnections() {
283 if(connection
!= null && !connection
.isClosed()){
287 } catch (SQLException e
) {
288 logger
.error("Error closing the connection");
294 public Map
<CdmMetaDataPropertyName
, String
> getMetaDataMap() throws CdmSourceException
{
295 Map
<CdmMetaDataPropertyName
, String
> cdmMetaDataMap
= new HashMap
<>();
297 for(CdmMetaDataPropertyName mdpn
: CdmMetaDataPropertyName
.values()) {
300 value
= (String
)getSingleValue(mdpn
.getSqlQuery());
301 } catch (SQLException e1
) {
303 value
= (String
)getSingleValue(mdpn
.getSqlQueryOld());
304 } catch (SQLException e
) {
305 throw new CdmSourceException(this.toString(), e
.getMessage());
309 cdmMetaDataMap
.put(mdpn
, value
);
312 return cdmMetaDataMap
;
315 // ************ javax.sql.DataSource base interfaces ********************/
319 public PrintWriter
getLogWriter() throws SQLException
{
320 //implementations copied from org.springframework.jdbc.datasource.AbstractDataSource;
321 throw new UnsupportedOperationException("getLogWriter");
326 public void setLogWriter(PrintWriter out
) throws SQLException
{
327 //implementations copied from org.springframework.jdbc.datasource.AbstractDataSource;
328 throw new UnsupportedOperationException("setLogWriter");
333 public void setLoginTimeout(int seconds
) throws SQLException
{
334 //implementations copied from org.springframework.jdbc.datasource.AbstractDataSource;
335 throw new UnsupportedOperationException("setLoginTimeout");
340 public int getLoginTimeout() throws SQLException
{
341 //implementations copied from org.springframework.jdbc.datasource.AbstractDataSource;
347 * This is a preliminary implementation to be compliant with
348 * java.sql.Datasource (1.6). It may not be fully working.
349 * Please let the developers know if this doesn't work.
352 //---------------------------------------------------------------------
353 // Implementation of JDBC 4.0's Wrapper interface
354 //---------------------------------------------------------------------
357 @SuppressWarnings("unchecked")
358 public <T
> T
unwrap(Class
<T
> iface
) throws SQLException
{
359 if (iface
.isInstance(this)) {
362 throw new SQLException("DataSource of type [" + getClass().getName() +
363 "] cannot be unwrapped as [" + iface
.getName() + "]");
367 public boolean isWrapperFor(Class
<?
> iface
) throws SQLException
{
368 return iface
.isInstance(this);
372 //---------------------------------------------------------------------
373 // Implementation of JDBC 4.1's getParentLogger method
374 // Required in Java >=7.x
375 // must not have the @Override annotation for compatibility with
377 //---------------------------------------------------------------------
379 public java
.util
.logging
.Logger
getParentLogger() {
380 //copied from org.springframework.jdbc.datasource.AbstractDataSource, not checked if this is correct
381 return java
.util
.logging
.Logger
.getLogger(java
.util
.logging
.Logger
.GLOBAL_LOGGER_NAME
);
384 //********************* Base methods for CdmDataSource and CdmPersistentDatasource
386 protected AbstractBeanDefinition
makeHibernatePropertiesBean(DatabaseTypeEnum dbType
,
387 DbSchemaValidation hbm2dll
, boolean showSql
,
388 boolean formatSql
, boolean registerAuditing
, boolean registerSearchListener
,
389 Class
<?
extends RegionFactory
> cacheProviderClass
,
390 String byteCodeProvider
) {
392 AbstractBeanDefinition bd
= new RootBeanDefinition(PropertiesFactoryBean
.class);
393 MutablePropertyValues hibernateProps
= new MutablePropertyValues();
395 Properties props
= new Properties();
396 props
.setProperty("hibernate.hbm2ddl.auto", hbm2dll
.toString());
397 props
.setProperty("hibernate.dialect", dbType
.getHibernateDialectCanonicalName());
398 // OLD:props.setProperty("hibernate.cache.provider_class", cacheProviderClass.getName());
399 props
.setProperty(HibernateConfiguration
.CACHE_PROVIDER_CLASS
, cacheProviderClass
.getName());
400 props
.setProperty(HibernateConfiguration
.SHOW_SQL
, String
.valueOf(showSql
));
401 props
.setProperty(HibernateConfiguration
.FORMAT_SQL
, String
.valueOf(formatSql
));
402 props
.setProperty(HibernateConfiguration
.REGISTER_SEARCH
, String
.valueOf(registerSearchListener
));
403 props
.setProperty(EnversIntegrator
.AUTO_REGISTER
, String
.valueOf(registerAuditing
));
404 props
.setProperty(HibernateConfiguration
.BYTECODE_PROVIDER
, byteCodeProvider
);
406 hibernateProps
.add("properties",props
);
407 bd
.setPropertyValues(hibernateProps
);