Project

General

Profile

Download (12.1 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 *
3
 */
4
package eu.etaxonomy.cdm.database;
5

    
6
import java.io.PrintWriter;
7
import java.net.URI;
8
import java.net.URISyntaxException;
9
import java.sql.Connection;
10
import java.sql.DatabaseMetaData;
11
import java.sql.PreparedStatement;
12
import java.sql.ResultSet;
13
import java.sql.SQLException;
14
import java.sql.SQLFeatureNotSupportedException;
15
import java.util.Map;
16

    
17
import javax.sql.DataSource;
18

    
19
import org.apache.log4j.Logger;
20
import org.hibernate.cache.spi.RegionFactory;
21
import org.springframework.beans.factory.config.BeanDefinition;
22

    
23
import com.mchange.v2.c3p0.ComboPooledDataSource;
24

    
25
import eu.etaxonomy.cdm.config.CdmSourceException;
26
import eu.etaxonomy.cdm.model.metadata.CdmMetaData.MetaDataPropertyName;
27
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
28

    
29
/**
30
 * This class is a wrapper class to wrap an {@link javax.sql.DataSource} to an
31
 * {@link ICdmDataSource}. As the former is a very limited interface it is not possible
32
 * to implement all methods of {@link ICdmDataSource}. However, the aim is
33
 * to implement all those methods which are usually needed to work with a datasource
34
 * which represents a connection to a database such as transaction handling and
35
 * sending queries.
36
 * Those methods which are not supported by this wrapper class will throw an xxx
37
 * exception.
38
 *
39
 *
40
 * @author a.mueller
41
 */
42

    
43
//FIXME this class replicates lots of code in CdmDataSourceBase, we may want to merge it
44
//in a common helper class to avoid redundant code
45
public class WrappedCdmDataSource implements ICdmDataSource {
46
	private static final Logger logger = Logger.getLogger(WrappedCdmDataSource.class);
47

    
48

    
49
	private final DataSource datasource;
50

    
51
	private Connection connection;
52

    
53

    
54
	public WrappedCdmDataSource(DataSource datasource) {
55
		if (datasource == null){
56
			throw new NullPointerException("datasource must not be null for WrappedCdmDataSource");
57
		}
58
		this.datasource = datasource;
59
	}
60

    
61
	@Override
62
	public Connection getConnection() throws SQLException {
63
		Connection existingConnection = getExistingConnection();
64
		if (existingConnection != null){
65
			return existingConnection;
66
		}else{
67
			return datasource.getConnection();
68
		}
69
	}
70

    
71
	public Connection getExistingConnection(){
72
		return this.connection;
73
	}
74

    
75

    
76
	@Override
77
	public Connection getConnection(String username, String password) throws SQLException {
78
		Connection existingConnection = getExistingConnection();
79
		if (existingConnection != null){
80
			return existingConnection;
81
		}else{
82
			return datasource.getConnection(username, password);
83
		}
84
	}
85

    
86
	@Override
87
	public PrintWriter getLogWriter() throws SQLException {
88
		return datasource.getLogWriter();
89
	}
90

    
91
	@Override
92
	public void setLogWriter(PrintWriter out) throws SQLException {
93
		datasource.setLogWriter(out);
94
	}
95

    
96
	@Override
97
	public void setLoginTimeout(int seconds) throws SQLException {
98
		datasource.setLoginTimeout(seconds);
99
	}
100

    
101
	@Override
102
	public int getLoginTimeout() throws SQLException {
103
		return datasource.getLoginTimeout();
104
	}
105

    
106
	@Override
107
	public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
108
		return datasource.getParentLogger();
109
	}
110

    
111
	@Override
112
	public <T> T unwrap(Class<T> iface) throws SQLException {
113
		return datasource.unwrap(iface);
114
	}
115

    
116
	@Override
117
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
118
		return datasource.isWrapperFor(iface);
119
	}
120

    
121
	@Override
122
	public String getName() {
123
		throw new UnsupportedOperationException("getName() not supported by WrappedCdmDataSource");
124
	}
125

    
126
	@Override
127
	public void setName(String name) {
128
		throw new UnsupportedOperationException("setName(String) not supported by WrappedCdmDataSource");
129
	}
130

    
131
	@Override
132
	public String getServer() {
133
		//TODO we may want to use client info from connection here
134
		throw new UnsupportedOperationException("getServer() not supported by WrappedCdmDataSource");
135
	}
136

    
137
	@Override
138
	public void setServer(String server) {
139
		throw new UnsupportedOperationException("setServer() not supported by WrappedCdmDataSource");
140
	}
141

    
142
	@Override
143
	public int getPort() {
144
		//TODO we may want to use client info from connection here
145
		throw new UnsupportedOperationException("getPort() not supported by WrappedCdmDataSource");
146
	}
147

    
148
	@Override
149
	public void setPort(int port) {
150
		throw new UnsupportedOperationException("setPort(int) not supported by WrappedCdmDataSource");
151
	}
152

    
153
	@Override
154
	public NomenclaturalCode getNomenclaturalCode() {
155
		throw new UnsupportedOperationException("getNomenclaturalCode() not supported by WrappedCdmDataSource");
156
	}
157

    
158
	@Override
159
	public void setNomenclaturalCode(NomenclaturalCode nomenclaturalCode) {
160
		throw new UnsupportedOperationException("setNomenclaturalCode(nc) not supported by WrappedCdmDataSource");
161
	}
162

    
163
	@Override
164
	public String getDbSchemaVersion() throws CdmSourceException {
165
		try {
166
			return (String)getSingleValue(MetaDataPropertyName.DB_SCHEMA_VERSION.getSqlQuery());
167
		} catch (SQLException e) {
168
			throw new CdmSourceException(e.getMessage());
169
		}
170
	}
171

    
172

    
173
	@Override
174
	public boolean isDbEmpty() throws CdmSourceException {
175
		// Any CDM DB should have a schema version
176
		String dbSchemaVersion = getDbSchemaVersion();
177
		return (dbSchemaVersion == null || dbSchemaVersion.equals(""));
178
	}
179

    
180
	@Override
181
	public boolean checkConnection() throws CdmSourceException {
182
		try {
183
			return testConnection();
184
		} catch (ClassNotFoundException e) {
185
			throw new CdmSourceException(e.getMessage());
186
		} catch (SQLException e) {
187
			throw new CdmSourceException(e.getMessage());
188
		}
189
	}
190

    
191
	@Override
192
	public String getConnectionMessage() {
193
		try {
194
			Connection connection = getConnection();
195
			String message = "Connecting to datasource " + connection.getSchema() + ".";
196
			return message;
197
		} catch (SQLException e) {
198
			throw new RuntimeException(e);
199
		}
200
	}
201

    
202
	@Override
203
	public void closeOpenConnections() {
204
	    try {
205
	    	if(connection != null && !connection.isClosed()){
206
                connection.close();
207
                connection = null;
208
            }
209
        } catch (SQLException e) {
210
        	logger.error("Error closing the connection");
211
        }
212
	}
213

    
214
	@Override
215
	public Map<MetaDataPropertyName, String> getMetaDataMap() throws CdmSourceException {
216
		//TODO is it possible/required to build a meta data map here?
217
		throw new UnsupportedOperationException("getMetaDataMap() not supported by WrappedCdmDataSource");
218
	}
219

    
220
	@Override
221
	public BeanDefinition getDatasourceBean() {
222
		//TODO is it possible/required to build a datasource bean here?
223
		throw new UnsupportedOperationException("getDatasourceBean() not supported by WrappedCdmDataSource");
224
	}
225

    
226
	@Override
227
	public BeanDefinition getHibernatePropertiesBean(DbSchemaValidation hbm2dll) {
228
		//TODO is it possible/required to build a properties bean here?
229
		throw new UnsupportedOperationException("getHibernatePropertiesBean() not supported by WrappedCdmDataSource");
230
	}
231

    
232
	@Override
233
	public BeanDefinition getHibernatePropertiesBean(DbSchemaValidation hbm2dll,
234
			Boolean showSql, Boolean formatSql, Boolean registerSearchListener,
235
			Class<? extends RegionFactory> cacheProviderClass) {
236
		//TODO is it possible/required to build a properties bean here?
237
		throw new UnsupportedOperationException("getHibernatePropertiesBean() not supported by WrappedCdmDataSource");
238
	}
239

    
240
	@Override
241
	public String getFilePath() {
242
		throw new UnsupportedOperationException("getFilePath() not supported by WrappedCdmDataSource");
243
	}
244

    
245
	@Override
246
	public H2Mode getMode() {
247
		throw new UnsupportedOperationException("getMode() not supported by WrappedCdmDataSource");
248
	}
249

    
250
	@Override
251
	public String getUsername() {
252
		//TODO maybe this can be implemented by connection meta data
253
		throw new UnsupportedOperationException("getUsername() not supported by WrappedCdmDataSource");
254
	}
255

    
256
	@Override
257
	public String getPassword() {
258
		throw new UnsupportedOperationException("getPassword() not supported by WrappedCdmDataSource");
259
	}
260

    
261
	@Override
