Project

General

Profile

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

    
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;
14
import java.util.Map;
15

    
16
import javax.sql.DataSource;
17

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

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

    
24
import eu.etaxonomy.cdm.config.CdmSourceException;
25
import eu.etaxonomy.cdm.model.metadata.CdmMetaDataPropertyName;
26

    
27
/**
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
33
 * sending queries.
34
 * Those methods which are not supported by this wrapper class will throw an xxx
35
 * exception.
36
 *
37
 *
38
 * @author a.mueller
39
 */
40

    
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);
45

    
46

    
47
	private final DataSource datasource;
48

    
49
	private Connection connection;
50

    
51

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

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

    
69
	public Connection getExistingConnection(){
70
		return this.connection;
71
	}
72

    
73

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

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

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

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

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

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

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

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

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

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

    
129
	@Override
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");
133
	}
134

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

    
140
	@Override
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");
144
	}
145

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

    
151
	@Override
152
	public String getDbSchemaVersion() throws CdmSourceException {
153
		try {
154
			return (String)getSingleValue(CdmMetaDataPropertyName.DB_SCHEMA_VERSION.getSqlQuery());
155
		} catch (SQLException e1) {
156
		    try {
157
	            return (String)getSingleValue(CdmMetaDataPropertyName.DB_SCHEMA_VERSION.getSqlQueryOld());
158
	        } catch (SQLException e) {
159
	            throw new CdmSourceException(e.getMessage());
160
	        }
161
		}
162
	}
163

    
164

    
165
	@Override
166
	public boolean isDbEmpty() throws CdmSourceException {
167
		// Any CDM DB should have a schema version
168
		String dbSchemaVersion = getDbSchemaVersion();
169
		return (dbSchemaVersion == null || dbSchemaVersion.equals(""));
170
	}
171

    
172
	@Override
173
	public boolean checkConnection() throws CdmSourceException {
174
		try {
175
			return testConnection();
176
		} catch (ClassNotFoundException e) {
177
			throw new CdmSourceException(e.getMessage());
178
		} catch (SQLException e) {
179
			throw new CdmSourceException(e.getMessage());
180
		}
181
	}
182

    
183
	@Override
184
	public String getConnectionMessage() {
185
		try {
186
			Connection connection = getConnection();
187
			String message = "Connecting to datasource " + connection.getSchema() + ".";
188
			return message;
189
		} catch (SQLException e) {
190
			throw new RuntimeException(e);
191
		}
192
	}
193

    
194
	@Override
195
	public void closeOpenConnections() {
196
	    try {
197
	    	if(connection != null && !connection.isClosed()){
198
                connection.close();
199
                connection = null;
200
            }
201
        } catch (SQLException e) {
202
        	logger.error("Error closing the connection");
203
        }
204
	}
205

    
206
	@Override
207
	public Map<CdmMetaDataPropertyName, String> getMetaDataMap() throws CdmSourceException {
208
		//TODO is it possible/required to build a meta data map here?
209
		throw new UnsupportedOperationException("getMetaDataMap() not supported by WrappedCdmDataSource");
210
	}
211

    
212
	@Override
213
	public BeanDefinition getDatasourceBean() {
214
		//TODO is it possible/required to build a datasource bean here?
215
		throw new UnsupportedOperationException("getDatasourceBean() not supported by WrappedCdmDataSource");
216
	}
217

    
218
	@Override
219
	public BeanDefinition getHibernatePropertiesBean(DbSchemaValidation hbm2dll) {
220
		//TODO is it possible/required to build a properties bean here?
221
		throw new UnsupportedOperationException("getHibernatePropertiesBean() not supported by WrappedCdmDataSource");
222
	}
223

    
224
	@Override
225
	public BeanDefinition getHibernatePropertiesBean(DbSchemaValidation hbm2dll,
226
			Boolean showSql, Boolean formatSql, Boolean registerSearchListener,
227
			Class<? extends RegionFactory> cacheProviderClass) {
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 String getFilePath() {
234
		throw new UnsupportedOperationException("getFilePath() not supported by WrappedCdmDataSource");
235
	}
236

    
237
	@Override
238
	public H2Mode getMode() {
239
		throw new UnsupportedOperationException("getMode() not supported by WrappedCdmDataSource");
240
	}
241

    
242
	@Override
243
	public String getUsername() {
244
		//TODO maybe this can be implemented by connection meta data
245
		throw new UnsupportedOperationException("getUsername() not supported by WrappedCdmDataSource");
246
	}
247

    
248
	@Override
249
	public String getPassword() {
250
		throw new UnsupportedOperationException("getPassword() not supported by WrappedCdmDataSource");
251
	}
252

    
253
	@Override
254
	public String getDatabase() {
255
	    if(datasource instanceof ComboPooledDataSource) {
256
	      String jdbcUrl = ((ComboPooledDataSource)datasource).getJdbcUrl();
257
	        try {
258
                return getDatabaseFrom(jdbcUrl);
259
            } catch (URISyntaxException e) {
260
                throw new RuntimeException(e);
261
            }
262
	    } else {
263
	        throw new UnsupportedOperationException("getDatabase() not implemented for " + datasource.getClass() + " in WrappedCdmDataSource");
264
	    }
265
	}
266

    
267
    /**
268
     * @param dbType
269
     * @param jdbcUrl
270
     * @return
271
     * @throws URISyntaxException
272
     */
273
    private String getDatabaseFrom(String jdbcUrl) throws URISyntaxException {
274
        DatabaseTypeEnum type = DatabaseTypeEnum.byConnectionString(jdbcUrl);
275
        if (type == null){
276
            return null;
277
        }else{
278
            String dbName = type.getDatabaseType().getDatabaseNameByConnectionString(jdbcUrl);
279
            return dbName;
280
        }
281
    }
282

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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