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

au.net.causal.maven.plugins.boxdb.db.SqlServerDatabase Maven / Gradle / Ivy

There is a newer version: 3.3
Show newest version
package au.net.causal.maven.plugins.boxdb.db;

import au.net.causal.maven.plugins.boxdb.JdbcSqlRunner;
import au.net.causal.maven.plugins.boxdb.ScriptReaderRunner;
import au.net.causal.maven.plugins.boxdb.vagrant.BoxDefinition;
import au.net.causal.maven.plugins.boxdb.vagrant.Vagrant;
import au.net.causal.maven.plugins.boxdb.vagrant.VagrantException;
import org.apache.maven.plugin.MojoExecutionException;
import org.codehaus.plexus.util.IOUtil;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class SqlServerDatabase extends VagrantDatabase
{
    private final Path scriptsVagrantfile;
    private final Path sqlVagrantfile;
    private final Path logsVagrantfile;

    public SqlServerDatabase(BoxConfiguration boxConfiguration, ProjectConfiguration projectConfiguration, BoxContext context,
                             Vagrant vagrant,
                             Path vagrantDirectory, Path vagrantMainFile,
                             Path scriptsVagrantfile, Path sqlVagrantfile, Path logsVagrantfile)
    {
        super(boxConfiguration, projectConfiguration, context, vagrant, vagrantDirectory, vagrantMainFile);
        this.scriptsVagrantfile = scriptsVagrantfile;
        this.sqlVagrantfile = sqlVagrantfile;
        this.logsVagrantfile = logsVagrantfile;
    }

    @Override
    protected BoxDefinition vagrantBoxDefinition()
    {
        return new BoxDefinition("msabramo/mssqlserver2014express", "0.1", "virtualbox");
    }

    @Override
    public JdbcConnectionInfo jdbcConnectionInfo(DatabaseTarget target)
    throws BoxDatabaseException
    {
        return driverType().jdbcConnectionInfo(target, getBoxConfiguration(), "localhost");
    }
    
    protected SqlServerJdbcDriverType driverType()
    {
        return SqlServerJdbcDriverType.fromBoxConfiguration(getBoxConfiguration());
    }

    @Override
    public JdbcDriverInfo jdbcDriverInfo() throws BoxDatabaseException
    {
        return driverType().jdbcDriver();
    }

    protected DataSourceBuilder dataSourceBuilder(DatabaseTarget target)
    throws BoxDatabaseException
    {
        DataSourceBuilder builder = new DataSourceBuilder(getContext());
        driverType().configureDataSourceBuilder(builder, target, getBoxConfiguration(), "localhost");
        return builder;
    }

    @Override
    public Connection createJdbcConnection(DatabaseTarget targetDatabase)
    throws SQLException, BoxDatabaseException, IOException
    {
        return dataSourceBuilder(targetDatabase).create().getConnection();
    }

    @Override
    public void executeJdbcScript(Reader scriptReader, DatabaseTarget targetDatabase)
    throws IOException, SQLException, BoxDatabaseException
    {
        try (Connection con = createJdbcConnection(targetDatabase);
             JdbcSqlRunner sqlRunner = new JdbcSqlRunner(con, getContext().getLog()))
        {
            sqlRunner.executeSql(new BufferedReader(scriptReader));
        }
    }

    @Override
    public void configureNewDatabase()
    throws IOException, SQLException, BoxDatabaseException
    {
        runFilteredScript("sqlserver-create-database.sql");
    }

    private void runFilteredScript(String scriptResourceName)
    throws IOException, BoxDatabaseException, SQLException
    {
        URL scriptResource = SqlServerDatabase.class.getResource(scriptResourceName);
        if (scriptResource == null)
            throw new FileNotFoundException("Missing script resource: " + scriptResourceName);

        ScriptReaderRunner scriptRunner = getContext().createScriptReaderRunner(this, getBoxConfiguration(), getProjectConfiguration());
        ScriptReaderExecution execution = new ScriptReaderExecution();
        execution.setFiltering(true);
        //Use JDBC because using native tool through Vagrant is really slow and we don't need extra functionality
        execution.setMode(ExecutionMode.JDBC);
        execution.setScripts(Arrays.asList(scriptResource));

        try
        {
            scriptRunner.execute(execution, DatabaseTarget.ADMIN, getProjectConfiguration().getScriptTimeout());
        }
        catch (MojoExecutionException e)
        {
            throw new BoxDatabaseException(e);
        }
    }

    @Override
    public void executeScript(URL script, DatabaseTarget targetDatabase, Duration timeout)
    throws IOException, SQLException, BoxDatabaseException
    {
        //Copy the script file to inside our script dir mounted to the container
        Path mountedScriptFile = Files.createTempFile(getVagrantDirectory(), "script", ".sql");
        try (OutputStream os = Files.newOutputStream(mountedScriptFile);
             InputStream is = script.openStream())
        {
            IOUtil.copy(is, os);
        }

        executeSqlCmdForScript(mountedScriptFile.getFileName().toString(), targetDatabase, timeout);
    }

    @Override
    public void executeScript(Reader scriptReader, DatabaseTarget targetDatabase, Duration timeout)
    throws IOException, SQLException, BoxDatabaseException
    {
        //Copy the script file to inside our script dir mounted to the container
        Path mountedScriptFile = Files.createTempFile(getVagrantDirectory(), "script", ".sql");
        try (BufferedWriter out = Files.newBufferedWriter(mountedScriptFile, StandardCharsets.UTF_8))
        {
            IOUtil.copy(scriptReader, out);
        }

        executeSqlCmdForScript(mountedScriptFile.getFileName().toString(), targetDatabase, timeout);
    }

    @Override
    public void executeSql(String sql, DatabaseTarget target, Duration timeout)
    throws IOException, SQLException, BoxDatabaseException
    {
        executeSqlCmdForSql(sql, target, timeout);
    }

    protected void executeSqlCmdForScript(String scriptFileName, DatabaseTarget target, Duration timeout)
    throws SQLException, BoxDatabaseException
    {
        Vagrant.ProvisionOptions options = new Vagrant.ProvisionOptions(getVagrantDirectory(), getBoxConfiguration().getContainerName());
        configureInstanceOptions(options);
        options.env("SCRIPTFILE", scriptFileName);
        options.env("DBUSER", target.user(getBoxConfiguration()));
        options.env("DBPASSWORD", target.password(getBoxConfiguration()));
        options.env("DBNAME", target == DatabaseTarget.ADMIN ? "master" : getBoxConfiguration().getDatabaseName());
        options.setVagrantFileName(scriptsVagrantfile.getFileName().toString());
        options.setTimeout(timeout);

        try
        {
            getVagrant().provision(options);
        }
        catch (VagrantException e)
        {
            throw new BoxDatabaseException(e);
        }
    }

    protected void executeSqlCmdForSql(String sql, DatabaseTarget target, Duration timeout)
    throws SQLException, BoxDatabaseException
    {
        Vagrant.ProvisionOptions options = new Vagrant.ProvisionOptions(getVagrantDirectory(), getBoxConfiguration().getContainerName());
        configureInstanceOptions(options);
        options.env("SCRIPTSQL", sql);
        options.env("DBUSER", target.user(getBoxConfiguration()));
        options.env("DBPASSWORD", target.password(getBoxConfiguration()));
        options.env("DBNAME", target == DatabaseTarget.ADMIN ? "master" : getBoxConfiguration().getDatabaseName());
        options.setVagrantFileName(sqlVagrantfile.getFileName().toString());
        options.setTimeout(timeout);

        try
        {
            getVagrant().provision(options);
        }
        catch (VagrantException e)
        {
            throw new BoxDatabaseException(e);
        }
    }

    @Override
    public void backup(Path backupFile, BackupFileTypeHint backupFileTypeHint)
    throws BoxDatabaseException, IOException, SQLException
    {
        Path targetFile = getVagrantDirectory().resolve("backup.bak");

        //Backup to backup.bak file
        String sql = "backup database " + getBoxConfiguration().getDatabaseName() + " to disk = 'c:\\vagrant\\backup.bak' with format;";
        executeJdbcSqlCommand(sql, DatabaseTarget.ADMIN);

        //Move file to destination
        Files.move(targetFile, backupFile, StandardCopyOption.REPLACE_EXISTING);
    }

    @Override
    public void restore(Path backupFile) throws BoxDatabaseException, IOException, SQLException
    {
        Path targetFile = getVagrantDirectory().resolve("backup.bak");

        //Copy backup file to vagrant directory
        Files.copy(backupFile, targetFile, StandardCopyOption.REPLACE_EXISTING);

        executeRestoreSqlCmd(targetFile);
    }

    @Override
    public void restore(URL backupResource)
    throws BoxDatabaseException, IOException, SQLException
    {
        Path targetFile = getVagrantDirectory().resolve("backup.bak");

        //Copy backup file to vagrant directory
        try (InputStream is = backupResource.openStream())
        {
            Files.copy(is, targetFile, StandardCopyOption.REPLACE_EXISTING);
        }

        executeRestoreSqlCmd(targetFile);
    }

    private void executeJdbcSqlCommand(String sql, DatabaseTarget target)
    throws SQLException, BoxDatabaseException, IOException
    {
        try (StringReader reader = new StringReader(sql))
        {
            executeJdbcScript(reader, target);
        }
    }

    private void executeRestoreSqlCmd(Path backupFile)
    throws SQLException, BoxDatabaseException, IOException
    {
        String sql = "restore database " + getBoxConfiguration().getDatabaseName() + " from disk = 'c:\\vagrant\\" + backupFile.getFileName().toString() + "' with replace;";
        executeJdbcSqlCommand(sql, DatabaseTarget.ADMIN);

        runFilteredScript("sqlserver-post-restore-users.sql");
    }

    @Override
    public List logFiles() throws BoxDatabaseException, IOException 
    {
        Vagrant.ProvisionOptions options = new Vagrant.ProvisionOptions(getVagrantDirectory(), getBoxConfiguration().getContainerName());
        configureInstanceOptions(options);
        options.setVagrantFileName(logsVagrantfile.getFileName().toString());
        options.setTimeout(getProjectConfiguration().getBackupTimeout());

        try
        {
            getVagrant().provision(options);
        }
        catch (VagrantException e)
        {
            throw new BoxDatabaseException(e);
        }
        
        //Now we should have ERRORLOG in vagrant directory
        return Collections.singletonList(new FileDatabaseLog("ERRORLOG", logsVagrantfile.resolveSibling("ERRORLOG"), StandardCharsets.UTF_16));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy