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.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.logging.log4j.LogManager;import org.apache.logging.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
import eu.etaxonomy.cdm.persistence.hibernate.HibernateConfiguration;
27

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

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

    
47

    
48
	private final DataSource datasource;
49

    
50
	private Connection connection;
51

    
52

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

    
60
	/**
61
	 * {@inheritDoc}
62
	 */
63
	@Override
64
	public Connection getConnection() throws SQLException {
65
		if (this.connection == null){
66
		    this.connection = datasource.getConnection();
67
		}
68
		return this.connection;
69
	}
70

    
71
	@Override
72
	public Connection getConnection(String username, String password) throws SQLException {
73
		if (this.connection == null){
74
            this.connection = datasource.getConnection(username, password);
75
        }
76
		return connection;
77
	}
78

    
79
	@Override
80
	public PrintWriter getLogWriter() throws SQLException {
81
		return datasource.getLogWriter();
82
	}
83

    
84
	@Override
85
	public void setLogWriter(PrintWriter out) throws SQLException {
86
		datasource.setLogWriter(out);
87
	}
88

    
89
	@Override
90
	public void setLoginTimeout(int seconds) throws SQLException {
91
		datasource.setLoginTimeout(seconds);
92
	}
93

    
94
	@Override
95
	public int getLoginTimeout() throws SQLException {
96
		return datasource.getLoginTimeout();
97
	}
98

    
99
	@Override
100
	public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
101
		return datasource.getParentLogger();
102
	}
103

    
104
	@Override
105
	public <T> T unwrap(Class<T> iface) throws SQLException {
106
		return datasource.unwrap(iface);
107
	}
108

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

    
114
	@Override
115
	public String getName() {
116
		throw new UnsupportedOperationException("getName() not supported by WrappedCdmDataSource");
117
	}
118

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

    
124
	@Override
125
	public String getServer() {
126
		//TODO we may want to use client info from connection here
127
		throw new UnsupportedOperationException("getServer() not supported by WrappedCdmDataSource");
128
	}
129

    
130
	@Override
131
	public void setServer(String server) {
132
		throw new UnsupportedOperationException("setServer() not supported by WrappedCdmDataSource");
133
	}
134

    
135
	@Override
136
	public int getPort() {
137
		//TODO we may want to use client info from connection here
138
		throw new UnsupportedOperationException("getPort() not supported by WrappedCdmDataSource");
139
	}
140

    
141
	@Override
142
	public void setPort(int port) {
143
		throw new UnsupportedOperationException("setPort(int) not supported by WrappedCdmDataSource");
144
	}
145

    
146
	@Override
147
	public String getDbSchemaVersion() throws CdmSourceException {
148
		try {
149
			return (String)getSingleValue(CdmMetaDataPropertyName.DB_SCHEMA_VERSION.getSqlQuery());
150
		} catch (SQLException e) {
151
		    try {
152
	            return (String)getSingleValue(CdmMetaDataPropertyName.DB_SCHEMA_VERSION.getSqlQueryOld());
153
	        } catch (SQLException e1) {
154
	            throw new CdmSourceException(e1.getMessage());
155
	        }
156
		}
157
	}
158

    
159
	@Override
160
	public boolean isDbEmpty() throws CdmSourceException {
161
		// Any CDM DB should have a schema version
162
		String dbSchemaVersion = getDbSchemaVersion();
163
		return (dbSchemaVersion == null || dbSchemaVersion.equals(""));
164
	}
165

    
166
	@Override
167
	public boolean checkConnection() throws CdmSourceException {
168
		try {
169
			return testConnection();
170
		} catch (ClassNotFoundException e) {
171
			throw new CdmSourceException(e.getMessage());
172
		} catch (SQLException e) {
173
			throw new CdmSourceException(e.getMessage());
174
		}
175
	}
176

    
177
	@Override
178
	public String getConnectionMessage() {
179
		try {
180
			Connection connection = getConnection();
181
			String message = "Connecting to datasource " + connection.getSchema() + ".";
182
			return message;
183
		} catch (SQLException e) {
184
			throw new RuntimeException(e);
185
		}
186
	}
187

    
188
	@Override
