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

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

package au.net.causal.maven.plugins.boxdb.db;

import au.net.causal.maven.plugins.boxdb.DependencyUtils;
import au.net.causal.maven.plugins.boxdb.ImageCheckerUtils;
import org.codehaus.plexus.util.FileUtils;
import org.eclipse.aether.resolution.DependencyResolutionException;

import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
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.sql.Connection;
import java.sql.SQLException;
import java.time.Duration;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeoutException;

public class SqliteDatabase extends FileBasedDatabase
{
    static final String SQLITE_DATABASE_GROUP_ID = "org.xerial";
    static final String SQLITE_DATABASE_ARTIFACT_ID = "sqlite-jdbc";

    /**
     * Purely to keep state, SQLite doesn't actually run a server.
     */
    private static volatile boolean running;

    public SqliteDatabase(BoxConfiguration boxConfiguration,
                          ProjectConfiguration projectConfiguration,
                          BoxContext context)
    {
        super(boxConfiguration, projectConfiguration, context);
    }
    
    protected Path sqliteDatabaseFile()
    {
        return getBoxConfiguration().getDatabaseFile().resolve(getBoxConfiguration().getDatabaseName() + ".db");
    }
    
    private String translateFileToJdbcSyntax(Path file)
    {
        return file.toAbsolutePath().toString().replace(File.separatorChar, '/');
    }

    @Override
    public boolean exists()
    throws BoxDatabaseException
    {
        if (!Files.exists(getBoxConfiguration().getDatabaseFile()))
            return false;

        //Also check databaseName exists underneath
        if (!Files.exists(sqliteDatabaseFile()))
            return false;
        
        return true;
    }

    @Override
    public boolean isRunning()
    throws BoxDatabaseException
    {
        return running;
    }

    @Override
    public void start()
    throws BoxDatabaseException
    {
        //Ensure directories are created
        try 
        {
            Files.createDirectories(sqliteDatabaseFile().getParent());
        }
        catch (IOException e)
        {
            throw new BoxDatabaseException("Failed to create directories for database: " + e.getMessage(), e);
        }
        
        //Connect to the database the first time just to create files, etc.
        try 
        {
            DataSource ds = dataSourceBuilder(DatabaseTarget.USER).create();
            try (Connection con = ds.getConnection())
            {
                //Don't need to do anything
                getContext().getLog().debug("SQLite database connection has been setup: " + con + " from " + ds);
            }
        }
        catch (IOException | SQLException e)
        {
            throw new BoxDatabaseException("Error creating SQLite database: " + e, e);
        }
        
        running = true;
    }

    @Override
    public void stop()
    throws BoxDatabaseException
    {
        //Nothing needs to be done since no server is running
        running = false;
    }

    @Override
    public void createAndStart()
    throws BoxDatabaseException
    {
        start();
    }

    @Override
    public void delete()
    throws BoxDatabaseException
    {
        getContext().getLog().info("Deleting SQLite DB " + getBoxConfiguration().getDatabaseFile());

        try
        {
            FileUtils.deleteDirectory(getBoxConfiguration().getDatabaseFile().toFile());
        }
        catch (IOException e)
        {
            throw new BoxDatabaseException("Failed to delete SQLite database in " +
                                           getBoxConfiguration().getDatabaseFile() + ": " + e, e);
        }
    }

    @Override
    public void deleteImage()
    throws BoxDatabaseException
    {
        //Not going to wipe sqlite from local Maven repo, so do nothing
    }

    @Override
    public JdbcConnectionInfo jdbcConnectionInfo(DatabaseTarget target)
    throws BoxDatabaseException
    {
        String uri = "jdbc:sqlite:" + translateFileToJdbcSyntax(sqliteDatabaseFile());
        return new JdbcConnectionInfo(uri,
                        target.user(getBoxConfiguration()), target.password(getBoxConfiguration()),
                        null, 0);
    }

    @Override
    public JdbcDriverInfo jdbcDriverInfo()
    throws BoxDatabaseException
    {
        return new JdbcDriverInfo(getSqliteDatabaseDependencies(), "org.sqlite.JDBC");
    }

    @Override
    public void waitUntilStarted(Duration maxTimeToWait)
    throws TimeoutException, BoxDatabaseException
    {
        //No network, it's up immediately
    }

    @Override
    public void executeScript(URL script, DatabaseTarget targetDatabase, Duration timeout)
    throws IOException, SQLException, BoxDatabaseException
    {
        try (Reader reader = new InputStreamReader(script.openStream(), StandardCharsets.UTF_8))
        {
            executeScript(reader, targetDatabase, timeout);
        }
    }

    protected DataSourceBuilder dataSourceBuilder(DatabaseTarget target)
    throws BoxDatabaseException
    {
        JdbcConnectionInfo jdbcInfo = jdbcConnectionInfo(target);
        return new DataSourceBuilder(getContext())
                .dataSourceClassName("org.sqlite.SQLiteDataSource")
                .dependencies(jdbcDriverInfo().getDependencies())
                .configureDataSource("setUrl", String.class, jdbcInfo.getUri())
                .configureDataSource("setDatabaseName", String.class, getBoxConfiguration().getDatabaseName());
    }
    
    @Override
    public Connection createJdbcConnection(DatabaseTarget targetDatabase)
    throws SQLException, BoxDatabaseException, IOException
    {
        return dataSourceBuilder(targetDatabase).create().getConnection();
    }

    @Override
    public void executeScript(Reader scriptReader, DatabaseTarget targetDatabase, Duration timeout)
    throws IOException, SQLException, BoxDatabaseException
    {
        executeJdbcScript(scriptReader, targetDatabase);
    }

    @Override
    public void executeSql(String sql, DatabaseTarget targetDatabase, Duration timeout)
    throws IOException, SQLException, BoxDatabaseException
    {
        try (Reader reader = new StringReader(sql))
        {
            executeScript(reader, targetDatabase, timeout);
        }
    }

    @Override
    public String getName()
    {
        return getBoxConfiguration().getDatabaseName();
    }

    @Override
    public void configureNewDatabase()
    throws IOException, SQLException, BoxDatabaseException
    {
        DataSource dataSource = dataSourceBuilder(DatabaseTarget.ADMIN).create();
        try (Connection con = dataSource.getConnection())
        {
            //Don't actually need to do anything with it as by now the database has been created
            getContext().getLog().info("Created SQLite database " + getName());
        }
    }

    /**
     * @return SQLite dependencies.
     */
    protected List getSqliteDatabaseDependencies()
    {
        return Collections.singletonList(new RunnerDependency(SQLITE_DATABASE_GROUP_ID, SQLITE_DATABASE_ARTIFACT_ID,
                                                              getBoxConfiguration().getDatabaseVersion()));
    }

    @Override
    public void prepareImage()
    throws BoxDatabaseException
    {
        try
        {
            DependencyUtils.resolveDependencies(getSqliteDatabaseDependencies(),
                                                getContext().getRepositorySystem(),
                                                getContext().getRepositorySystemSession(),
                                                getContext().getRemoteRepositories());
        }
        catch (DependencyResolutionException e)
        {
            throw new BoxDatabaseException("Failed to download dependencies for database: " + e.getMessage(), e);
        }
    }

    @Override
    public Collection checkImage()
    throws BoxDatabaseException
    {
        return Collections.singleton(ImageCheckerUtils.checkImageUsingMavenDependencies("SQLite database", getContext(), getSqliteDatabaseDependencies()));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy