This commit is contained in:
Keith Donald 2009-05-06 07:56:52 +00:00
parent d159195b79
commit 442e7343d6
8 changed files with 75 additions and 18 deletions

View File

@ -1,9 +1,33 @@
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.datasource.embedded; package org.springframework.jdbc.datasource.embedded;
import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.EncodedResource;
/**
* Thrown by {@link ResourceDatabasePopulator} if one of its SQL scripts could not be read during population.
* @author Keith Donald
*/
public class CannotReadScriptException extends RuntimeException { public class CannotReadScriptException extends RuntimeException {
/**
* Creates a new cannot read script exception.
* @param resource the resource that could not be read from
* @param cause the underlying cause of the resource access failure
*/
public CannotReadScriptException(EncodedResource resource, Throwable cause) { public CannotReadScriptException(EncodedResource resource, Throwable cause) {
super("Cannot read SQL script from " + resource, cause); super("Cannot read SQL script from " + resource, cause);
} }

View File

@ -20,7 +20,7 @@ import javax.sql.DataSource;
import org.springframework.jdbc.datasource.SimpleDriverDataSource; import org.springframework.jdbc.datasource.SimpleDriverDataSource;
/** /**
* A factory for a kind of DataSource, such as a {@link SimpleDriverDataSource} or connection pool such as Apache DBCP or c3p0. * A factory for DataSource implementation, such as a {@link SimpleDriverDataSource} or connection pool such as Apache DBCP or c3p0.
* Call {@link #getConnectionProperties()} to configure normalized DataSource properties before calling {@link #getDataSource()} to actually get the configured DataSource instance. * Call {@link #getConnectionProperties()} to configure normalized DataSource properties before calling {@link #getDataSource()} to actually get the configured DataSource instance.
* @author Keith Donald * @author Keith Donald
*/ */

View File

@ -19,7 +19,7 @@ import javax.sql.DataSource;
/** /**
* Encapsulates the configuration required to create, connect to, and shutdown a specific type of embedded database such as HSQLdb or H2. * Encapsulates the configuration required to create, connect to, and shutdown a specific type of embedded database such as HSQLdb or H2.
* Create a implementation for each database type we wish to support. * Create a implementation for each database type you wish to support; for example HSQL, H2, or some other type.
* @author Keith Donald * @author Keith Donald
*/ */
public interface EmbeddedDatabaseConfigurer { public interface EmbeddedDatabaseConfigurer {

View File

@ -18,10 +18,14 @@ package org.springframework.jdbc.datasource.embedded;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Package private factory for mapping well-known embedded database types to database configurer strategies. * Package private factory for mapping well-known {@link EmbeddedDatabaseType embedded database types} to
* {@link EmbeddedDatabaseConfigurer} strategies.
* @author Keith Donald * @author Keith Donald
*/ */
class EmbeddedDatabaseConfigurerFactory { final class EmbeddedDatabaseConfigurerFactory {
private EmbeddedDatabaseConfigurerFactory() {
}
public static EmbeddedDatabaseConfigurer getConfigurer(EmbeddedDatabaseType type) throws IllegalStateException { public static EmbeddedDatabaseConfigurer getConfigurer(EmbeddedDatabaseType type) throws IllegalStateException {
Assert.notNull(type, "The EmbeddedDatabaseType is required"); Assert.notNull(type, "The EmbeddedDatabaseType is required");
@ -29,10 +33,11 @@ class EmbeddedDatabaseConfigurerFactory {
if (type == EmbeddedDatabaseType.HSQL) { if (type == EmbeddedDatabaseType.HSQL) {
return HsqlEmbeddedDatabaseConfigurer.getInstance(); return HsqlEmbeddedDatabaseConfigurer.getInstance();
} else { } else {
throw new UnsupportedOperationException("Other types not yet supported"); throw new UnsupportedOperationException("Other embedded database types not yet supported");
} }
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new IllegalStateException("Drivers for test database type [" + type + "] are not available in the classpath", e); throw new IllegalStateException("Drivers for test database type [" + type
+ "] are not available in the classpath", e);
} }
} }

View File

@ -116,14 +116,19 @@ public class EmbeddedDatabaseFactory {
*/ */
public EmbeddedDatabase getDatabase() { public EmbeddedDatabase getDatabase() {
if (dataSource == null) { if (dataSource == null) {
initDataSource(); initDatabase();
} }
return new EmbeddedDataSourceProxy(dataSource); return new EmbeddedDataSourceProxy(dataSource);
} }
// subclassing hooks // subclassing hooks
protected void initDataSource() { /**
* Hook to initialize the embedded database.
* Subclasses may call to force initialization.
* After calling this method, {@link #getDataSource()} returns the DataSource providing connectivity to the db.
*/
protected void initDatabase() {
// create the embedded database source first // create the embedded database source first
if (logger.isInfoEnabled()) { if (logger.isInfoEnabled()) {
logger.info("Created embedded database '" + databaseName + "'"); logger.info("Created embedded database '" + databaseName + "'");
@ -136,11 +141,23 @@ public class EmbeddedDatabaseFactory {
} }
} }
/**
* Hook that gets the datasource that provides the connectivity to the embedded database.
* Returns null if the datasource has not been initialized or the database has been shutdown.
* Subclasses may call to access the datasource instance directly.
* @return the datasource
*/
protected DataSource getDataSource() { protected DataSource getDataSource() {
return dataSource; return dataSource;
} }
protected void shutdownDataSource() { /**
* Hook to shutdown the embedded database.
* Subclasses may call to force shutdown.
* After calling, {@link #getDataSource()} returns null.
* Does nothing if no embedded database has been initialized.
*/
protected void shutdownDatabase() {
if (dataSource != null) { if (dataSource != null) {
databaseConfigurer.shutdown(dataSource); databaseConfigurer.shutdown(dataSource);
dataSource = null; dataSource = null;
@ -200,7 +217,7 @@ public class EmbeddedDatabaseFactory {
} }
public void shutdown() { public void shutdown() {
shutdownDataSource(); shutdownDatabase();
} }
} }

View File

@ -32,7 +32,7 @@ import org.springframework.beans.factory.InitializingBean;
public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory implements FactoryBean<DataSource>, InitializingBean, DisposableBean { public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory implements FactoryBean<DataSource>, InitializingBean, DisposableBean {
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
initDataSource(); initDatabase();
} }
public DataSource getObject() throws Exception { public DataSource getObject() throws Exception {
@ -48,7 +48,7 @@ public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory impleme
} }
public void destroy() throws Exception { public void destroy() throws Exception {
shutdownDataSource(); shutdownDatabase();
} }
} }

View File

@ -25,12 +25,26 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
public class HsqlEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigurer { /**
* Initializes a HSQL embedded database instance.
* Call {@link #getInstance()} to get the singleton instance of this class.
*
* @author Keith Donald
*/
final class HsqlEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigurer {
private static final Log logger = LogFactory.getLog(HsqlEmbeddedDatabaseConfigurer.class); private static final Log logger = LogFactory.getLog(HsqlEmbeddedDatabaseConfigurer.class);
private static HsqlEmbeddedDatabaseConfigurer INSTANCE; private static HsqlEmbeddedDatabaseConfigurer INSTANCE;
private HsqlEmbeddedDatabaseConfigurer() {
}
/**
* Get the singleton {@link HsqlEmbeddedDatabaseConfigurer} instance.
* @return the configurer
* @throws ClassNotFoundException if HSQL is not on the classpath
*/
public static synchronized HsqlEmbeddedDatabaseConfigurer getInstance() throws ClassNotFoundException { public static synchronized HsqlEmbeddedDatabaseConfigurer getInstance() throws ClassNotFoundException {
if (INSTANCE == null) { if (INSTANCE == null) {
ClassUtils.forName("org.hsqldb.jdbcDriver", HsqlEmbeddedDatabaseConfigurer.class.getClassLoader()); ClassUtils.forName("org.hsqldb.jdbcDriver", HsqlEmbeddedDatabaseConfigurer.class.getClassLoader());

View File

@ -4,13 +4,12 @@ import javax.sql.DataSource;
import org.springframework.jdbc.datasource.SimpleDriverDataSource; import org.springframework.jdbc.datasource.SimpleDriverDataSource;
public class SimpleDriverDataSourceFactory implements DataSourceFactory { final class SimpleDriverDataSourceFactory implements DataSourceFactory {
private SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); private SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
public ConnectionProperties getConnectionProperties() { public ConnectionProperties getConnectionProperties() {
return new ConnectionProperties() { return new ConnectionProperties() {
public void setDriverClass(Class<?> driverClass) { public void setDriverClass(Class<?> driverClass) {
dataSource.setDriverClass(driverClass); dataSource.setDriverClass(driverClass);
} }
@ -26,7 +25,6 @@ public class SimpleDriverDataSourceFactory implements DataSourceFactory {
public void setPassword(String password) { public void setPassword(String password) {
dataSource.setPassword(password); dataSource.setPassword(password);
} }
}; };
} }
@ -34,5 +32,4 @@ public class SimpleDriverDataSourceFactory implements DataSourceFactory {
return dataSource; return dataSource;
} }
} }