189
	public void closeOpenConnections() {
190
	    try {
191
	    	if(connection != null && !connection.isClosed()){
192
                connection.close();
193
                connection = null;
194
            }
195
        } catch (SQLException e) {
196
        	logger.error("Error closing the connection");
197
        }
198
	}
199

    
200
	@Override
201
	public Map<CdmMetaDataPropertyName, String> getMetaDataMap() throws CdmSourceException {
202
		//TODO is it possible/required to build a meta data map here?
203
		throw new UnsupportedOperationException("getMetaDataMap() not supported by WrappedCdmDataSource");
204
	}
205

    
206
	@Override
207
	public BeanDefinition getDatasourceBean() {
208
		//TODO is it possible/required to build a datasource bean here?
209
		throw new UnsupportedOperationException("getDatasourceBean() not supported by WrappedCdmDataSource");
210
	}
211

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

    
218
	@Override
219
	@Deprecated
220
	public BeanDefinition getHibernatePropertiesBean(DbSchemaValidation hbm2dll,
221
			Boolean showSql, Boolean formatSql, Boolean registerSearchListener,
222
			Class<? extends RegionFactory> cacheProviderClass, String byteCodeProvider) {
223
		//TODO is it possible/required to build a properties bean here?
224
		throw new UnsupportedOperationException("getHibernatePropertiesBean() not supported by WrappedCdmDataSource");
225
	}
226

    
227
    /**
228
     * {@inheritDoc}
229
     */
230
    @Override
231
    public BeanDefinition getHibernatePropertiesBean(DbSchemaValidation hbm2dll,
232
            HibernateConfiguration hibernateConfig) {
233
        //TODO is it possible/required to build a properties bean here?
234
        throw new UnsupportedOperationException("getHibernatePropertiesBean() not supported by WrappedCdmDataSource");
235
    }
236

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

    
242
	@Override
243
	public H2Mode getMode() {
244
		throw new UnsupportedOperationException("getMode() not supported by WrappedCdmDataSource");
245
	}
246

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

    
253
	@Override
254
	public String getPassword() {
255
		throw new UnsupportedOperationException("getPassword() not supported by WrappedCdmDataSource");
256
	}
257

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

    
272
    /**
273
     * @param dbType
274
     * @param jdbcUrl
275
     * @return
276
     * @throws URISyntaxException
277
     */
278
    private String getDatabaseFrom(String jdbcUrl) throws URISyntaxException {
279
        DatabaseTypeEnum type = DatabaseTypeEnum.byConnectionString(jdbcUrl);
280
        if (type == null){
281
            return null;
282
        }else{
283
            String dbName = type.getDatabaseType().getDatabaseNameByConnectionString(jdbcUrl);
284
            return dbName;
285
        }
286
    }
287

    
288
	@Override
289
	public void setMode(H2Mode h2Mode) {
290
		throw new UnsupportedOperationException("setMode(H2Mode) not supported by WrappedCdmDataSource");
291
	}
292

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

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

    
303
	@Override
304
	public void setDatabase(String database) {
305
		throw new UnsupportedOperationException("setDatabase(String) not supported by WrappedCdmDataSource");
306
	}
307

    
308
	@Override
309
	public DatabaseTypeEnum getDatabaseType() {
310
	    if (this.datasource instanceof ICdmDataSource){
311
	        return ((ICdmDataSource)this.datasource).getDatabaseType();
312
	    }
313

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

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

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

    
342
        }
343
		throw new IllegalStateException("datasource type (MySQL, SQL Server, ...) could not be retrieved from generic datasource");
344
	}
345

    
346
	@Override
347
	public boolean testConnection() throws ClassNotFoundException, SQLException {
348
		return getConnection() != null;
349
	}
350

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

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

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

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

    
379
	@Override
380
	public void rollback() throws SQLException {
381
		getConnection().rollback();
382
	}
383

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

    
396
	@Override
397
	public DatabaseMetaData getMetaData() {
398
		try {
399
			return getConnection().getMetaData();
400
		} catch (SQLException e) {
401
			throw new RuntimeException(e);
402
		}
403
	}
404

    
405
}
(21-21/21)