All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.unitils.database.DataSourceWrapper Maven / Gradle / Ivy

There is a newer version: 3.4.6
Show newest version
package org.unitils.database;

import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.unitils.core.Unitils;
import org.unitils.core.UnitilsException;
import org.unitils.core.dbsupport.DefaultSQLHandler;
import org.unitils.core.dbsupport.SQLHandler;
import org.unitils.core.util.ConfigUtils;
import org.unitils.database.config.DataSourceFactory;
import org.unitils.database.config.DatabaseConfiguration;
import org.unitils.database.transaction.UnitilsTransactionManager;
import org.unitils.dbmaintainer.DBMaintainer;
import org.unitils.dbmaintainer.clean.DBCleaner;
import org.unitils.dbmaintainer.clean.DBClearer;
import org.unitils.dbmaintainer.structure.ConstraintsDisabler;
import org.unitils.dbmaintainer.structure.DataSetStructureGenerator;
import org.unitils.dbmaintainer.structure.SequenceUpdater;
import org.unitils.dbmaintainer.util.DatabaseAccessing;
import org.unitils.dbmaintainer.util.DatabaseModuleConfigUtils;
import org.unitils.util.PropertyUtils;


/**
 * DataSourceWrapper.
 * 
 * @author Jeroen Horemans
 * @author Thomas De Rycke
 * @author Willemijn Wouters
 * 
 * @since 3.4
 * 
 */
public class DataSourceWrapper {
    private static final Log LOGGER = LogFactory.getLog(DataSourceWrapper.class);

    private DataSource wrappedDataSource;
    protected DatabaseConfiguration databaseConfiguration;
    private DataSourceFactory dataSourceFactory;
    private boolean updateDatabaseSchemaEnabled;
    private Properties configuration;
    private String databaseName;
    
    protected Connection connection;

    private UnitilsTransactionManager transactionManager;

    private boolean wrapDataSourceInTransactionalProxy;

    public DataSourceWrapper(DatabaseConfiguration databaseConfiguration, UnitilsTransactionManager transactionManager) {
        this(databaseConfiguration, Unitils.getInstance().getConfiguration(), transactionManager);
    }

    public DataSourceWrapper(DatabaseConfiguration databaseConfiguration, Properties unitilsConfig, UnitilsTransactionManager transactionmanager) {
        // Get the factory for the data source and create it
        configuration = unitilsConfig;
        dataSourceFactory = ConfigUtils.getConfiguredInstanceOf(DataSourceFactory.class, configuration);
        dataSourceFactory.init(databaseConfiguration);
        updateDatabaseSchemaEnabled = PropertyUtils.getBoolean(DatabaseModule.PROPERTY_UPDATEDATABASESCHEMA_ENABLED, configuration);
        wrapDataSourceInTransactionalProxy = PropertyUtils.getBoolean(DatabaseModule.PROPERTY_WRAP_DATASOURCE_IN_TRANSACTIONAL_PROXY, configuration);
        databaseName = databaseConfiguration.getDatabaseName();
        this.databaseConfiguration = databaseConfiguration;
        this.transactionManager = transactionmanager;
    }

    /**
     * 
     * @return A connection from the data source, not null
     */
    public Connection getConnection() {
        try {
            connection = DataSourceUtils.getConnection(wrappedDataSource);
            
            return DatabaseUnitils.getGoodConnection(connection, wrappedDataSource);
        } catch (Exception e) {
            throw new UnitilsException("Unable to connect to database for " + databaseConfiguration + ".", e);
        }
    }

    /**
     * Returns the DataSource that provides connection to the unit test database. When invoked the first
     * time, the DBMaintainer is invoked to make sure the test database is up-to-date (if database updating is enabled)
     * If the property {@link #PROPERTY_WRAP_DATASOURCE_IN_TRANSACTIONAL_PROXY} has been set to true, the DataSource
     * returned will make sure that, for the duration of a transaction, the same java.sql.Connection is returned,
     * and that invocations of the close() method of these connections are suppressed.
     *
     * @param testObject The test instance, not null
     * @param wrapDataSourceInTransactionalProxy 
     * @return The DataSource (default database).
     */
    public DataSource getTransactionalDataSourceAndActivateTransactionIfNeeded(Object testObject) {
        if (wrapDataSourceInTransactionalProxy) {
            //return transactionHandler.getTransactionManager().getTransactionalDataSource(getDataSourceAndActivateTransactionIfNeeded());
            return transactionManager.getTransactionalDataSource(getDataSourceAndActivateTransactionIfNeeded());
        }
        return getDataSourceAndActivateTransactionIfNeeded();
    } 

