From 8364c74e9c0144c98730d5071cc869a16192c8ea Mon Sep 17 00:00:00 2001
From: ribeaudc <ribeaudc>
Date: Sat, 16 Aug 2008 19:40:25 +0000
Subject: [PATCH] change: - 'Script.getCode' renamed to 'Script.getContent'. -
 Java migration step stuff moved into its own package. - Improve performance:
 1/ Load the script only once, and not for each pre/post method. 2/ Look only
 for the first line (do not scan the whole script).

SVN: 7934
---
 .../java/ch/systemsx/cisd/common/Script.java  |  20 +-
 .../cisd/dbmigration/DBMigrationEngine.java   |  35 +--
 .../dbmigration/DatabaseVersionLogDAO.java    |   4 +-
 .../cisd/dbmigration/IDAOFactory.java         |   3 +-
 .../JavaMigrationStepExecutor.java            | 174 -------------
 .../cisd/dbmigration/SqlScriptExecutor.java   |   2 +-
 .../cisd/dbmigration/h2/H2DAOFactory.java     |  10 +-
 .../{ => java}/IMigrationStep.java            |  12 +-
 .../IMigrationStepExecutor.java}              |  23 +-
 .../java/MigrationStepExecutor.java           | 144 +++++++++++
 .../postgresql/PostgreSQLDAOFactory.java      |  12 +-
 .../dbmigration/DBMigrationEngineTest.java    | 241 ++++++++----------
 .../JavaMigrationStepExecutorTest.java        | 114 ---------
 .../dbmigration/SqlScriptProviderTest.java    |  10 +-
 .../java/MigrationStepExecutorTest.java       | 160 ++++++++++++
 .../{ => java}/MigrationStepFrom001To002.java |  15 +-
 .../{ => java}/MigrationStepFrom002To003.java |  20 +-
 17 files changed, 486 insertions(+), 513 deletions(-)
 delete mode 100644 dbmigration/source/java/ch/systemsx/cisd/dbmigration/JavaMigrationStepExecutor.java
 rename dbmigration/source/java/ch/systemsx/cisd/dbmigration/{ => java}/IMigrationStep.java (81%)
 rename dbmigration/source/java/ch/systemsx/cisd/dbmigration/{IJavaMigrationStepExecutor.java => java/IMigrationStepExecutor.java} (62%)
 create mode 100644 dbmigration/source/java/ch/systemsx/cisd/dbmigration/java/MigrationStepExecutor.java
 delete mode 100644 dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/JavaMigrationStepExecutorTest.java
 create mode 100644 dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/java/MigrationStepExecutorTest.java
 rename dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/{ => java}/MigrationStepFrom001To002.java (66%)
 rename dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/{ => java}/MigrationStepFrom002To003.java (53%)

diff --git a/common/source/java/ch/systemsx/cisd/common/Script.java b/common/source/java/ch/systemsx/cisd/common/Script.java
index 734bfccdfb9..ceedf7dc31d 100644
--- a/common/source/java/ch/systemsx/cisd/common/Script.java
+++ b/common/source/java/ch/systemsx/cisd/common/Script.java
@@ -28,37 +28,37 @@ public class Script
 {
     private final String name;
 
-    private final String code;
+    private final String content;
 
     private final String version;
 
     /**
-     * Creates an instance for the specified script name, code and version.
+     * Creates an instance for the specified script name, content and version.
      */
-    public Script(String name, String code)
+    public Script(final String name, final String content)
     {
-        this(name, code, "-");
+        this(name, content, "-");
     }
 
     /**
      * Creates an instance for the specified script name, code and version.
      */
-    public Script(String name, String code, String version)
+    public Script(final String name, final String content, final String version)
     {
         assert name != null;
-        assert code != null;
+        assert content != null;
         assert version != null;
         this.name = name;
-        this.code = code;
+        this.content = content;
         this.version = version;
     }
 
     /**
      * Returns script code.
      */
-    public String getCode()
+    public String getContent()
     {
-        return code;
+        return content;
     }
 
     /**
@@ -78,7 +78,7 @@ public class Script
     }
 
     @Override
-    public boolean equals(Object obj)
+    public boolean equals(final Object obj)
     {
         return EqualsBuilder.reflectionEquals(this, obj);
     }
diff --git a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/DBMigrationEngine.java b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/DBMigrationEngine.java
index 8485a5e4167..a2ee43e235f 100644
--- a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/DBMigrationEngine.java
+++ b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/DBMigrationEngine.java
@@ -24,9 +24,9 @@ import ch.systemsx.cisd.common.Script;
 import ch.systemsx.cisd.common.db.ISqlScriptExecutor;
 import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
-import ch.systemsx.cisd.common.exceptions.Status;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.dbmigration.java.IMigrationStepExecutor;
 
 /**
  * Class for creating and migrating a database.
@@ -72,7 +72,7 @@ public final class DBMigrationEngine
 
     private final ISqlScriptExecutor scriptExecutor;
 
-    private final IJavaMigrationStepExecutor javaMigrationStepExecutor;
+    private final IMigrationStepExecutor migrationStepExecutor;
 
     /**
      * Creates an instance for the specified DAO factory and SQL script provider.
@@ -86,7 +86,7 @@ public final class DBMigrationEngine
         adminDAO = daoFactory.getDatabaseDAO();
         logDAO = daoFactory.getDatabaseVersionLogDAO();
         scriptExecutor = daoFactory.getSqlScriptExecutor();
-        javaMigrationStepExecutor = daoFactory.getJavaMigrationStepExecutor();
+        migrationStepExecutor = daoFactory.getMigrationStepExecutor();
         this.scriptProvider = scriptProvider;
         this.shouldCreateFromScratch = shouldCreateFromScratch;
     }
@@ -255,13 +255,11 @@ public final class DBMigrationEngine
                 throw new EnvironmentFailureException(message);
             }
             final long time = System.currentTimeMillis();
-            final Status preMigrationStatusOrNull =
-                    javaMigrationStepExecutor.tryPerformPreMigration(migrationScript);
-            checkErrors(preMigrationStatusOrNull, "pre");
+            migrationStepExecutor.init(migrationScript);
+            migrationStepExecutor.performPreMigration();
             scriptExecutor.execute(migrationScript, true, logDAO);
-            final Status postMigrationStatusOrNull =
-                    javaMigrationStepExecutor.tryPerformPostMigration(migrationScript);
-            checkErrors(postMigrationStatusOrNull, "post");
+            migrationStepExecutor.performPostMigration();
+            migrationStepExecutor.finish();
             if (operationLog.isInfoEnabled())
             {
                 operationLog.info("Successfully migrated from version " + version + " to "
@@ -271,25 +269,6 @@ public final class DBMigrationEngine
         } while (version.equals(toVersion) == false);
     }
 
-    private void checkErrors(final Status migrationStatusOrNull, final String prefix)
-    {
-        if (migrationStatusOrNull != null)
-        {
-            if (migrationStatusOrNull.isError())
-            {
-                final String message =
-                        String.format("Java %s-migration finnished with an error status ('%s')",
-                                prefix, migrationStatusOrNull.tryGetErrorMessage());
-                operationLog.error(message);
-                throw new EnvironmentFailureException(message);
-            } else if (operationLog.isInfoEnabled())
-            {
-                operationLog.info(String.format("Java %s-migration succesfull.", prefix));
-            }
-
-        }
-    }
-
     @Private
     final static String increment(final String version)
     {
diff --git a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/DatabaseVersionLogDAO.java b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/DatabaseVersionLogDAO.java
index 79f86a65e99..7f1a3e8bd4d 100644
--- a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/DatabaseVersionLogDAO.java
+++ b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/DatabaseVersionLogDAO.java
@@ -135,7 +135,7 @@ public class DatabaseVersionLogDAO extends SimpleJdbcDaoSupport implements IData
     public void createTable(Script script)
     {
         JdbcTemplate template = getJdbcTemplate();
-        template.execute(script.getCode());
+        template.execute(script.getContent());
     }
 
     public LogEntry getLastEntry()
@@ -167,7 +167,7 @@ public class DatabaseVersionLogDAO extends SimpleJdbcDaoSupport implements IData
                             ps.setString(3, LogEntry.RunStatus.START.toString());
                             ps.setTimestamp(4, new Timestamp(System.currentTimeMillis()));
                             lobCreator
-                                    .setBlobAsBytes(ps, 5, getAsByteArray(moduleScript.getCode()));
+                                    .setBlobAsBytes(ps, 5, getAsByteArray(moduleScript.getContent()));
                         }
                     };
         template.execute("insert into " + DB_VERSION_LOG + " (" + DB_VERSION + "," + MODULE_NAME
diff --git a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/IDAOFactory.java b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/IDAOFactory.java
index bea2fdb05d2..200168f2424 100644
--- a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/IDAOFactory.java
+++ b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/IDAOFactory.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.dbmigration;
 
 import ch.systemsx.cisd.common.db.ISqlScriptExecutor;
+import ch.systemsx.cisd.dbmigration.java.IMigrationStepExecutor;
 
 /**
  * Factory for DAOs.
@@ -48,5 +49,5 @@ public interface IDAOFactory
     /**
      * Returns the java migration step executor.
      */
-    public IJavaMigrationStepExecutor getJavaMigrationStepExecutor();
+    public IMigrationStepExecutor getMigrationStepExecutor();
 }
diff --git a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/JavaMigrationStepExecutor.java b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/JavaMigrationStepExecutor.java
deleted file mode 100644
index 54841948366..00000000000
--- a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/JavaMigrationStepExecutor.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright 2007 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.dbmigration;
-
-import java.util.Arrays;
-import java.util.List;
-
-import javax.sql.DataSource;
-
-import org.apache.commons.lang.StringUtils;
-import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
-
-import ch.systemsx.cisd.common.Script;
-import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
-import ch.systemsx.cisd.common.exceptions.Status;
-import ch.systemsx.cisd.common.utilities.ClassUtils;
-
-/**
- * Allows to extract {@link IMigrationStep} class from migration script and run the <i>pre</i>- and
- * <i>post</i>- migration java steps.<br>
- * Example of the script containing Java Migration Step definition:
- * 
- * <pre>
- * -- JAVA ch.systemsx.cisd.openbis.db.migration.MigrationStepFrom022To023
- * </pre>
- * 
- * @author Izabela Adamczyk
- */
-public class JavaMigrationStepExecutor extends SimpleJdbcDaoSupport implements
-        IJavaMigrationStepExecutor
-{
-    private static final String JAVA_MIGRATION_STEP_PREFIX = "--JAVA";
-
-    public JavaMigrationStepExecutor(final DataSource dataSource)
-    {
-        setDataSource(dataSource);
-    }
-
-    private IMigrationStep tryExtractMigrationStep(final Script sqlScript)
-
-    {
-        if (sqlScript == null || StringUtils.isBlank(sqlScript.getCode()))
-        {
-            return null;
-        }
-        final String code = sqlScript.getCode();
-        final List<String> lines = Arrays.asList(code.split("\n"));
-        IMigrationStep extratedMigrationStepOrNull = null;
-        boolean nonEmptyLineFound = false;
-        for (final String line : lines)
-        {
-            // blank lines are allowed at the beginning of the script
-            if (StringUtils.isBlank(line))
-            {
-                continue;
-            }
-            // only the first non-blank line is supposed to contain Java Migration Step
-            if (nonEmptyLineFound == false)
-            {
-                extratedMigrationStepOrNull = tryExtractMigrationStepFromLine(line);
-                nonEmptyLineFound = true;
-            } else
-            {
-                checkIfCurrentLineConsistentWithAlredyProcessed(sqlScript,
-                        extratedMigrationStepOrNull, line);
-            }
-        }
-        return extratedMigrationStepOrNull;
-    }
-
-    private void checkIfCurrentLineConsistentWithAlredyProcessed(final Script sqlScript,
-            final IMigrationStep extratedMigrationStepOrNull, final String line)
-    {
-        if (tryExtractMigrationStepFromLine(line) != null)
-        {
-            final String msg;
-            if (extratedMigrationStepOrNull != null)
-            {
-
-                msg =
-                        String.format("Migration script '%s' contains more "
-                                + "than one Java Migration Steps.", sqlScript.getName());
-            } else
-            {
-                msg =
-                        String.format("Java Migration Step should be defined in the first "
-                                + "non-blank line of the migration script '%s'.", sqlScript
-                                .getName());
-            }
-            throw new EnvironmentFailureException(msg);
-        }
-    }
-
-    private final IMigrationStep tryExtractMigrationStepFromLine(final String lineToProcess)
-    {
-        final String line = StringUtils.deleteWhitespace(lineToProcess);
-        if (line != null && line.startsWith(JAVA_MIGRATION_STEP_PREFIX))
-        {
-            final String className = StringUtils.removeStart(line, JAVA_MIGRATION_STEP_PREFIX);
-            try
-            {
-                return (IMigrationStep) ClassUtils.createInstance(Class.forName(className));
-            } catch (final ClassNotFoundException ex)
-            {
-                throw new EnvironmentFailureException(String.format("Class '%s' not found.",
-                        className));
-            } catch (final RuntimeException ex)
-            {
-                throw new EnvironmentFailureException(ex.getMessage());
-            }
-        } else
-        {
-            return null;
-        }
-    }
-
-    //
-    // IJavaMigrationStepExecutor
-    //
-
-    /**
-     * Returns null if MigrationStep has not been found and status returned by
-     * {@link  IMigrationStep#performPreMigration(org.springframework.jdbc.core.simple.SimpleJdbcTemplate)}
-     * otherwise.
-     */
-    public final Status tryPerformPreMigration(final Script sqlScript)
-
-    {
-        final IMigrationStep migrationStep = tryExtractMigrationStep(sqlScript);
-        if (migrationStep != null)
-        {
-            final Status preMigrationStatus =
-                    migrationStep.performPreMigration(getSimpleJdbcTemplate());
-            return preMigrationStatus;
-        } else
-        {
-            return null;
-        }
-    }
-
-    /**
-     * Returns null if MigrationStep has not been found and status returned by
-     * {@link  IMigrationStep#performPostMigration(org.springframework.jdbc.core.simple.SimpleJdbcTemplate)}
-     * otherwise.
-     */
-    public final Status tryPerformPostMigration(final Script sqlScript)
-    {
-        final IMigrationStep migrationStep = tryExtractMigrationStep(sqlScript);
-        if (migrationStep != null)
-        {
-            final Status postMigrationStatus =
-                    migrationStep.performPostMigration(getSimpleJdbcTemplate());
-            return postMigrationStatus;
-        } else
-        {
-            return null;
-        }
-    }
-
-}
diff --git a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/SqlScriptExecutor.java b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/SqlScriptExecutor.java
index 544550c755e..803cecd0a53 100644
--- a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/SqlScriptExecutor.java
+++ b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/SqlScriptExecutor.java
@@ -62,7 +62,7 @@ public class SqlScriptExecutor extends JdbcDaoSupport implements ISqlScriptExecu
         }
         try
         {
-            final String sqlScriptCode = sqlScript.getCode();
+            final String sqlScriptCode = sqlScript.getContent();
             if (singleStepMode && honorSingleStepMode)
             {
                 String lastSqlStatement = "";
diff --git a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/h2/H2DAOFactory.java b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/h2/H2DAOFactory.java
index 27863e57017..72a0fdf34ad 100644
--- a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/h2/H2DAOFactory.java
+++ b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/h2/H2DAOFactory.java
@@ -27,10 +27,10 @@ import ch.systemsx.cisd.dbmigration.DatabaseVersionLogDAO;
 import ch.systemsx.cisd.dbmigration.IDAOFactory;
 import ch.systemsx.cisd.dbmigration.IDatabaseAdminDAO;
 import ch.systemsx.cisd.dbmigration.IDatabaseVersionLogDAO;
-import ch.systemsx.cisd.dbmigration.IJavaMigrationStepExecutor;
 import ch.systemsx.cisd.dbmigration.IMassUploader;
-import ch.systemsx.cisd.dbmigration.JavaMigrationStepExecutor;
 import ch.systemsx.cisd.dbmigration.SqlScriptExecutor;
+import ch.systemsx.cisd.dbmigration.java.IMigrationStepExecutor;
+import ch.systemsx.cisd.dbmigration.java.MigrationStepExecutor;
 
 /**
  * Implementation of {@link IDAOFactory} for H2.
@@ -47,7 +47,7 @@ public class H2DAOFactory implements IDAOFactory
 
     private final IMassUploader massUploader;
 
-    private final IJavaMigrationStepExecutor javaMigrationStepExecutor;
+    private final IMigrationStepExecutor javaMigrationStepExecutor;
 
     /**
      * Creates an instance based on the specified configuration context.
@@ -56,7 +56,7 @@ public class H2DAOFactory implements IDAOFactory
     {
         final DataSource dataSource = context.getDataSource();
         sqlScriptExecutor = new SqlScriptExecutor(dataSource, context.isScriptSingleStepMode());
-        javaMigrationStepExecutor = new JavaMigrationStepExecutor(dataSource);
+        javaMigrationStepExecutor = new MigrationStepExecutor(dataSource);
         databaseVersionLogDAO = new DatabaseVersionLogDAO(dataSource, context.getLobHandler());
         try
         {
@@ -90,7 +90,7 @@ public class H2DAOFactory implements IDAOFactory
         return massUploader;
     }
 
-    public IJavaMigrationStepExecutor getJavaMigrationStepExecutor()
+    public IMigrationStepExecutor getMigrationStepExecutor()
     {
         return javaMigrationStepExecutor;
     }
diff --git a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/IMigrationStep.java b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/java/IMigrationStep.java
similarity index 81%
rename from dbmigration/source/java/ch/systemsx/cisd/dbmigration/IMigrationStep.java
rename to dbmigration/source/java/ch/systemsx/cisd/dbmigration/java/IMigrationStep.java
index a4a727c4abd..7b9aa7389d0 100644
--- a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/IMigrationStep.java
+++ b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/java/IMigrationStep.java
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.dbmigration;
+package ch.systemsx.cisd.dbmigration.java;
 
+import org.springframework.dao.DataAccessException;
 import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
-import ch.systemsx.cisd.common.exceptions.Status;
-
 /**
  * An interface which must be implemented by all classes providing Java code that performs migration
  * steps prior (<i>pre</i>) or after (<i>post</i>) the SQL migration script ran.
@@ -44,11 +43,12 @@ public interface IMigrationStep
     /**
      * Called before the SQL migration is performed.
      */
-    public Status performPreMigration(final SimpleJdbcTemplate simpleJdbcTemplate);
+    public void performPreMigration(final SimpleJdbcTemplate simpleJdbcTemplate)
+            throws DataAccessException;
 
     /**
      * Called after the SQL migration has been performed.
      */
-    public Status performPostMigration(final SimpleJdbcTemplate simpleJdbcTemplate);
-
+    public void performPostMigration(final SimpleJdbcTemplate simpleJdbcTemplate)
+            throws DataAccessException;
 }
diff --git a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/IJavaMigrationStepExecutor.java b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/java/IMigrationStepExecutor.java
similarity index 62%
rename from dbmigration/source/java/ch/systemsx/cisd/dbmigration/IJavaMigrationStepExecutor.java
rename to dbmigration/source/java/ch/systemsx/cisd/dbmigration/java/IMigrationStepExecutor.java
index 4f6df71730d..20bc5998d63 100644
--- a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/IJavaMigrationStepExecutor.java
+++ b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/java/IMigrationStepExecutor.java
@@ -14,26 +14,39 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.dbmigration;
+package ch.systemsx.cisd.dbmigration.java;
 
 import ch.systemsx.cisd.common.Script;
-import ch.systemsx.cisd.common.exceptions.Status;
 
 /**
  * A migration step executor.
  * 
  * @author Christian Ribeaud
  */
-public interface IJavaMigrationStepExecutor
+public interface IMigrationStepExecutor
 {
 
+    /**
+     * Initializes the migration step executor with given <var>migrationScript</var>.
+     * <p>
+     * Is called just before {@link #performPreMigration()} and/or {@link #performPostMigration()}.
+     * </p>
+     */
+    public void init(final Script migrationScript);
+
     /**
      * Performs some step after the migration has happened.
      */
-    public Status tryPerformPostMigration(final Script sqlScript);
+    public void performPostMigration();
 
     /**
      * Performs some step before the migration has happened.
      */
-    public Status tryPerformPreMigration(final Script sqlScript);
+    public void performPreMigration();
+
+    /**
+     * Resets the migration step executor.
+     */
+    public void finish();
+
 }
diff --git a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/java/MigrationStepExecutor.java b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/java/MigrationStepExecutor.java
new file mode 100644
index 00000000000..c96289cbd82
--- /dev/null
+++ b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/java/MigrationStepExecutor.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2007 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.dbmigration.java;
+
+import java.io.StringReader;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
+
+import ch.systemsx.cisd.common.Script;
+import ch.systemsx.cisd.common.exceptions.CheckedExceptionTunnel;
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.common.parser.Line;
+import ch.systemsx.cisd.common.parser.ParserUtilities;
+import ch.systemsx.cisd.common.parser.filter.NonEmptyLineFilter;
+import ch.systemsx.cisd.common.utilities.ClassUtils;
+
+/**
+ * Allows to extract {@link IMigrationStep} class from migration script and run the <i>pre</i>- and
+ * <i>post</i>- migration java steps.<br>
+ * Example of the script containing Java Migration Step definition:
+ * 
+ * <pre>
+ * -- JAVA ch.systemsx.cisd.openbis.db.migration.MigrationStepFrom022To023
+ * </pre>
+ * 
+ * @author Izabela Adamczyk
+ */
+public class MigrationStepExecutor extends SimpleJdbcDaoSupport implements IMigrationStepExecutor
+{
+    private static final Logger operationLog =
+            LogFactory.getLogger(LogCategory.OPERATION, MigrationStepExecutor.class);
+
+    private static final String JAVA_MIGRATION_STEP_PREFIX = "--JAVA";
+
+    private IMigrationStep migrationStep;
+
+    private boolean inited;
+
+    public MigrationStepExecutor(final DataSource dataSource)
+    {
+        setDataSource(dataSource);
+    }
+
+    private final static IMigrationStep tryExtractMigrationStep(final Script sqlScript)
+
+    {
+        assert sqlScript != null : "SQL script not provided";
+        final String content = sqlScript.getContent();
+        if (StringUtils.isBlank(content))
+        {
+            return null;
+        }
+        final Line firstNonEmptyLineOrNull =
+                ParserUtilities.tryGetFirstAcceptedLine(new StringReader(content),
+                        NonEmptyLineFilter.INSTANCE);
+        if (firstNonEmptyLineOrNull != null)
+        {
+            return tryExtractMigrationStepFromLine(firstNonEmptyLineOrNull.getText());
+        }
+        return null;
+    }
+
+    private final static IMigrationStep tryExtractMigrationStepFromLine(final String lineToProcess)
+    {
+        final String line = StringUtils.deleteWhitespace(lineToProcess);
+        if (line != null && line.startsWith(JAVA_MIGRATION_STEP_PREFIX))
+        {
+            final String className = StringUtils.removeStart(line, JAVA_MIGRATION_STEP_PREFIX);
+            try
+            {
+                return (IMigrationStep) ClassUtils.createInstance(Class.forName(className));
+            } catch (final ClassNotFoundException ex)
+            {
+                throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+            }
+        } else
+        {
+            return null;
+        }
+    }
+
+    //
+    // IMigrationStepExecutor
+    //
+
+    public final void init(final Script migrationScript)
+    {
+        migrationStep = tryExtractMigrationStep(migrationScript);
+        if (migrationStep != null)
+        {
+            operationLog.info(String.format(
+                    "Migration step class '%s' found for migration script '%s'.", migrationStep
+                            .getClass().getSimpleName(), migrationScript.getName()));
+        } else
+        {
+            operationLog.debug(String.format(
+                    "No migration step class found for migration script '%s'.", migrationScript
+                            .getName()));
+        }
+        inited = true;
+    }
+
+    public final void performPreMigration()
+    {
+        assert inited : "Executor not initialized.";
+        if (migrationStep != null)
+        {
+            migrationStep.performPreMigration(getSimpleJdbcTemplate());
+        }
+    }
+
+    public final void performPostMigration()
+    {
+        assert inited : "Executor not initialized.";
+        if (migrationStep != null)
+        {
+            migrationStep.performPostMigration(getSimpleJdbcTemplate());
+        }
+    }
+
+    public final void finish()
+    {
+        inited = false;
+    }
+}
diff --git a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/postgresql/PostgreSQLDAOFactory.java b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/postgresql/PostgreSQLDAOFactory.java
index 60e5da6698b..4226b9683bb 100644
--- a/dbmigration/source/java/ch/systemsx/cisd/dbmigration/postgresql/PostgreSQLDAOFactory.java
+++ b/dbmigration/source/java/ch/systemsx/cisd/dbmigration/postgresql/PostgreSQLDAOFactory.java
@@ -27,10 +27,10 @@ import ch.systemsx.cisd.dbmigration.DatabaseVersionLogDAO;
 import ch.systemsx.cisd.dbmigration.IDAOFactory;
 import ch.systemsx.cisd.dbmigration.IDatabaseAdminDAO;
 import ch.systemsx.cisd.dbmigration.IDatabaseVersionLogDAO;
-import ch.systemsx.cisd.dbmigration.IJavaMigrationStepExecutor;
 import ch.systemsx.cisd.dbmigration.IMassUploader;
-import ch.systemsx.cisd.dbmigration.JavaMigrationStepExecutor;
 import ch.systemsx.cisd.dbmigration.SqlScriptExecutor;
+import ch.systemsx.cisd.dbmigration.java.IMigrationStepExecutor;
+import ch.systemsx.cisd.dbmigration.java.MigrationStepExecutor;
 
 /**
  * Implementation of {@link IDAOFactory} for PostgreSQL.
@@ -47,7 +47,7 @@ public class PostgreSQLDAOFactory implements IDAOFactory
 
     private final IMassUploader massUploader;
 
-    private final IJavaMigrationStepExecutor javaMigrationStepExecutor;
+    private final IMigrationStepExecutor migrationStepExecutor;
 
     /**
      * Creates an instance based on the specified configuration context.
@@ -56,7 +56,7 @@ public class PostgreSQLDAOFactory implements IDAOFactory
     {
         final DataSource dataSource = context.getDataSource();
         sqlScriptExecutor = new SqlScriptExecutor(dataSource, context.isScriptSingleStepMode());
-        javaMigrationStepExecutor = new JavaMigrationStepExecutor(dataSource);
+        migrationStepExecutor = new MigrationStepExecutor(dataSource);
         databaseVersionLogDAO = new DatabaseVersionLogDAO(dataSource, context.getLobHandler());
         try
         {
@@ -91,9 +91,9 @@ public class PostgreSQLDAOFactory implements IDAOFactory
         return massUploader;
     }
 
-    public IJavaMigrationStepExecutor getJavaMigrationStepExecutor()
+    public IMigrationStepExecutor getMigrationStepExecutor()
     {
-        return javaMigrationStepExecutor;
+        return migrationStepExecutor;
     }
 
 }
diff --git a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/DBMigrationEngineTest.java b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/DBMigrationEngineTest.java
index bce3d3e46df..0dd11e5d61d 100644
--- a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/DBMigrationEngineTest.java
+++ b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/DBMigrationEngineTest.java
@@ -18,16 +18,18 @@ package ch.systemsx.cisd.dbmigration;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertSame;
-import static org.testng.AssertJUnit.assertTrue;
 import static org.testng.AssertJUnit.fail;
 
 import java.io.File;
 import java.sql.SQLException;
 import java.util.Date;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Level;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.EmptyResultDataAccessException;
 import org.springframework.jdbc.BadSqlGrammarException;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
@@ -38,9 +40,9 @@ import ch.systemsx.cisd.common.Script;
 import ch.systemsx.cisd.common.db.ISqlScriptExecutor;
 import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
-import ch.systemsx.cisd.common.exceptions.Status;
 import ch.systemsx.cisd.common.logging.BufferedAppender;
 import ch.systemsx.cisd.common.utilities.OSUtilities;
+import ch.systemsx.cisd.dbmigration.java.IMigrationStepExecutor;
 
 /**
  * Tests of {@link DBMigrationEngine} using mocks for database and {@link SqlScriptProvider}.
@@ -64,11 +66,11 @@ public class DBMigrationEngineTest
                 final boolean honorSingleStepMode)
         {
             will(returnValue(script));
-            one(javaMigrationStepExecutor).tryPerformPreMigration(script);
-            will(returnValue(Status.OK));
+            one(migrationStepExecutor).init(script);
+            one(migrationStepExecutor).performPreMigration();
             one(scriptExecutor).execute(script, honorSingleStepMode, logDAO);
-            one(javaMigrationStepExecutor).tryPerformPostMigration(script);
-            will(returnValue(Status.OK));
+            one(migrationStepExecutor).performPostMigration();
+            one(migrationStepExecutor).finish();
         }
     }
 
@@ -84,7 +86,7 @@ public class DBMigrationEngineTest
 
     private ISqlScriptExecutor scriptExecutor;
 
-    private IJavaMigrationStepExecutor javaMigrationStepExecutor;
+    private IMigrationStepExecutor migrationStepExecutor;
 
     private BufferedAppender logRecorder;
 
@@ -97,7 +99,7 @@ public class DBMigrationEngineTest
         adminDAO = context.mock(IDatabaseAdminDAO.class);
         logDAO = context.mock(IDatabaseVersionLogDAO.class);
         scriptExecutor = context.mock(ISqlScriptExecutor.class);
-        javaMigrationStepExecutor = context.mock(IJavaMigrationStepExecutor.class);
+        migrationStepExecutor = context.mock(IMigrationStepExecutor.class);
         logRecorder = new BufferedAppender("%-5p %c - %m%n", Level.DEBUG);
     }
 
@@ -132,8 +134,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(adminDAO).dropDatabase();
                     one(logDAO).canConnectToDatabase();
@@ -159,13 +161,11 @@ public class DBMigrationEngineTest
         final DBMigrationEngine migrationEngine =
                 new DBMigrationEngine(daoFactory, scriptProvider, true);
         migrationEngine.migrateTo(version);
-        assertEquals(
-                "INFO  OPERATION.DBMigrationEngine - Dropping database."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - "
-                        + "Database 'my 1. database' does not exist." + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - "
-                        + "Database 'my 2. database' version 042 has been successfully created.",
+        assertEquals("INFO  OPERATION.DBMigrationEngine - Dropping database."
+                + OSUtilities.LINE_SEPARATOR + "INFO  OPERATION.DBMigrationEngine - "
+                + "Database 'my 1. database' does not exist." + OSUtilities.LINE_SEPARATOR
+                + "INFO  OPERATION.DBMigrationEngine - "
+                + "Database 'my 2. database' version 042 has been successfully created.",
                 logRecorder.getLogContent());
 
         context.assertIsSatisfied();
@@ -184,8 +184,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(adminDAO).dropDatabase();
                     one(logDAO).canConnectToDatabase();
@@ -207,13 +207,11 @@ public class DBMigrationEngineTest
         final DBMigrationEngine migrationEngine =
                 new DBMigrationEngine(daoFactory, scriptProvider, true);
         migrationEngine.migrateTo(version);
-        assertEquals(
-                "INFO  OPERATION.DBMigrationEngine - Dropping database."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - "
-                        + "Database 'my 1. database' does not exist." + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - "
-                        + "Database 'my 2. database' version 042 has been successfully created.",
+        assertEquals("INFO  OPERATION.DBMigrationEngine - Dropping database."
+                + OSUtilities.LINE_SEPARATOR + "INFO  OPERATION.DBMigrationEngine - "
+                + "Database 'my 1. database' does not exist." + OSUtilities.LINE_SEPARATOR
+                + "INFO  OPERATION.DBMigrationEngine - "
+                + "Database 'my 2. database' version 042 has been successfully created.",
                 logRecorder.getLogContent());
 
         context.assertIsSatisfied();
@@ -235,8 +233,8 @@ public class DBMigrationEngineTest
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
 
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(adminDAO).dropDatabase();
                     one(logDAO).canConnectToDatabase();
@@ -257,11 +255,9 @@ public class DBMigrationEngineTest
         {
             assertSame(exception, e);
         }
-        assertEquals(
-                "INFO  OPERATION.DBMigrationEngine - Dropping database."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - "
-                        + "Database 'my 1. database' does not exist.", logRecorder.getLogContent());
+        assertEquals("INFO  OPERATION.DBMigrationEngine - Dropping database."
+                + OSUtilities.LINE_SEPARATOR + "INFO  OPERATION.DBMigrationEngine - "
+                + "Database 'my 1. database' does not exist.", logRecorder.getLogContent());
 
         context.assertIsSatisfied();
     }
@@ -279,8 +275,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(logDAO).canConnectToDatabase();
                     will(returnValue(false));
@@ -326,8 +322,8 @@ public class DBMigrationEngineTest
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
 
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(logDAO).canConnectToDatabase();
                     will(returnValue(false));
@@ -374,8 +370,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(logDAO).canConnectToDatabase();
                     will(returnValue(false));
@@ -402,8 +398,7 @@ public class DBMigrationEngineTest
         }
         assertEquals("INFO  OPERATION.DBMigrationEngine - "
                 + "Database 'my 1. database' does not exist." + OSUtilities.LINE_SEPARATOR
-                + "ERROR OPERATION.DBMigrationEngine - " + message,
-                logRecorder.getLogContent());
+                + "ERROR OPERATION.DBMigrationEngine - " + message, logRecorder.getLogContent());
 
         context.assertIsSatisfied();
     }
@@ -421,8 +416,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(logDAO).canConnectToDatabase();
                     will(returnValue(true));
@@ -441,11 +436,10 @@ public class DBMigrationEngineTest
                 new DBMigrationEngine(daoFactory, scriptProvider, false);
 
         migrationEngine.migrateTo(version);
-        assertEquals(
-                "DEBUG OPERATION.DBMigrationEngine - "
-                        + "No migration needed for database 'my database'. It has the right version (042)."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - Using database 'my database URL'",
+        assertEquals("DEBUG OPERATION.DBMigrationEngine - "
+                + "No migration needed for database 'my database'. It has the right version (042)."
+                + OSUtilities.LINE_SEPARATOR
+                + "INFO  OPERATION.DBMigrationEngine - Using database 'my database URL'",
                 logRecorder.getLogContent());
 
         context.assertIsSatisfied();
@@ -465,8 +459,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(logDAO).canConnectToDatabase();
                     will(returnValue(true));
@@ -497,28 +491,16 @@ public class DBMigrationEngineTest
         migrationEngine.migrateTo(toVersion);
         String logContent = logRecorder.getLogContent();
         logContent = logContent.replaceAll("\\d+ msec", "0 msec");
-        assertEquals(
-                "INFO  OPERATION.DBMigrationEngine - "
-                        + "Trying to migrate database 'my 1. database' from version 099 to 101."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - Java pre-migration succesfull."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - Java post-migration succesfull."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - "
-                        + "Successfully migrated from version 099 to 100 in 0 msec"
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - Java pre-migration succesfull."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - Java post-migration succesfull."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - "
-                        + "Successfully migrated from version 100 to 101 in 0 msec"
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - "
-                        + "Database 'my 2. database' successfully migrated from version 099 to 101."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - Using database 'my database URL'",
+        assertEquals("INFO  OPERATION.DBMigrationEngine - "
+                + "Trying to migrate database 'my 1. database' from version 099 to 101."
+                + OSUtilities.LINE_SEPARATOR + "INFO  OPERATION.DBMigrationEngine - "
+                + "Successfully migrated from version 099 to 100 in 0 msec"
+                + OSUtilities.LINE_SEPARATOR + "INFO  OPERATION.DBMigrationEngine - "
+                + "Successfully migrated from version 100 to 101 in 0 msec"
+                + OSUtilities.LINE_SEPARATOR + "INFO  OPERATION.DBMigrationEngine - "
+                + "Database 'my 2. database' successfully migrated from version 099 to 101."
+                + OSUtilities.LINE_SEPARATOR
+                + "INFO  OPERATION.DBMigrationEngine - Using database 'my database URL'",
                 logContent);
 
         context.assertIsSatisfied();
@@ -538,8 +520,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(logDAO).canConnectToDatabase();
                     will(returnValue(true));
@@ -555,40 +537,29 @@ public class DBMigrationEngineTest
 
                     will(returnValue(script));
 
-                    one(javaMigrationStepExecutor).tryPerformPreMigration(script);
-                    will(returnValue(Status.OK));
+                    one(migrationStepExecutor).init(script);
+                    one(migrationStepExecutor).performPreMigration();
                     one(scriptExecutor).execute(script, true, logDAO);
 
-                    one(javaMigrationStepExecutor).tryPerformPostMigration(script);
-                    will(returnValue(Status.createError("Bad system user code.")));
+                    one(migrationStepExecutor).performPostMigration();
+                    will(throwException(new DataIntegrityViolationException(StringUtils.EMPTY)));
                 }
             });
         final DBMigrationEngine migrationEngine =
                 new DBMigrationEngine(daoFactory, scriptProvider, false);
-
-        boolean exceptionThrown = false;
         try
         {
             migrationEngine.migrateTo(toVersion);
-        } catch (final EnvironmentFailureException e)
+            fail();
+        } catch (final DataIntegrityViolationException e)
         {
-            exceptionThrown = true;
-            assertEquals(
-                    "Java post-migration finnished with an error status ('Bad system user code.')",
-                    e.getMessage());
+            // Nothing to do here.
         }
-        assertTrue(exceptionThrown);
         String logContent = logRecorder.getLogContent();
         logContent = logContent.replaceAll("\\d+ msec", "0 msec");
-        assertEquals(
-                "INFO  OPERATION.DBMigrationEngine - "
-                        + "Trying to migrate database 'my 1. database' from version 099 to 101."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "INFO  OPERATION.DBMigrationEngine - Java pre-migration succesfull."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "ERROR OPERATION.DBMigrationEngine - Java post-migration finnished with an error status ('Bad system user code.')",
+        assertEquals("INFO  OPERATION.DBMigrationEngine - "
+                + "Trying to migrate database 'my 1. database' from version 099 to 101.",
                 logContent);
-
         context.assertIsSatisfied();
     }
 
@@ -606,8 +577,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(logDAO).canConnectToDatabase();
                     will(returnValue(true));
@@ -621,30 +592,26 @@ public class DBMigrationEngineTest
                     one(scriptProvider).tryGetMigrationScript(fromVersion, "100");
                     final Script script = new Script("m-099-100", "code 099 100", toVersion);
                     will(returnValue(script));
-                    one(javaMigrationStepExecutor).tryPerformPreMigration(script);
-                    will(returnValue(Status.createError("Bad system user code.")));
+
+                    one(migrationStepExecutor).init(script);
+                    one(migrationStepExecutor).performPreMigration();
+                    will(throwException(new EmptyResultDataAccessException(1)));
                 }
             });
         final DBMigrationEngine migrationEngine =
                 new DBMigrationEngine(daoFactory, scriptProvider, false);
-        boolean exceptionThrown = false;
         try
         {
             migrationEngine.migrateTo(toVersion);
-        } catch (final EnvironmentFailureException e)
+            fail();
+        } catch (final EmptyResultDataAccessException e)
         {
-            exceptionThrown = true;
-            assertEquals(
-                    "Java pre-migration finnished with an error status ('Bad system user code.')",
-                    e.getMessage());
+            // Nothing to do here.
         }
-        assertTrue(exceptionThrown);
         String logContent = logRecorder.getLogContent();
         logContent = logContent.replaceAll("\\d+ msec", "0 msec");
         assertEquals(
-                "INFO  OPERATION.DBMigrationEngine - Trying to migrate database 'my 1. database' from version 099 to 101."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "ERROR OPERATION.DBMigrationEngine - Java pre-migration finnished with an error status ('Bad system user code.')",
+                "INFO  OPERATION.DBMigrationEngine - Trying to migrate database 'my 1. database' from version 099 to 101.",
                 logContent);
 
         context.assertIsSatisfied();
@@ -664,8 +631,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(logDAO).canConnectToDatabase();
                     will(returnValue(true));
@@ -697,8 +664,7 @@ public class DBMigrationEngineTest
         }
         assertEquals("INFO  OPERATION.DBMigrationEngine - "
                 + "Trying to migrate database 'my 1. database' from version 099 to 101."
-                + OSUtilities.LINE_SEPARATOR
-                + "ERROR OPERATION.DBMigrationEngine - "
+                + OSUtilities.LINE_SEPARATOR + "ERROR OPERATION.DBMigrationEngine - "
                 + errorMessage, logRecorder.getLogContent());
 
         context.assertIsSatisfied();
@@ -718,8 +684,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(logDAO).canConnectToDatabase();
                     will(returnValue(true));
@@ -745,8 +711,8 @@ public class DBMigrationEngineTest
         {
             assertEquals(errorMessage, e.getMessage());
         }
-        assertEquals("ERROR OPERATION.DBMigrationEngine - "
-                + errorMessage, logRecorder.getLogContent());
+        assertEquals("ERROR OPERATION.DBMigrationEngine - " + errorMessage, logRecorder
+                .getLogContent());
 
         context.assertIsSatisfied();
     }
@@ -763,8 +729,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(adminDAO).dropDatabase();
                     one(logDAO).canConnectToDatabase();
@@ -784,11 +750,9 @@ public class DBMigrationEngineTest
         {
             assertEquals(message, e.getMessage());
         }
-        assertEquals(
-                "INFO  OPERATION.DBMigrationEngine - Dropping database."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "ERROR OPERATION.DBMigrationEngine - "
-                        + message, logRecorder.getLogContent());
+        assertEquals("INFO  OPERATION.DBMigrationEngine - Dropping database."
+                + OSUtilities.LINE_SEPARATOR + "ERROR OPERATION.DBMigrationEngine - " + message,
+                logRecorder.getLogContent());
 
         context.assertIsSatisfied();
     }
@@ -810,8 +774,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(adminDAO).dropDatabase();
                     one(logDAO).canConnectToDatabase();
@@ -834,11 +798,9 @@ public class DBMigrationEngineTest
         {
             assertEquals(message, e.getMessage());
         }
-        assertEquals(
-                "INFO  OPERATION.DBMigrationEngine - Dropping database."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "ERROR OPERATION.DBMigrationEngine - "
-                        + message, logRecorder.getLogContent());
+        assertEquals("INFO  OPERATION.DBMigrationEngine - Dropping database."
+                + OSUtilities.LINE_SEPARATOR + "ERROR OPERATION.DBMigrationEngine - " + message,
+                logRecorder.getLogContent());
 
         context.assertIsSatisfied();
     }
@@ -861,8 +823,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(adminDAO).dropDatabase();
                     one(logDAO).canConnectToDatabase();
@@ -885,11 +847,9 @@ public class DBMigrationEngineTest
         {
             assertEquals(message, e.getMessage());
         }
-        assertEquals(
-                "INFO  OPERATION.DBMigrationEngine - Dropping database."
-                        + OSUtilities.LINE_SEPARATOR
-                        + "ERROR OPERATION.DBMigrationEngine - "
-                        + message, logRecorder.getLogContent());
+        assertEquals("INFO  OPERATION.DBMigrationEngine - Dropping database."
+                + OSUtilities.LINE_SEPARATOR + "ERROR OPERATION.DBMigrationEngine - " + message,
+                logRecorder.getLogContent());
 
         context.assertIsSatisfied();
     }
@@ -909,8 +869,8 @@ public class DBMigrationEngineTest
                     will(returnValue(logDAO));
                     one(daoFactory).getSqlScriptExecutor();
                     will(returnValue(scriptExecutor));
-                    one(daoFactory).getJavaMigrationStepExecutor();
-                    will(returnValue(javaMigrationStepExecutor));
+                    one(daoFactory).getMigrationStepExecutor();
+                    will(returnValue(migrationStepExecutor));
 
                     one(logDAO).canConnectToDatabase();
                     will(returnValue(true));
@@ -925,7 +885,8 @@ public class DBMigrationEngineTest
                     final Script script = new Script("m-1-2", "code", toVersion);
                     will(returnValue(script));
 
-                    one(javaMigrationStepExecutor).tryPerformPreMigration(script);
+                    one(migrationStepExecutor).init(script);
+                    one(migrationStepExecutor).performPreMigration();
                     one(scriptExecutor).execute(script, true, logDAO);
                     will(throwException(exception));
                 }
diff --git a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/JavaMigrationStepExecutorTest.java b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/JavaMigrationStepExecutorTest.java
deleted file mode 100644
index a1f5a64dac3..00000000000
--- a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/JavaMigrationStepExecutorTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2008 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.dbmigration;
-
-import javax.sql.DataSource;
-
-import org.jmock.Mockery;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import ch.systemsx.cisd.common.Script;
-import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
-import ch.systemsx.cisd.common.exceptions.StatusFlag;
-import ch.systemsx.cisd.common.logging.LogInitializer;
-
-/**
- * Test cases for the {@link JavaMigrationStepExecutor}.
- * 
- * @author Izabela Adamczyk
- */
-public class JavaMigrationStepExecutorTest
-{
-    private Mockery context;
-
-    DataSource dataSource;
-
-    @BeforeMethod
-    public void setUp()
-    {
-        context = new Mockery();
-        dataSource = context.mock(DataSource.class);
-    }
-
-    @BeforeClass(alwaysRun = true)
-    public void beforeClass() throws Exception
-    {
-        LogInitializer.init();
-    }
-
-    @Test
-    public void testHappyCase()
-    {
-        final JavaMigrationStepExecutor javaMigrationStepExecutor =
-                new JavaMigrationStepExecutor(dataSource);
-        final Script script =
-                new Script("001To002.sql",
-                        "-- JAVA ch.systemsx.cisd.dbmigration.MigrationStepFrom001To002");
-        Assert.assertTrue(javaMigrationStepExecutor.tryPerformPreMigration(script).getFlag()
-                .equals(StatusFlag.OK));
-        Assert.assertTrue(javaMigrationStepExecutor.tryPerformPostMigration(script).getFlag()
-                .equals(StatusFlag.OK));
-
-    }
-
-    @Test
-    public void testUnhappyCase()
-    {
-        final JavaMigrationStepExecutor javaMigrationStepExecutor =
-                new JavaMigrationStepExecutor(dataSource);
-        final Script script =
-                new Script("002To003.sql",
-                        "-- JAVA ch.systemsx.cisd.dbmigration.MigrationStepFrom002To003");
-
-        Assert.assertTrue(javaMigrationStepExecutor.tryPerformPreMigration(script).getFlag()
-                .equals(StatusFlag.ERROR));
-        Assert.assertTrue(javaMigrationStepExecutor.tryPerformPreMigration(script)
-                .tryGetErrorMessage().equals("bad pre"));
-
-        Assert.assertTrue(javaMigrationStepExecutor.tryPerformPostMigration(script).getFlag()
-                .equals(StatusFlag.ERROR));
-        Assert.assertTrue(javaMigrationStepExecutor.tryPerformPostMigration(script)
-                .tryGetErrorMessage().equals("bad post"));
-
-    }
-
-    @Test
-    public void testClassNotFound()
-    {
-        final JavaMigrationStepExecutor javaMigrationStepExecutor =
-                new JavaMigrationStepExecutor(dataSource);
-        final Script script =
-                new Script("003To004.sql",
-                        "-- JAVA ch.systemsx.cisd.dbmigration.MigrationStepFrom003To003");
-        boolean exceptionThrown = false;
-        try
-        {
-            javaMigrationStepExecutor.tryPerformPreMigration(script);
-        } catch (final EnvironmentFailureException e)
-        {
-            exceptionThrown = true;
-            Assert.assertEquals(e.getMessage(),
-                    "Class 'ch.systemsx.cisd.dbmigration.MigrationStepFrom003To003' not found.");
-        }
-        Assert.assertTrue(exceptionThrown);
-
-    }
-
-}
diff --git a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/SqlScriptProviderTest.java b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/SqlScriptProviderTest.java
index 357dd09a2de..f0bd9b79ce5 100644
--- a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/SqlScriptProviderTest.java
+++ b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/SqlScriptProviderTest.java
@@ -147,7 +147,7 @@ public class SqlScriptProviderTest
         assertNotNull(script);
         assertEquals(TEMP_SCHEMA_SPECIFIC_SCRIPT_FOLDER.getPath() + "/" + VERSION + "/schema-"
                 + VERSION + ".sql", script.getName());
-        assertEquals("code: schema", script.getCode().trim());
+        assertEquals("code: schema", script.getContent().trim());
     }
 
     // Note: we make it dependent on testGetSchemaScript(), because we delete the specific schema
@@ -167,7 +167,7 @@ public class SqlScriptProviderTest
         assertNotNull(script);
         assertEquals(TEMP_SCHEMA_GENERIC_SCRIPT_FOLDER.getPath() + "/" + VERSION + "/schema-"
                 + VERSION + ".sql", script.getName());
-        assertEquals(genericSchemaScriptContent, script.getCode().trim());
+        assertEquals(genericSchemaScriptContent, script.getContent().trim());
     }
 
     @Test
@@ -183,7 +183,7 @@ public class SqlScriptProviderTest
         assertNotNull(script);
         assertEquals(TEMP_SCHEMA_SPECIFIC_SCRIPT_FOLDER.getPath() + "/" + VERSION + "/function-"
                 + VERSION + ".sql", script.getName());
-        assertEquals("code: function", script.getCode().trim());
+        assertEquals("code: function", script.getContent().trim());
     }
 
     @Test
@@ -198,7 +198,7 @@ public class SqlScriptProviderTest
         Script script = sqlScriptProvider.tryGetDataScript(VERSION);
         assertEquals(TEMP_SCHEMA_SPECIFIC_SCRIPT_FOLDER + "/" + VERSION + "/data-" + VERSION
                 + ".sql", script.getName());
-        assertEquals("code: data", script.getCode().trim());
+        assertEquals("code: data", script.getContent().trim());
     }
 
     @Test
@@ -213,7 +213,7 @@ public class SqlScriptProviderTest
         Script script = sqlScriptProvider.tryGetMigrationScript(VERSION, VERSION2);
         assertEquals(TEMP_SCHEMA_SPECIFIC_SCRIPT_FOLDER.getPath() + "/" + MIGRATION + "/migration-"
                 + VERSION + "-" + VERSION2 + ".sql", script.getName());
-        assertEquals("code: migration", script.getCode().trim());
+        assertEquals("code: migration", script.getContent().trim());
     }
 
     @Test
diff --git a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/java/MigrationStepExecutorTest.java b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/java/MigrationStepExecutorTest.java
new file mode 100644
index 00000000000..533523aec98
--- /dev/null
+++ b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/java/MigrationStepExecutorTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.dbmigration.java;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.fail;
+
+import javax.sql.DataSource;
+
+import org.apache.log4j.Level;
+import org.jmock.Mockery;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.common.Script;
+import ch.systemsx.cisd.common.exceptions.CheckedExceptionTunnel;
+import ch.systemsx.cisd.common.logging.BufferedAppender;
+import ch.systemsx.cisd.common.logging.LogInitializer;
+
+/**
+ * Test cases for the {@link MigrationStepExecutor}.
+ * 
+ * @author Izabela Adamczyk
+ */
+public final class MigrationStepExecutorTest
+{
+    private Mockery context;
+
+    private DataSource dataSource;
+
+    private BufferedAppender logRecorder;
+
+    @BeforeMethod
+    public final void setUp()
+    {
+        context = new Mockery();
+        dataSource = context.mock(DataSource.class);
+        logRecorder = new BufferedAppender("%m%n", Level.DEBUG);
+    }
+
+    @BeforeClass(alwaysRun = true)
+    public final void beforeClass() throws Exception
+    {
+        LogInitializer.init();
+    }
+
+    @Test
+    public final void testHappyCase()
+    {
+        final MigrationStepExecutor migrationStepExecutor = new MigrationStepExecutor(dataSource);
+        Script script =
+                new Script("001To002.sql",
+                        "-- JAVA ch.systemsx.cisd.dbmigration.java.MigrationStepFrom001To002");
+        migrationStepExecutor.init(script);
+        migrationStepExecutor.performPreMigration();
+        migrationStepExecutor.performPostMigration();
+        migrationStepExecutor.finish();
+        assertEquals("Migration step class 'MigrationStepFrom001To002' found for "
+                + "migration script '001To002.sql'.", logRecorder.getLogContent());
+        logRecorder.resetLogContent();
+        script =
+                new Script("001To002.sql", "\n\n  \n"
+                        + "--JAVA ch.systemsx.cisd.dbmigration.java.MigrationStepFrom001To002");
+        migrationStepExecutor.init(script);
+        assertEquals("Migration step class 'MigrationStepFrom001To002' found for "
+                + "migration script '001To002.sql'.", logRecorder.getLogContent());
+    }
+
+    @Test
+    public final void testFinish()
+    {
+        final MigrationStepExecutor migrationStepExecutor = new MigrationStepExecutor(dataSource);
+        final Script script =
+                new Script("001To002.sql",
+                        "--   JAVA ch.systemsx.cisd.dbmigration.java.MigrationStepFrom001To002");
+        migrationStepExecutor.init(script);
+        migrationStepExecutor.performPreMigration();
+        migrationStepExecutor.performPostMigration();
+        migrationStepExecutor.finish();
+        boolean fail = true;
+        try
+        {
+            migrationStepExecutor.performPreMigration();
+        } catch (final AssertionError ex)
+        {
+            fail = false;
+        }
+        assertFalse(fail);
+    }
+
+    @Test
+    public final void testUnhappyCase()
+    {
+        final MigrationStepExecutor migrationStepExecutor = new MigrationStepExecutor(dataSource);
+        Script script =
+                new Script("002To003.sql", "\n-- This is a comment\n"
+                        + "-- JAVA ch.systemsx.cisd.dbmigration.java.MigrationStepFrom002To003");
+        migrationStepExecutor.init(script);
+        assertEquals("No migration step class found for migration script '002To003.sql'.",
+                logRecorder.getLogContent());
+        logRecorder.resetLogContent();
+        script =
+                new Script("002To003.sql",
+                        "-- JAVA ch.systemsx.cisd.dbmigration.java.MigrationStepFrom002To003");
+        migrationStepExecutor.init(script);
+        assertEquals("Migration step class 'MigrationStepFrom002To003' found for "
+                + "migration script '002To003.sql'.", logRecorder.getLogContent());
+        try
+        {
+            migrationStepExecutor.performPreMigration();
+            fail();
+        } catch (final DataIntegrityViolationException ex)
+        {
+            // Nothing to do here.
+        }
+        try
+        {
+            migrationStepExecutor.performPostMigration();
+            fail();
+        } catch (final EmptyResultDataAccessException ex)
+        {
+            // Nothing to do here.
+        }
+    }
+
+    @Test
+    public final void testClassNotFound()
+    {
+        final MigrationStepExecutor migrationStepExecutor = new MigrationStepExecutor(dataSource);
+        final Script script =
+                new Script("003To004.sql",
+                        "-- JAVA ch.systemsx.cisd.dbmigration.java.MigrationStepFrom003To003");
+        try
+        {
+            migrationStepExecutor.init(script);
+            fail();
+        } catch (final CheckedExceptionTunnel e)
+        {
+            // Nothing to do here.
+        }
+    }
+}
diff --git a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/MigrationStepFrom001To002.java b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/java/MigrationStepFrom001To002.java
similarity index 66%
rename from dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/MigrationStepFrom001To002.java
rename to dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/java/MigrationStepFrom001To002.java
index dadcc9f8f41..f82fa54a83c 100644
--- a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/MigrationStepFrom001To002.java
+++ b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/java/MigrationStepFrom001To002.java
@@ -14,32 +14,31 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.dbmigration;
+package ch.systemsx.cisd.dbmigration.java;
 
+import org.springframework.dao.DataAccessException;
 import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
-import ch.systemsx.cisd.common.exceptions.Status;
-
 /**
  * A <code>IMigrationStep</code> implementation for test.
  * 
  * @author Izabela Adamczyk
  */
-public class MigrationStepFrom001To002 implements IMigrationStep
+public final class MigrationStepFrom001To002 implements IMigrationStep
 {
 
     //
     // IMigrationStep
     //
 
-    public final Status performPostMigration(final SimpleJdbcTemplate simpleJdbcTemplate)
+    public final void performPostMigration(final SimpleJdbcTemplate simpleJdbcTemplate)
+            throws DataAccessException
     {
-        return Status.OK;
     }
 
-    public final Status performPreMigration(final SimpleJdbcTemplate simpleJdbcTemplate)
+    public final void performPreMigration(final SimpleJdbcTemplate simpleJdbcTemplate)
+            throws DataAccessException
     {
-        return Status.OK;
     }
 
 }
diff --git a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/MigrationStepFrom002To003.java b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/java/MigrationStepFrom002To003.java
similarity index 53%
rename from dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/MigrationStepFrom002To003.java
rename to dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/java/MigrationStepFrom002To003.java
index 5a182419a6c..27cfe28b346 100644
--- a/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/MigrationStepFrom002To003.java
+++ b/dbmigration/sourceTest/java/ch/systemsx/cisd/dbmigration/java/MigrationStepFrom002To003.java
@@ -14,32 +14,36 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.dbmigration;
+package ch.systemsx.cisd.dbmigration.java;
 
+import org.apache.commons.lang.StringUtils;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.EmptyResultDataAccessException;
 import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
-import ch.systemsx.cisd.common.exceptions.Status;
-
 /**
  * A <code>IMigrationStep</code> implementation for test.
  * 
  * @author Izabela Adamczyk
  */
-public class MigrationStepFrom002To003 implements IMigrationStep
+public final class MigrationStepFrom002To003 implements IMigrationStep
 {
 
     //
     // IMigrationStep
     //
 
-    public final Status performPostMigration(final SimpleJdbcTemplate simpleJdbcTemplate)
+    public final void performPostMigration(final SimpleJdbcTemplate simpleJdbcTemplate)
+            throws DataAccessException
     {
-        return Status.createError("bad post");
+        throw new EmptyResultDataAccessException(1);
     }
 
-    public final Status performPreMigration(final SimpleJdbcTemplate simpleJdbcTemplate)
+    public final void performPreMigration(final SimpleJdbcTemplate simpleJdbcTemplate)
+            throws DataAccessException
     {
-        return Status.createError("bad pre");
+        throw new DataIntegrityViolationException(StringUtils.EMPTY);
     }
 
 }
-- 
GitLab