Skip to content

Commit

Permalink
Merge pull request #1081 from tdonohue/DS-2701-service-api-flyway-cle…
Browse files Browse the repository at this point in the history
…anup

DS-2701: Bug fix, cleanup and pgcrypto checking
  • Loading branch information
tdonohue committed Sep 30, 2015
2 parents 1826910 + d451304 commit a699413
Show file tree
Hide file tree
Showing 9 changed files with 711 additions and 188 deletions.
338 changes: 236 additions & 102 deletions dspace-api/src/main/java/org/dspace/storage/rdbms/DatabaseUtils.java

Large diffs are not rendered by default.

@@ -0,0 +1,189 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.storage.rdbms;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.log4j.Logger;
import org.flywaydb.core.api.FlywayException;
import org.flywaydb.core.api.MigrationInfo;
import org.flywaydb.core.api.callback.FlywayCallback;

/**
* This is a FlywayCallback class which automatically verifies that "pgcrypto"
* is at the proper version before running any database migrations.
* <P>
* When running PostgreSQL, pgcrypto is REQUIRED by DSpace as it allows UUIDs
* to be generated.
* <P>
* During a database "clean", this also de-registers "pgcrypto" proir to the
* full database clean.
*
* @author Tim Donohue
*/
public class PostgreSQLCryptoChecker implements FlywayCallback
{
private Logger log = Logger.getLogger(PostgreSQLCryptoChecker.class);

/**
* Check for pgcrypto (if needed). Throws an exception if pgcrypto is
* not installed or needs an upgrade.
* @param connection database connection
*/
public void checkPgCrypto(Connection connection)
{
String dbType;
try
{
dbType = DatabaseUtils.getDbType(connection);
}
catch(SQLException se)
{
throw new FlywayException("Unable to determine database type.", se);
}

// ONLY Check if this is a PostgreSQL database
if(dbType!=null && dbType.equals(DatabaseUtils.DBMS_POSTGRES))
{
// If this is a PostgreSQL database, then a supported version
// of the 'pgcrypto' extension MUST be installed to continue.

// Check if pgcrypto is both installed & a supported version
if(!PostgresUtils.isPgcryptoUpToDate())
{
throw new FlywayException("This PostgreSQL Database is INCOMPATIBLE with DSpace. The upgrade will NOT proceed. " +
"A supported version (>=" + PostgresUtils.PGCRYPTO_VERSION + ") of the '" + PostgresUtils.PGCRYPTO + "' extension must be installed! " +
"Please run 'dspace database info' for additional info/tips.");
}
}
}

/**
* Remove pgcrypto (if necessary).
* <P>
* The pgcrypto extension MUST be removed before a clean or else errors occur.
* This method checks if it needs to be removed and, if so, removes it.
* @param connection database connection
*/
public void removePgCrypto(Connection connection)
{
try
{
String dbType = DatabaseUtils.getDbType(connection);

// ONLY remove if this is a PostgreSQL database
if(dbType!=null && dbType.equals(DatabaseUtils.DBMS_POSTGRES))
{
// Get current schema
String schema = DatabaseUtils.getSchemaName(connection);

// Check if pgcrypto is in this schema
// If so, it MUST be removed before a 'clean'
if(PostgresUtils.isPgcryptoInSchema(schema))
{
// remove the extension
try(Statement statement = connection.createStatement())
{
// WARNING: ONLY superusers can remove pgcrypto. However, at this point,
// we have already verified user acct permissions via PostgresUtils.checkCleanPermissions()
// (which is called prior to a 'clean' being triggered).
statement.execute("DROP EXTENSION " + PostgresUtils.PGCRYPTO + " CASCADE");
}
}
}
}
catch(SQLException e)
{
throw new FlywayException("Failed to check for and/or remove '" + PostgresUtils.PGCRYPTO + "' extension", e);
}
}

@Override
public void beforeClean(Connection connection) {
// If pgcrypto is installed, remove it
removePgCrypto(connection);
}

@Override
public void afterClean(Connection connection) {

}

@Override
public void beforeMigrate(Connection connection) {
// Before migrating database, check for pgcrypto
checkPgCrypto(connection);
}

@Override
public void afterMigrate(Connection connection) {

}

@Override
public void beforeEachMigrate(Connection connection, MigrationInfo migrationInfo) {

}

@Override
public void afterEachMigrate(Connection connection, MigrationInfo migrationInfo) {

}

@Override
public void beforeValidate(Connection connection) {

}

@Override
public void afterValidate(Connection connection) {

}

@Override
public void beforeInit(Connection connection) {

}

@Override
public void afterInit(Connection connection) {

}

@Override
public void beforeBaseline(Connection connection) {
// Before initializing database, check for pgcrypto
checkPgCrypto(connection);
}

@Override
public void afterBaseline(Connection connection) {

}

@Override
public void beforeRepair(Connection connection) {

}

@Override
public void afterRepair(Connection connection) {

}

@Override
public void beforeInfo(Connection connection) {

}

@Override
public void afterInfo(Connection connection) {

}
}

0 comments on commit a699413

Please sign in to comment.