262
	public String getDatabase() {
263
	    if(datasource instanceof ComboPooledDataSource) {
264
	      String jdbcUrl = ((ComboPooledDataSource)datasource).getJdbcUrl();
265
	        try {
266
                return getDatabaseFrom(jdbcUrl);
267
            } catch (URISyntaxException e) {
268
                throw new RuntimeException(e);
269
            }
270
	    } else {
271
	        throw new UnsupportedOperationException("getDatabase() not implemented for " + datasource.getClass() + " in WrappedCdmDataSource");
272
	    }
273
	}
274

    
275
    /**
276
     * @param jdbcUrl
277
     * @return
278
     * @throws URISyntaxException
279
     */
280
    private String getDatabaseFrom(String jdbcUrl) throws URISyntaxException {
281
        URI url = new URI(jdbcUrl.substring(5));
282
        return url.getPath().substring(1);
283
    }
284

    
285
	@Override
286
	public void setMode(H2Mode h2Mode) {
287
		throw new UnsupportedOperationException("setMode(H2Mode) not supported by WrappedCdmDataSource");
288
	}
289

    
290
	@Override
291
	public void setUsername(String username) {
292
		throw new UnsupportedOperationException("setUsername(String) not supported by WrappedCdmDataSource");
293
	}
294

    
295
	@Override
296
	public void setPassword(String password) {
297
		throw new UnsupportedOperationException("setPassword(String) not supported by WrappedCdmDataSource");
298
	}
299

    
300
	@Override
301
	public void setDatabase(String database) {
302
		throw new UnsupportedOperationException("setDatabase(String) not supported by WrappedCdmDataSource");
303
	}
304

    
305
	@Override
306
	public DatabaseTypeEnum getDatabaseType() {
307
	    if (this.datasource instanceof ICdmDataSource){
308
	        return ((ICdmDataSource)this.datasource).getDatabaseType();
309
	    }
310

    
311
	    try {
312
            getConnection();
313
        } catch (SQLException e1) {
314
            throw new RuntimeException("SQL Exception while trying to establish connection to datasource");
315
        }
316

    
317
	    String driverName = null;
318
        if (connection != null){
319
            DatabaseMetaData metaData = null;
320
            try {
321
                metaData = connection.getMetaData();
322
            } catch (SQLException e) {
323
                throw new RuntimeException("SQL Exception while trying to read datasource metadata");
324
            }
325

    
326
            try {
327
                driverName = metaData != null ? metaData.getDriverName() : null;
328
            } catch (SQLException e) {
329
                //throw exception at end
330
            }
331
            if (metaData != null){
332
                DatabaseTypeEnum type = DatabaseTypeEnum.byDatabaseMetaData(metaData);
333
                if (type != null){
334
                    return type;
335
                }
336
            }
337
            throw new IllegalStateException("datasource type (MySQL, SQL Server, ...) could not be retrieved from generic datasource");
338

    
339
        }
340
		throw new IllegalStateException("datasource type (MySQL, SQL Server, ...) could not be retrieved from generic datasource");
341
	}
342

    
343
	@Override
344
	public boolean testConnection() throws ClassNotFoundException, SQLException {
345
		return getConnection() != null;
346
	}
347

    
348
	@Override
349
	public ResultSet executeQuery(String query) throws SQLException {
350
		PreparedStatement a = getConnection().prepareStatement(query);
351
		return a.executeQuery();
352
	}
353

    
354
	@Override
355
	public int executeUpdate(String sqlUpdate) throws SQLException {
356
		PreparedStatement a = getConnection().prepareStatement(sqlUpdate);
357
		return a.executeUpdate();
358
	}
359

    
360
	@Override
361
	public void startTransaction() {
362
		try {
363
            Connection connection = getConnection();
364
            this.connection = connection;
365
            connection.setAutoCommit(false);
366
		} catch (SQLException e) {
367
			throw new RuntimeException(e);
368
		}
369
	}
370

    
371
	@Override
372
	public void commitTransaction() throws SQLException {
373
		getConnection().commit();
374
	}
375

    
376
	@Override
377
	public void rollback() throws SQLException {
378
		getConnection().rollback();
379
	}
380

    
381
	@Override
382
	public Object getSingleValue(String query) throws SQLException {
383
		ResultSet rs = this.executeQuery(query);
384
		if (rs.next()){
385
			int count = rs.getMetaData().getColumnCount();
386
			if (count > 0){
387
				return rs.getObject(1);
388
			}
389
		}
390
		return null;
391
	}
392

    
393
	@Override
394
	public DatabaseMetaData getMetaData() {
395
		try {
396
			return getConnection().getMetaData();
397
		} catch (SQLException e) {
398
			throw new RuntimeException(e);
399
		}
400
	}
401
}
(20-20/20)