au.net.causal.maven.plugins.boxdb.db.BoxDatabase Maven / Gradle / Ivy
package au.net.causal.maven.plugins.boxdb.db;
import au.net.causal.maven.plugins.boxdb.db.ImageComponent.ImageStatus;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.net.URL;
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.Objects;
import java.util.concurrent.TimeoutException;
/**
* A database that runs in a container.
*/
public interface BoxDatabase
{
/**
* @return true if the container exists, false if not.
*
* @throws BoxDatabaseException if an error occurs.
*/
public boolean exists()
throws BoxDatabaseException;
/**
* @return true if the container exists and is currently running.
*
* @throws BoxDatabaseException if an error occurs.
*/
public boolean isRunning()
throws BoxDatabaseException;
/**
* Starts an already-existing container.
*
* @throws BoxDatabaseException if an error occurs.
*/
public void start()
throws BoxDatabaseException;
/**
* Stops a running container.
*
* @throws BoxDatabaseException if an error occurs.
*/
public void stop()
throws BoxDatabaseException;
/**
* Creates a container and starts it.
*
* @throws BoxDatabaseException if an error occurs.
*/
public void createAndStart()
throws BoxDatabaseException;
/**
* Deletes the container. Container must be stopped.
*
* @throws BoxDatabaseException if an error occurs.
*/
public void delete()
throws BoxDatabaseException;
/**
* @param targetDatabase whether to connect as admin user or database user. Admin target is typically
* used for creating databases, database target is for DDL.
*
* @return the JDBC URL to use to connect to the database.
*
* @throws BoxDatabaseException if an error occurs.
*/
public JdbcConnectionInfo jdbcConnectionInfo(DatabaseTarget targetDatabase)
throws BoxDatabaseException;
/**
* Blocks until the database has completely started up.
*
* @param maxTimeToWait the maximum time to wait. If null, potentially wait forever.
*
* @throws TimeoutException if the maximum time to wait is exceeded while waiting for startup.
* @throws BoxDatabaseException if another error occurs.
*/
public void waitUntilStarted(Duration maxTimeToWait)
throws TimeoutException, BoxDatabaseException;
/**
* Creates a JDBC connection to the database.
*
* @param targetDatabase the database target.
*
* @return a JDBC connection.
*
* @throws IOException if an I/O error occurs.
* @throws SQLException if an error occurs establishing the connection.
* @throws BoxDatabaseException if another error occurs.
*/
public Connection createJdbcConnection(DatabaseTarget targetDatabase)
throws SQLException, BoxDatabaseException, IOException;
/**
* Executes a script using JDBC.
*
*
* Scripts run via JDBC may execute a lot faster than native scripts, but may be limited in
* functionality.
*
* @param scriptReader the reader to read the JDBC script.
* @param targetDatabase the database to run the script against.
*
* @throws IOException if an I/O error occurs reading the script.
* @throws SQLException if there is an error executing the script.
* @throws BoxDatabaseException if another error occurs.
*/
public void executeJdbcScript(Reader scriptReader, DatabaseTarget targetDatabase)
throws IOException, SQLException, BoxDatabaseException;
/**
* Executes a SQL script using the database's native script executor.
*
* @param script a URL of the script to execute.
* @param targetDatabase the database to run the script against.
* @param timeout the maximum amount of time to allow to run the script. Recommendation only.
*
* @throws IOException if an I/O error occurs reading the script.
* @throws SQLException if there is an error executing the script.
* @throws BoxDatabaseException if another error occurs.
*/
public void executeScript(URL script, DatabaseTarget targetDatabase, Duration timeout)
throws IOException, SQLException, BoxDatabaseException;
/**
* Executes a SQL script read from a reader using the database's native script executor.
*
* @param scriptReader the reader to read the SQL script.
* @param targetDatabase the database to run the script against.
* @param timeout the maximum amount of time to allow to run the script. Recommendation only.
*
* @throws IOException if an I/O error occurs reading the script.
* @throws SQLException if there is an error executing the script.
* @throws BoxDatabaseException if another error occurs.
*/
public void executeScript(Reader scriptReader, DatabaseTarget targetDatabase, Duration timeout)
throws IOException, SQLException, BoxDatabaseException;
/**
* Executes a SQL command using the database's native script executor..
*
* @param sql the SQL command to execute.
* @param targetDatabase the database to run the script against.
* @param timeout the maximum amount of time to allow to run the script. Recommendation only.
*
* @throws IOException if an I/O error occurs with the script. Might occur if saving the script to temp directory.
* @throws SQLException if an error occurs executing the script.
* @throws BoxDatabaseException if another error occurs.
*/
public void executeSql(String sql, DatabaseTarget targetDatabase, Duration timeout)
throws IOException, SQLException, BoxDatabaseException;
/**
* @return the name of the container running the database.
*/
public String getName();
/**
* Creates and sets up the database so that the configuration's {@linkplain BoxConfiguration#getDatabaseName() database name},
* {@linkplain BoxConfiguration#getDatabaseUser() user name} and {@linkplain BoxConfiguration#getDatabasePassword() password}
* are set up.
*
* @throws IOException if an I/O error occurs reading scripts.
* @throws SQLException if a SQL execution error occurs.
* @throws BoxDatabaseException if another error occurs.
*/
public void configureNewDatabase()
throws IOException, SQLException, BoxDatabaseException;
/**
* @return JDBC driver information for the database.
*
* @throws BoxDatabaseException if an error occurs.
*/
public JdbcDriverInfo jdbcDriverInfo()
throws BoxDatabaseException;
/**
* Backs up the database to file.
*
* @param backupFile the file to save the backup to.
* @param backupFileTypeHint hint for the output format.
*
* @throws BoxDatabaseException if a database connectivity error occurs.
* @throws IOException if an I/O error occurs writing to the backup file.
* @throws SQLException if a backup execution error occurs.
*/
public void backup(Path backupFile, BackupFileTypeHint backupFileTypeHint)
throws BoxDatabaseException, IOException, SQLException;
/**
* Restore database from backup file. All existing data in the database is deleted.
*
* @param backupFile the backup file to restore.
*
* @throws BoxDatabaseException if a database connectivity error occurs.
* @throws IOException if an I/O error occurs reading from the backup file.
* @throws SQLException if a restore execution error occurs.
*/
public void restore(Path backupFile)
throws BoxDatabaseException, IOException, SQLException;
/**
* Restore database from a URL resource. All existing data in the database is deleted.
*
* @param backupResource the URL resource of the backup file to restore from.
*
* @throws BoxDatabaseException if a database connectivity error occurs.
* @throws IOException if an I/O error occurs reading from the backup file.
* @throws SQLException if a restore execution error occurs.
*/
public void restore(URL backupResource)
throws BoxDatabaseException, IOException, SQLException;
/**
* Retrieves a log file with the specified name.
*
*
* Log file names are database specific. If unsure, use {@link #logFiles()} to retrieve all logs.
*
* @param name the log file name.
*
* @return the log file.
*
* @throws BoxDatabaseException if an error occurs communicating with the database or container.
* @throws FileNotFoundException if no log file with the specified name exists for this database.
* @throws IOException if an I/O error occurs.
*
* @see #logFiles()
* @see #bestLogFile()
*
* @since 1.6
*/
public default DatabaseLog logFile(String name)
throws BoxDatabaseException, FileNotFoundException, IOException
{
Objects.requireNonNull(name, "name == null");
for (DatabaseLog dl : logFiles())
{
if (dl.getName().equals(name))
return dl;
}
throw new FileNotFoundException(name);
}
/**
* Retrieves the most important, or 'best', log file containing startup and diagnostic information.
*
* @return the best log file. Can return null
if there are no logs.
*
* @throws BoxDatabaseException if an error occurs communicating with the database or container.
* @throws IOException if an I/O error occurs.
*
* @see #logFiles()
*
* @since 1.6
*/
public default DatabaseLog bestLogFile()
throws BoxDatabaseException, IOException
{
List extends DatabaseLog> logs = logFiles();
if (logs.isEmpty())
return null;
return logs.get(0);
}
/**
* Retrieves all log files for the database. Log files contain startup details and other useful information, and
* can be used to debug startup problems. Name, type and number of log files available are dependent on database
* implementation.
*
*
* The most 'important' log file will be listed first. Older and less important logs are ordered afterwards.
*
* @return a list of database log files, most important/recent ordered first. May be empty if there are no logs.
*
* @throws BoxDatabaseException if an error occurs communicating with the database or container.
* @throws IOException if an I/O error occurs.
*
* @see #logFile(String)
* @see #bestLogFile()
*
* @since 1.6
*/
public default List extends DatabaseLog> logFiles()
throws BoxDatabaseException, IOException
{
return Collections.emptyList();
}
/**
* Returns true if the specified error from JDBC verifies the database has fully started up.
*
*
* If this method returns true on an error, BoxDB will deem JDBC waiting successful despite
* the error coming back from attempted connection to the database.
*
*
* By default, all errors are treated as critical so this method by default returns false always.
*
* @param ex an SQL error from attempting a JDBC connection.
*
* @return true if the exception indicates the database is ready and fully started up, false otherwise.
*
* @since 1.10
*/
public default boolean databaseIsReady(SQLException ex)
{
return false;
}
/**
* Deletes any images for the box database. This clears out image caches and cleans up as much as possible.
* No containers must exist and can be running for this database.
*
* @throws BoxDatabaseException if an error occurs.
*/
public void deleteImage()
throws BoxDatabaseException;
/**
* Returns whether an image exists for this box. Returns false if there are resources that must be downloaded
* for the box to be able to be used.
*
* @return true if the image exists for this database, false if not.
*
* @throws BoxDatabaseException if an error occurs.
*
* @since 3.0
*/
public default boolean hasImage()
throws BoxDatabaseException
{
//Ensure all image components are downloaded
//If one or more is not downloaded or found then we don't have everything locally
for (ImageComponent component : checkImage())
{
if (component.getStatus() == ImageStatus.NOT_DOWNLOADED || component.getStatus() == ImageStatus.NOT_FOUND)
return false;
}
return true;
}
/**
* Downloads and prepares and images, drivers and resources required for database operation. Does nothing if
* all required images and resources already exist locally and are up-to-date. Updates to newer version if
* the local image is older than the available remote image.
*
*
* This might simply involve downloading an image from the Internet or might involve a combination of downloading
* and other operations to generate a container image.
*
* @throws BoxDatabaseException if an error occurs.
*
* @since 3.0
*/
public void prepareImage()
throws BoxDatabaseException;
/**
* Checks the status of an image, whether it exists locally and whether a remote update is available.
*
* @return the image status of possibly multiple resources.
*
* @throws BoxDatabaseException if an error occurs.
*
* @since 3.0
*/
public Collection extends ImageComponent> checkImage()
throws BoxDatabaseException;
}