    /**
     * Creates a datasource by using the factory that is defined by the dataSourceFactory.className property
     *
     * @return the datasource
     */
    public DataSource createDataSource() {
        // Get the factory for the data source and create it
        DataSourceFactory dataSourceFactory = ConfigUtils.getConfiguredInstanceOf(DataSourceFactory.class, configuration);
        dataSourceFactory.init(configuration, databaseName);
        DataSource dataSource = dataSourceFactory.createDataSource();


        // Call the database maintainer if enabled
        if (updateDatabaseSchemaEnabled) {
            updateDatabase(new DefaultSQLHandler(dataSource));
        }
        return dataSource;
    }

    /**
     * Determines whether the test database is outdated and, if this is the case, updates the database with the
     * latest changes. See {@link DBMaintainer} for more information.
     */
    public void updateDatabase() {
        updateDatabase(getDefaultSqlHandler());
    }


    /**
     * Determines whether the test database is outdated and, if that is the case, updates the database with the
     * latest changes.
     *
     * @param sqlHandler SQLHandler that needs to be used for the database updates
     * @see {@link DBMaintainer}
     */
    public void updateDatabase(SQLHandler sqlHandler) {
        LOGGER.info("Checking if database has to be updated.");
        DBMaintainer dbMaintainer = new DBMaintainer(configuration, sqlHandler, databaseConfiguration.getDialect(), databaseConfiguration.getSchemaNames());
        dbMaintainer.updateDatabase(databaseConfiguration.getDatabaseName(), databaseConfiguration.isDefaultDatabase());
    }

    /**
     * @return The default SQLHandler, which simply executes the sql statements on the unitils-configured
     *         test database
     */
    protected SQLHandler getDefaultSqlHandler() {
        return new DefaultSQLHandler(getDataSourceAndActivateTransactionIfNeeded());
    }

    /**
     * Returns the DataSource that provides connection to the unit test database. When invoked the first
     * time, the DBMaintainer is invoked to make sure the test database is up-to-date (if database updating is enabled)
     *
     * @return The DataSource
     */
    public DataSource getDataSourceAndActivateTransactionIfNeeded() {
        if (wrappedDataSource == null) {
            wrappedDataSource = createDataSource();
            activateTransactionIfNeeded();
        }
        return wrappedDataSource;
    }

    public void activateTransactionIfNeeded() {
        //UnitilsTransactionManager transactionManager = transactionHandler.getTransactionManager();
        if (transactionManager != null) {
            transactionManager.activateTransactionIfNeeded(getTestObject());
        }
    }

    protected Object getTestObject() {
        return Unitils.getInstance().getTestContext().getTestObject();
    }

    public DataSource getDataSource() {
        if (wrappedDataSource == null) {
            wrappedDataSource = createDataSource();
        }
        return wrappedDataSource;
    }

    /**
     * Clears all configured schema's. I.e. drops all tables, views and other database objects.
     */
    public void clearSchemas() {
        getConfiguredDatabaseTaskInstance(DBClearer.class).clearSchemas();
    }


    /**
     * Cleans all configured schema's. I.e. removes all data from its database tables.
     */
    public void cleanSchemas() {
        getConfiguredDatabaseTaskInstance(DBCleaner.class).cleanSchemas();
    }


    /**
     * Disables all foreigh key and not-null constraints on the configured schema's.
     */
    public void disableConstraints() {
        getConfiguredDatabaseTaskInstance(ConstraintsDisabler.class).disableConstraints();
    }


    /**
     * Updates all sequences that have a value below a certain configurable treshold to become equal
     * to this treshold
     */
    public void updateSequences() {
        getConfiguredDatabaseTaskInstance(SequenceUpdater.class).updateSequences();
    }

    /**
     * @return A configured instance of {@link DatabaseAccessing} of the given type
     *
     * @param databaseTaskType The type of database task, not null
     */
    protected  T getConfiguredDatabaseTaskInstance(Class databaseTaskType) {
        return DatabaseModuleConfigUtils.getConfiguredDatabaseTaskInstance(databaseTaskType, configuration, getDefaultSqlHandler(), databaseConfiguration.getDialect(), databaseConfiguration.getSchemaNames());
    }

    /**
     * Generates a definition file that defines the structure of dataset's, i.e. a XSD of DTD that
     * describes the structure of the database.
     */
    public void generateDatasetDefinition() {
        getConfiguredDatabaseTaskInstance(DataSetStructureGenerator.class).generateDataSetStructure();
    }

    public boolean isDataSourceLoaded() {
        return wrappedDataSource != null;
    } 
    public DatabaseConfiguration getDatabaseConfiguration() {
        return databaseConfiguration;
    }

    /**
     * @return the databaseName
     */
    public String getDatabaseName() {
        return databaseName;
    }


    /**
     * @param transactionManager the transactionManager to set
     */
    public void setTransactionManager(UnitilsTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy