au.net.causal.maven.plugins.boxdb.db.SqlServerDatabase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of boxdb-maven-plugin Show documentation
Show all versions of boxdb-maven-plugin Show documentation
Maven plugin to start databases using Docker and VMs
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 extends DatabaseLog> 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));
}
}