3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
11 package eu
.etaxonomy
.cdm
.api
.service
;
13 import java
.sql
.Connection
;
14 import java
.sql
.ResultSet
;
15 import java
.sql
.SQLException
;
16 import java
.sql
.Statement
;
17 import java
.util
.HashMap
;
20 import javax
.sql
.DataSource
;
22 import org
.apache
.log4j
.Logger
;
23 import org
.hibernate
.SessionFactory
;
24 import org
.springframework
.beans
.BeansException
;
25 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
26 import org
.springframework
.context
.ApplicationContext
;
27 import org
.springframework
.context
.ApplicationContextAware
;
28 import org
.springframework
.jdbc
.datasource
.AbstractDriverBasedDataSource
;
29 import org
.springframework
.orm
.hibernate4
.SessionFactoryUtils
;
30 import org
.springframework
.stereotype
.Service
;
31 import org
.springframework
.transaction
.annotation
.Transactional
;
33 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationController
;
34 import eu
.etaxonomy
.cdm
.config
.CdmPersistentSourceUtils
;
35 import eu
.etaxonomy
.cdm
.config
.CdmSourceException
;
36 import eu
.etaxonomy
.cdm
.database
.CdmDataSource
;
37 import eu
.etaxonomy
.cdm
.database
.CdmPersistentDataSource
;
38 import eu
.etaxonomy
.cdm
.database
.DataSourceNotFoundException
;
39 import eu
.etaxonomy
.cdm
.database
.DatabaseTypeEnum
;
40 import eu
.etaxonomy
.cdm
.database
.H2Mode
;
41 import eu
.etaxonomy
.cdm
.database
.ICdmDataSource
;
42 import eu
.etaxonomy
.cdm
.model
.common
.init
.TermNotFoundException
;
43 import eu
.etaxonomy
.cdm
.model
.metadata
.CdmMetaData
.MetaDataPropertyName
;
44 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
49 * Implementation of service which provides functionality to directly access database
50 * related information.
56 @Transactional(readOnly
= true)
57 public class DatabaseServiceHibernateImpl
implements IDatabaseService
, ApplicationContextAware
{
58 private static final Logger logger
= Logger
.getLogger(DatabaseServiceHibernateImpl
.class);
60 private static final String TMP_DATASOURCE
= "tmp";
63 private SessionFactory factory
;
66 protected ApplicationContext appContext
;
68 private CdmApplicationController application
;
72 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#setApplicationController(eu.etaxonomy.cdm.api.application.CdmApplicationController)
74 public void setApplicationController(CdmApplicationController cdmApplicationController
){
75 this.application
= cdmApplicationController
;
80 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#connectToDatasource(eu.etaxonomy.cdm.database.CdmDataSource)
82 public boolean connectToDatasource(CdmPersistentDataSource dataSource
) throws TermNotFoundException
{
83 this.application
.changeDataSource(dataSource
);
84 logger
.debug("DataSource changed to " + dataSource
.getName());
89 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#connectToDatabase(eu.etaxonomy.cdm.database.DatabaseTypeEnum, java.lang.String, java.lang.String, java.lang.String, java.lang.String, int)
91 public boolean connectToDatabase(DatabaseTypeEnum databaseTypeEnum
, String server
,
92 String database
, String username
, String password
, int port
, String filePath
, H2Mode mode
, NomenclaturalCode code
) throws TermNotFoundException
{
93 ICdmDataSource dataSource
= CdmDataSource
.NewInstance(databaseTypeEnum
, server
, database
, port
, username
, password
, code
);
94 CdmPersistentDataSource tmpDataSource
= saveDataSource(TMP_DATASOURCE
, dataSource
);
95 boolean result
= connectToDatasource(tmpDataSource
);
96 CdmPersistentSourceUtils
.delete(tmpDataSource
);
102 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#connectToDatabase(eu.etaxonomy.cdm.database.DatabaseTypeEnum, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
104 public boolean connectToDatabase(DatabaseTypeEnum databaseTypeEnum
, String server
,
105 String database
, String username
, String password
) throws TermNotFoundException
{
106 return connectToDatabase(databaseTypeEnum
, server
, database
, username
, password
, databaseTypeEnum
.getDefaultPort(), null, null, null) ;
110 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#saveDataSource(java.lang.String, eu.etaxonomy.cdm.database.ICdmDataSource)
112 public CdmPersistentDataSource
saveDataSource(String strDataSourceName
,
113 ICdmDataSource dataSource
) {
114 return CdmPersistentDataSource
.save(strDataSourceName
, dataSource
);
118 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#updateDataSource(java.lang.String, eu.etaxonomy.cdm.database.CdmPersistentDataSource)
120 public CdmPersistentDataSource
updateDataSource(String strDataSourceName
,
121 CdmPersistentDataSource dataSource
) throws DataSourceNotFoundException
{
122 return CdmPersistentDataSource
.update(strDataSourceName
, dataSource
);
126 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#getUrl()
128 public String
getUrl() {
129 return getDataSource().getUrl();
133 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#getUsername()
135 public String
getUsername() {
136 return getDataSource().getUsername();
140 * Returns the AbstractDriverBasedDataSource from hibernate,
141 * generalized in order to also allow using SimpleDriverDataSource.
143 * @return the AbstractDriverBasedDataSource from the hibernate layer
145 private AbstractDriverBasedDataSource
getDataSource(){
146 AbstractDriverBasedDataSource ds
= (AbstractDriverBasedDataSource
)SessionFactoryUtils
.getDataSource(factory
);
152 * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
154 public void setApplicationContext(ApplicationContext applicationContext
)
155 throws BeansException
{
156 this.appContext
= applicationContext
;
162 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#getDbSchemaVersion()
165 public String
getDbSchemaVersion() throws CdmSourceException
{
167 return (String
)getSingleValue(MetaDataPropertyName
.DB_SCHEMA_VERSION
.getSqlQuery());
168 } catch (SQLException e
) {
169 throw new CdmSourceException(e
.getMessage());
175 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#isDbEmpty()
178 public boolean isDbEmpty() throws CdmSourceException
{
179 // Any CDM DB should have a schema version
180 String dbSchemaVersion
= (String
) getDbSchemaVersion();
181 return (dbSchemaVersion
== null || dbSchemaVersion
.equals(""));
185 * Execute a SQL query which returns a single value
186 * FIXME:Remoting maybe not a smart idea to have this method here
187 * since private methods can also be accessed via reflection, which
188 * could be problematic specially for the case of remoting.
190 * @param query , which returns a single value
192 * @throws SQLException
194 private Object
getSingleValue(String query
) throws SQLException
{
195 String queryString
= query
== null?
"(null)": query
;
196 ResultSet resultSet
= executeQuery(query
);
197 if (resultSet
== null || resultSet
.next() == false){
198 logger
.info("No record returned for query " + queryString
);
201 if (resultSet
.getMetaData().getColumnCount() != 1){
202 logger
.info("More than one column selected in query" + queryString
);
203 //first value will be taken
205 Object object
= resultSet
.getObject(1);
206 if (resultSet
.next()){
207 logger
.info("Multiple results for query " + queryString
);
208 //first row will be taken
214 * Executes a query and returns the ResultSet.
215 * FIXME:Remoting maybe not a smart idea to have this method here
216 * since private methods can also be accessed via reflection, which
217 * could be problematic specially for the case of remoting.
219 * @return ResultSet for the query.
220 * @throws SQLException
223 private ResultSet
executeQuery (String query
) throws SQLException
{
231 Connection connection
= SessionFactoryUtils
.getDataSource(factory
).getConnection();
232 if (connection
!= null){
233 Statement statement
= connection
.createStatement();
234 resultSet
= statement
.executeQuery(query
);
236 throw new RuntimeException("Could not establish connection to database");
244 public Map
<MetaDataPropertyName
, String
> getCdmMetadataMap() throws CdmSourceException
{
245 Map
<MetaDataPropertyName
, String
> cdmMetaDataMap
= new HashMap
<MetaDataPropertyName
, String
>();
247 for(MetaDataPropertyName mdpn
: MetaDataPropertyName
.values()){
250 value
= (String
)getSingleValue(mdpn
.getSqlQuery());
251 } catch (SQLException e
) {
252 throw new CdmSourceException(e
.getMessage());
255 cdmMetaDataMap
.put(mdpn
, value
);
258 return cdmMetaDataMap
;