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

cn.hiboot.mcn.autoconfigure.sql.SqlInitCreator Maven / Gradle / Ivy

There is a newer version: 3.3.1
Show newest version
package cn.hiboot.mcn.autoconfigure.sql;

import cn.hiboot.mcn.core.util.SpringBeanUtils;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.sql.init.SqlDataSourceScriptDatabaseInitializer;
import org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties;
import org.springframework.boot.sql.init.DatabaseInitializationMode;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * SqlInitCreator
 *
 * @author DingHao
 * @since 2022/10/11 12:39
 */
class SqlInitCreator {
    private static final String OPTIONAL_LOCATION_PREFIX = "optional:";

    static CustomSqlDataSourceScriptDatabaseInitializer create(){
        SqlInitProperties sqlInitProperties = SpringBeanUtils.getBean(SqlInitProperties.class);
        SqlInitializationProperties properties = SpringBeanUtils.getBean(SqlInitializationProperties.class);
        CustomDatabaseInitializationSettings settings = new CustomDatabaseInitializationSettings();
        settings.setSchemaLocations(scriptLocations(properties.getSchemaLocations(),sqlInitProperties.getDir(), "schema",properties.getPlatform()));
        settings.setScriptLocations(scriptLocations(sqlInitProperties.getLocations(),sqlInitProperties.getDir(),"other",properties.getPlatform()));
        settings.setDataLocations(scriptLocations(properties.getDataLocations(),sqlInitProperties.getDir(),"data",properties.getPlatform()));
        settings.setOtherSeparator(sqlInitProperties.getSeparator());
        settings.setContinueOnError(properties.isContinueOnError());
        settings.setSeparator(properties.getSeparator());
        settings.setEncoding(properties.getEncoding());
        settings.setMode(properties.getMode());
        settings.setInitDdName(sqlInitProperties.getInitDbName());
        return new CustomSqlDataSourceScriptDatabaseInitializer(SpringBeanUtils.getBean(DataSource.class),settings);
    }

    static List scriptLocations(List locations,String dir, String fallback,String platform) {
        if (locations != null) {
            return locations;
        }
        if (StringUtils.hasLength(dir)) {
            fallback = dir + "/" + fallback;
        }
        List fallbackLocations = new ArrayList<>();
        fallbackLocations.add("optional:classpath*:" + fallback + "-" + platform + ".sql");
        fallbackLocations.add("optional:classpath*:" + fallback + ".sql");
        return fallbackLocations;
    }

    private static class CustomSqlDataSourceScriptDatabaseInitializer extends SqlDataSourceScriptDatabaseInitializer {
        private final CustomDatabaseInitializationSettings settings;

        public CustomSqlDataSourceScriptDatabaseInitializer(DataSource dataSource, CustomDatabaseInitializationSettings settings) {
            super(dataSource,settings);
            this.settings = settings;
        }

        @Override
        public boolean initializeDatabase() {
            ScriptLocationResolver locationResolver = new ScriptLocationResolver(SpringBeanUtils.getApplicationContext());
            createDatabase(SpringBeanUtils.getBean(DataSourceProperties.class));
            boolean initialized = applySchemaScripts(locationResolver);
            boolean other = applyOtherScripts(locationResolver);
            return applyDataScripts(locationResolver) || other || initialized;
        }

        private void createDatabase(DataSourceProperties properties){
            String initDdName = settings.getInitDdName();
            if(ObjectUtils.isEmpty(initDdName)){
                return;
            }
            try{
                String url = properties.getUrl();
                int qPos = url.indexOf(63);
                String urlServer = url;
                if (qPos != -1) {
                    urlServer = url.substring(0, qPos);
                }
                int slash = urlServer.lastIndexOf(47);
                String dbName = urlServer.substring(slash + 1);
                url = urlServer.substring(0, slash + 1) + initDdName;
                try(Connection con = DriverManager.getConnection(url,properties.getUsername(),properties.getPassword())){
                    con.prepareStatement("CREATE DATABASE ".concat(dbName)).executeUpdate();
                }
            }catch (SQLException e){
                //ignore
            }
        }

        private boolean applySchemaScripts(ScriptLocationResolver locationResolver) {
            return applyScripts(this.settings.getSchemaLocations(), "schema", locationResolver,null);
        }

        private boolean applyOtherScripts(ScriptLocationResolver locationResolver) {
            return applyScripts(this.settings.getScriptLocations(), "other", locationResolver,this.settings.getOtherSeparator());
        }

        private boolean applyDataScripts(ScriptLocationResolver locationResolver) {
            return applyScripts(this.settings.getDataLocations(), "data", locationResolver,null);
        }

        private boolean applyScripts(List locations, String type, ScriptLocationResolver locationResolver,String separator) {
            List scripts = getScripts(locations, type, locationResolver);
            if (!scripts.isEmpty() && isEnabled()) {
                runScripts(scripts,separator);
                return true;
            }
            return false;
        }

        private boolean isEnabled() {
            if (this.settings.getMode() == DatabaseInitializationMode.NEVER) {
                return false;
            }
            return this.settings.getMode() == DatabaseInitializationMode.ALWAYS || isEmbeddedDatabase();
        }

        private List getScripts(List locations, String type, ScriptLocationResolver locationResolver) {
            if (CollectionUtils.isEmpty(locations)) {
                return Collections.emptyList();
            }
            List resources = new ArrayList<>();
            for (String location : locations) {
                boolean optional = location.startsWith(OPTIONAL_LOCATION_PREFIX);
                if (optional) {
                    location = location.substring(OPTIONAL_LOCATION_PREFIX.length());
                }
                for (Resource resource : doGetResources(location, locationResolver)) {
                    if (resource.exists()) {
                        resources.add(resource);
                    }
                    else if (!optional) {
                        throw new IllegalStateException("No " + type + " scripts found at location '" + location + "'");
                    }
                }
            }
            return resources;
        }

        private List doGetResources(String location, ScriptLocationResolver locationResolver) {
            try {
                return locationResolver.resolve(location);
            }catch (Exception ex) {
                throw new IllegalStateException("Unable to load resources from " + location, ex);
            }
        }

        private void runScripts(List resources,String separator) {
            runScripts(resources, this.settings.isContinueOnError(), separator == null ? this.settings.getSeparator() : separator, this.settings.getEncoding());
        }

    }

    private static class CustomDatabaseInitializationSettings extends DatabaseInitializationSettings{
        private List scriptLocations;
        private String otherSeparator = ";";
        private String initDdName;

        public List getScriptLocations() {
            return scriptLocations;
        }

        public void setScriptLocations(List scriptLocations) {
            this.scriptLocations = scriptLocations;
        }

        public String getOtherSeparator() {
            return otherSeparator;
        }

        public void setOtherSeparator(String otherSeparator) {
            this.otherSeparator = otherSeparator;
        }

        public String getInitDdName() {
            return initDdName;
        }

        public void setInitDdName(String initDdName) {
            this.initDdName = initDdName;
        }
    }

    private static class ScriptLocationResolver {

        private final ResourcePatternResolver resourcePatternResolver;

        ScriptLocationResolver(ResourceLoader resourceLoader) {
            this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
        }

        private List resolve(String location) throws IOException {
            List resources = new ArrayList<>(Arrays.asList(this.resourcePatternResolver.getResources(location)));
            resources.sort((r1, r2) -> {
                try {
                    return r1.getURL().toString().compareTo(r2.getURL().toString());
                }
                catch (IOException ex) {
                    return 0;
                }
            });
            return resources;
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy