Project

General

Profile

Download (8.82 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2007 EDIT
4
* European Distributed Institute of Taxonomy 
5
* http://www.e-taxonomy.eu
6
* 
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.
9
*/
10

    
11
package eu.etaxonomy.cdm.api.service;
12

    
13
import java.sql.Connection;
14
import java.sql.ResultSet;
15
import java.sql.SQLException;
16
import java.sql.Statement;
17

    
18
import javax.sql.DataSource;
19

    
20
import org.apache.log4j.Logger;
21
import org.hibernate.SessionFactory;
22
import org.springframework.beans.BeansException;
23
import org.springframework.beans.factory.annotation.Autowired;
24
import org.springframework.context.ApplicationContext;
25
import org.springframework.context.ApplicationContextAware;
26
import org.springframework.jdbc.datasource.AbstractDriverBasedDataSource;
27
import org.springframework.orm.hibernate4.SessionFactoryUtils;
28
import org.springframework.stereotype.Service;
29
import org.springframework.transaction.annotation.Transactional;
30

    
31
import eu.etaxonomy.cdm.api.application.CdmApplicationController;
32
import eu.etaxonomy.cdm.config.CdmPersistentSourceUtils;
33
import eu.etaxonomy.cdm.config.CdmSourceException;
34
import eu.etaxonomy.cdm.database.CdmDataSource;
35
import eu.etaxonomy.cdm.database.CdmPersistentDataSource;
36
import eu.etaxonomy.cdm.database.DataSourceNotFoundException;
37
import eu.etaxonomy.cdm.database.DatabaseTypeEnum;
38
import eu.etaxonomy.cdm.database.H2Mode;
39
import eu.etaxonomy.cdm.database.ICdmDataSource;
40
import eu.etaxonomy.cdm.model.common.init.TermNotFoundException;
41
import eu.etaxonomy.cdm.model.metadata.CdmMetaData.MetaDataPropertyName;
42
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
43

    
44

    
45

    
46
/**
47
 * Implementation of service which provides functionality to directly access database 
48
 * related information.
49
 * 
50
 * @author a.mueller
51
 *
52
 */
53
@Service
54
@Transactional(readOnly = true)
55
public class DatabaseServiceHibernateImpl  implements IDatabaseService, ApplicationContextAware {
56
	private static final Logger logger = Logger.getLogger(DatabaseServiceHibernateImpl.class);
57
	
58
	private static final String TMP_DATASOURCE = "tmp"; 
59
	
60
	@Autowired
61
	private SessionFactory factory;
62
	
63
	@Autowired
64
	protected ApplicationContext appContext;
65
	
66
	private CdmApplicationController application;
67
	
68
	
69
	/* (non-Javadoc)
70
	 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#setApplicationController(eu.etaxonomy.cdm.api.application.CdmApplicationController)
71
	 */
72
	public void setApplicationController(CdmApplicationController cdmApplicationController){
73
		this.application = cdmApplicationController;
74
	}
75
	
76
	
77
	/* (non-Javadoc)
78
	 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#connectToDatasource(eu.etaxonomy.cdm.database.CdmDataSource)
79
	 */
80
	public boolean connectToDatasource(CdmPersistentDataSource dataSource) throws TermNotFoundException{
81
		this.application.changeDataSource(dataSource);
82
		logger.debug("DataSource changed to " + dataSource.getName());
83
		return true;
84
	}
85
	
86
	/* (non-Javadoc)
87
	 * @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)
88
	 */
89
	public boolean connectToDatabase(DatabaseTypeEnum databaseTypeEnum, String server,
90
			String database, String username, String password, int port, String filePath, H2Mode mode, NomenclaturalCode code) throws TermNotFoundException  {
91
		ICdmDataSource dataSource = CdmDataSource.NewInstance(databaseTypeEnum, server, database, port, username, password, code);
92
		CdmPersistentDataSource tmpDataSource =  saveDataSource(TMP_DATASOURCE, dataSource);
93
		boolean result = connectToDatasource(tmpDataSource);
94
		CdmPersistentSourceUtils.delete(tmpDataSource);
95
		return result;
96
	}
97

    
98

    
99
	/* (non-Javadoc)
100
	 * @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)
101
	 */
102
	public boolean connectToDatabase(DatabaseTypeEnum databaseTypeEnum, String server,
103
			String database, String username, String password)  throws TermNotFoundException {
104
		return connectToDatabase(databaseTypeEnum, server, database, username, password, databaseTypeEnum.getDefaultPort(), null, null, null) ;
105
	}
106
	
107
	/* (non-Javadoc)
108
	 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#saveDataSource(java.lang.String, eu.etaxonomy.cdm.database.ICdmDataSource)
109
	 */
110
	public CdmPersistentDataSource saveDataSource(String strDataSourceName,
111
			ICdmDataSource dataSource) {
112
		return CdmPersistentDataSource.save(strDataSourceName, dataSource);
113
	}
114
	
115
	/* (non-Javadoc)
116
	 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#updateDataSource(java.lang.String, eu.etaxonomy.cdm.database.CdmPersistentDataSource)
117
	 */
118
	public CdmPersistentDataSource updateDataSource(String strDataSourceName,
119
			CdmPersistentDataSource dataSource) throws DataSourceNotFoundException {
120
		return CdmPersistentDataSource.update(strDataSourceName, dataSource);
121
	}
122

    
123
	/* (non-Javadoc)
124
	 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#getUrl()
125
	 */
126
	public String getUrl() {
127
		return getDataSource().getUrl();
128
	}
129

    
130
	/* (non-Javadoc)
131
	 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#getUsername()
132
	 */
133
	public String getUsername() {
134
		return getDataSource().getUsername();
135
	}
136

    
137
	/**
138
	 * Returns the AbstractDriverBasedDataSource from hibernate,
139
	 * generalized in order to also allow using SimpleDriverDataSource.
140
	 * 
141
	 * @return the AbstractDriverBasedDataSource from the hibernate layer 
142
	 */
143
	private AbstractDriverBasedDataSource getDataSource(){
144
		AbstractDriverBasedDataSource ds = (AbstractDriverBasedDataSource)SessionFactoryUtils.getDataSource(factory);
145
		return ds;
146
	}
147

    
148

    
149
	/* (non-Javadoc)
150
	 * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
151
	 */
152
	public void setApplicationContext(ApplicationContext applicationContext)
153
			throws BeansException {
154
		this.appContext = applicationContext;
155
	}
156
	
157
	/* (non-Javadoc)
158
	 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#getDbSchemaVersion()
159
	 */
160
	@Override
161
	public  String getDbSchemaVersion() throws CdmSourceException  {		
162
		try {
163
			return (String)getSingleValue(MetaDataPropertyName.DB_SCHEMA_VERSION.getSqlQuery());
164
		} catch (SQLException e) {
165
			throw new CdmSourceException(e.getMessage());	
166
		}
167
	}
168
	
169
    
170
	/* (non-Javadoc)
171
	 * @see eu.etaxonomy.cdm.api.service.IDatabaseService#isDbEmpty()
172
	 */
173
	@Override
174
	public boolean isDbEmpty() throws CdmSourceException {
175
		// Any CDM DB should have a schema version
176
		String dbSchemaVersion = (String) getDbSchemaVersion();		
177
		return (dbSchemaVersion == null || dbSchemaVersion.equals(""));
178
	}
179
	
180
    /**
181
     * Execute a SQL query which returns a single value
182
     * FIXME:Remoting maybe not a smart idea to have this method here 
183
     * since private methods can also be accessed via reflection, which
184
     * could be problematic specially for the case of remoting.
185
     * 
186
     * @param query , which returns a single value
187
     * @return
188
     * @throws SQLException
189
     */
190
    private Object getSingleValue(String query) throws SQLException{
191
        String queryString = query == null? "(null)": query;
192
        ResultSet resultSet = executeQuery(query);
193
        if (resultSet == null || resultSet.next() == false){
194
            logger.info("No record returned for query " +  queryString);
195
            return null;
196
        }
197
        if (resultSet.getMetaData().getColumnCount() != 1){
198
            logger.info("More than one column selected in query" +  queryString);
199
            //first value will be taken
200
        }
201
        Object object = resultSet.getObject(1);
202
        if (resultSet.next()){
203
            logger.info("Multiple results for query " +  queryString);
204
            //first row will be taken
205
        }
206
        return object;
207
    }
208
    
209
    /**
210
     * Executes a query and returns the ResultSet.
211
     * FIXME:Remoting maybe not a smart idea to have this method here 
212
     * since private methods can also be accessed via reflection, which
213
     * could be problematic specially for the case of remoting.
214
     *      
215
     * @return ResultSet for the query.
216
     * @throws SQLException
217
     */
218
    
219
    private ResultSet executeQuery (String query) throws SQLException {
220

    
221
        ResultSet resultSet;
222

    
223
        if (query == null){
224
            return null;
225
        }
226
        
227
        Connection connection = SessionFactoryUtils.getDataSource(factory).getConnection();
228
        if (connection != null){
229
            Statement statement = connection.createStatement();
230
            resultSet = statement.executeQuery(query);
231
        }else{
232
            throw new RuntimeException("Could not establish connection to database");
233
        }
234
        return resultSet;
235

    
236
    }
237
}
(10-10/84)