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

com.github.trang.druid.autoconfigure.datasource.init.DataSourceInitializer Maven / Gradle / Ivy

package com.github.trang.druid.autoconfigure.datasource.init;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.jdbc.config.SortedResourcesFactoryBean;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.util.StringUtils;

import com.alibaba.druid.pool.DruidDataSource;

/**
 * Initialize {@link DataSource} List based on a matching {@link DataSourceProperties} config.
 *
 * @author Dave Syer
 * @author Phillip Webb
 * @author Eddú Meléndez
 * @author Stephane Nicoll
 * @author Kazuki Shimizu
 */
public class DataSourceInitializer {

    private static final Log logger = LogFactory.getLog(DataSourceInitializer.class);

    private final List dataSources;

    private final DataSourceProperties properties;

    private final ResourceLoader resourceLoader;

    /**
     * Create a new instance with the {@link DataSource} to initialize and its matching
     * {@link DataSourceProperties configuration}.
     *
     * @param dataSources    the data sources to initialize
     * @param properties     the matching configuration
     * @param resourceLoader the resource loader to use (can be null)
     */
    public DataSourceInitializer(List dataSources, DataSourceProperties properties,
                                 ResourceLoader resourceLoader) {
        this.dataSources = dataSources;
        this.properties = properties;
        this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader());
    }

    /**
     * Create a new instance with the {@link DataSource} to initialize and its matching
     * {@link DataSourceProperties configuration}.
     *
     * @param dataSources the data sources to initialize
     * @param properties  the matching configuration
     */
    public DataSourceInitializer(List dataSources, DataSourceProperties properties) {
        this(dataSources, properties, null);
    }

    public List getDataSources() {
        return this.dataSources;
    }

    /**
     * Create the schema if necessary.
     *
     * @return {@code true} if the schema was created
     * @see DataSourceProperties#getSchema()
     */
    public boolean createSchema() {
        List scripts = getScripts("spring.datasource.schema",
                this.properties.getSchema(), "schema");
        if (!scripts.isEmpty()) {
            if (!isEnabled()) {
                logger.debug("Initialization disabled (not running DDL scripts)");
                return false;
            }
            String username = this.properties.getSchemaUsername();
            String password = this.properties.getSchemaPassword();
            runScripts(scripts, username, password);
        }
        return !scripts.isEmpty();
    }

    /**
     * Initialize the schema if necessary.
     *
     * @see DataSourceProperties#getData()
     */
    public void initSchema() {
        List scripts = getScripts("spring.datasource.data",
                this.properties.getData(), "data");
        if (!scripts.isEmpty()) {
            if (!isEnabled()) {
                logger.debug("Initialization disabled (not running data scripts)");
                return;
            }
            String username = this.properties.getDataUsername();
            String password = this.properties.getDataPassword();
            runScripts(scripts, username, password);
        }
    }

    private boolean isEnabled() {
        DataSourceInitializationMode mode = this.properties.getInitializationMode();
        if (mode == DataSourceInitializationMode.NEVER) {
            return false;
        }
        if (mode == DataSourceInitializationMode.EMBEDDED && !isEmbedded()) {
            return false;
        }
        return true;
    }

    private boolean isEmbedded() {
        try {
            return this.dataSources.stream().allMatch(EmbeddedDatabaseConnection::isEmbedded);
        } catch (Exception ex) {
            logger.debug("Could not determine if datasource is embedded", ex);
            return false;
        }
    }

    private List getScripts(String propertyName, List resources, String fallback) {
        if (resources != null) {
            return getResources(propertyName, resources, true);
        }
        String platform = this.properties.getPlatform();
        List fallbackResources = new ArrayList<>();
        fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");
        fallbackResources.add("classpath*:" + fallback + ".sql");
        return getResources(propertyName, fallbackResources, false);
    }

    private List getResources(String propertyName, List locations, boolean validate) {
        List resources = new ArrayList<>();
        for (String location : locations) {
            for (Resource resource : doGetResources(location)) {
                if (resource.exists()) {
                    resources.add(resource);
                } else if (validate) {
                    throw new InvalidConfigurationPropertyValueException(propertyName,
                            resource, "The specified resource does not exist.");
                }
            }
        }
        return resources;
    }

    private Resource[] doGetResources(String location) {
        try {
            SortedResourcesFactoryBean factory = new SortedResourcesFactoryBean(
                    this.resourceLoader, Collections.singletonList(location));
            factory.afterPropertiesSet();
            return factory.getObject();
        } catch (Exception ex) {
            throw new IllegalStateException("Unable to load resources from " + location, ex);
        }
    }

    private void runScripts(List resources, String username, String password) {
        if (resources.isEmpty()) {
            return;
        }
        ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
        populator.setContinueOnError(this.properties.isContinueOnError());
        populator.setSeparator(this.properties.getSeparator());
        if (this.properties.getSqlScriptEncoding() != null) {
            populator.setSqlScriptEncoding(this.properties.getSqlScriptEncoding().name());
        }
        for (Resource resource : resources) {
            populator.addScript(resource);
        }
        List dataSources = this.dataSources;
        boolean isDifferent = (username != null && !this.properties.getUsername().equals(username)) ||
                (password != null && !this.properties.getPassword().equals(password));
        if (username == null) {
            username = this.properties.getUsername();
        }
        if (password == null) {
            password = this.properties.getPassword();
        }
        if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
            for (DataSource dataSource : dataSources) {
                if (isDifferent) {
                    dataSource = DataSourceBuilder.create(this.properties.getClassLoader())
                            .driverClassName(this.properties.determineDriverClassName())
                            .url(this.properties.determineUrl())
                            .username(username)
                            .password(password)
                            .build();
                }
                DatabasePopulatorUtils.execute(populator, dataSource);
            }
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy