]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3292 improve messages when database is not up-to-date
authorSimon Brandhof <simon.brandhof@gmail.com>
Wed, 7 Mar 2012 21:13:35 +0000 (22:13 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Wed, 7 Mar 2012 22:30:28 +0000 (23:30 +0100)
26 files changed:
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibility.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibilityTest.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/persistence/BadDatabaseVersion.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/persistence/DatabaseMigrator.java
sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
sonar-core/src/main/java/org/sonar/core/persistence/SchemaMigrationDto.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/persistence/SchemaMigrationMapper.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java
sonar-core/src/main/java/org/sonar/jpa/session/AbstractDatabaseConnector.java
sonar-core/src/main/java/org/sonar/jpa/session/DefaultDatabaseConnector.java
sonar-core/src/main/java/org/sonar/jpa/session/MemoryDatabaseConnector.java
sonar-core/src/main/resources/org/sonar/core/persistence/SchemaMigrationMapper.xml [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/persistence/DatabaseVersionTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/jpa/entity/SchemaMigrationTest.java [deleted file]
sonar-core/src/test/resources/org/sonar/core/persistence/DatabaseVersionTest/getVersion.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/persistence/DatabaseVersionTest/getVersion_no_rows.xml [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/configuration/Backup.java
sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java
sonar-server/src/main/java/org/sonar/server/platform/Platform.java
sonar-server/src/main/webapp/WEB-INF/db/migrate/README.txt
sonar-server/src/test/java/org/sonar/server/platform/DatabaseServerCompatibilityTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java
sonar-server/src/test/java/org/sonar/server/startup/DeleteDeprecatedMeasuresTest.java

index 9f480c8980f4840287f6e77bfc70da0f80137e30..8ca3fe2a087fa2aa889734874dcf06fe04032054 100644 (file)
@@ -27,6 +27,7 @@ import org.sonar.batch.MavenPluginExecutor;
 import org.sonar.batch.ServerMetadata;
 import org.sonar.batch.config.BatchSettings;
 import org.sonar.batch.config.BatchSettingsEnhancer;
+import org.sonar.core.persistence.DatabaseVersion;
 import org.sonar.jpa.session.DatabaseSessionProvider;
 import org.sonar.jpa.session.DefaultDatabaseConnector;
 import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory;
@@ -64,14 +65,20 @@ public class BootstrapModule extends Module {
     // set as the current context classloader for hibernate, else it does not find the JDBC driver.
     Thread.currentThread().setContextClassLoader(bootstrapClassLoader);
 
+    // mybatis
     addCoreSingleton(BatchDatabase.class);
     addCoreSingleton(MyBatis.class);
-    addCoreSingleton(DefaultDatabaseConnector.class);
-    addCoreSingleton(ThreadLocalDatabaseSessionFactory.class);
+    addCoreSingleton(DatabaseVersion.class);
+    addCoreSingleton(DatabaseBatchCompatibility.class);
     for (Class daoClass : DaoUtils.getDaoClasses()) {
       addCoreSingleton(daoClass);
     }
+
+    // hibernate
+    addCoreSingleton(DefaultDatabaseConnector.class);
+    addCoreSingleton(ThreadLocalDatabaseSessionFactory.class);
     addAdapter(new DatabaseSessionProvider());
+
     for (Object component : boostrapperComponents) {
       addCoreSingleton(component);
     }
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibility.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibility.java
new file mode 100644 (file)
index 0000000..683bcda
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.batch.bootstrap;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.api.platform.Server;
+import org.sonar.core.persistence.BadDatabaseVersion;
+import org.sonar.core.persistence.DatabaseVersion;
+
+/**
+ * Detects if database is not up-to-date with the version required by the batch.
+ */
+public class DatabaseBatchCompatibility implements BatchComponent {
+
+  private DatabaseVersion version;
+  private Server server;
+
+  public DatabaseBatchCompatibility(DatabaseVersion version, Server server) {
+    this.version = version;
+    this.server = server;
+  }
+
+  public void start() {
+    DatabaseVersion.Status status = version.getStatus();
+    if (status == DatabaseVersion.Status.REQUIRES_DOWNGRADE) {
+      throw new BadDatabaseVersion("Database relates to a more recent version of Sonar. Please check your settings (JDBC settings, version of Maven plugin)");
+    }
+    if (status == DatabaseVersion.Status.REQUIRES_UPGRADE) {
+      throw new BadDatabaseVersion("Database must be upgraded. Please browse " + server.getURL() + "/setup");
+    }
+    if (status != DatabaseVersion.Status.UP_TO_DATE) {
+      // Support other future values
+      throw new BadDatabaseVersion("Unknown database status: " + status);
+    }
+  }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibilityTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibilityTest.java
new file mode 100644 (file)
index 0000000..2059313
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.batch.bootstrap;
+
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.api.platform.Server;
+import org.sonar.batch.ServerMetadata;
+import org.sonar.core.persistence.BadDatabaseVersion;
+import org.sonar.core.persistence.DatabaseVersion;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DatabaseBatchCompatibilityTest {
+
+  private Server server = new ServerMetadata(new Settings());
+
+  @Test(expected = BadDatabaseVersion.class)
+  public void shouldFailIfRequiresDowngrade() {
+    DatabaseVersion version = mock(DatabaseVersion.class);
+    when(version.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_DOWNGRADE);
+    new DatabaseBatchCompatibility(version, server).start();
+  }
+
+  @Test(expected = BadDatabaseVersion.class)
+  public void shouldFailIfRequiresUpgrade() {
+    DatabaseVersion version = mock(DatabaseVersion.class);
+    when(version.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE);
+    new DatabaseBatchCompatibility(version, server).start();
+  }
+
+  @Test
+  public void shouldDoNothingIfUpToDate() {
+    DatabaseVersion version = mock(DatabaseVersion.class);
+    when(version.getStatus()).thenReturn(DatabaseVersion.Status.UP_TO_DATE);
+    new DatabaseBatchCompatibility(version, server).start();
+    // no error
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/BadDatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/BadDatabaseVersion.java
new file mode 100644 (file)
index 0000000..fee98c3
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.core.persistence;
+
+public final class BadDatabaseVersion extends RuntimeException {
+  public BadDatabaseVersion(String s) {
+    super(s);
+  }
+
+  @Override
+  public Throwable fillInStackTrace() {
+    return this;
+  }
+}
index e2688a408ef4eef835b6cf929668c3fd49dc969b..32b7ba37697016ddacce05a0324b8b6d5fd28b25 100644 (file)
@@ -26,7 +26,8 @@ import org.sonar.api.ServerComponent;
 import java.sql.Connection;
 
 /**
- * Restore schema by executing DDL scripts. Only Derby database is supported. Other databases are created by Ruby on Rails migrations.
+ * Restore schema by executing DDL scripts. Only Derby database is supported. 
+ * Other databases are created by Ruby on Rails migrations.
  *
  * @since 2.12
  */
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
new file mode 100644 (file)
index 0000000..942d41e
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.core.persistence;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.apache.ibatis.session.SqlSession;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.ServerComponent;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @since 2.15
+ */
+public class DatabaseVersion implements BatchComponent, ServerComponent {
+
+  public static final int LAST_VERSION = 263;
+
+  public static enum Status {
+    UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE
+  }
+
+  private MyBatis mybatis;
+
+  public DatabaseVersion(MyBatis mybatis) {
+    this.mybatis = mybatis;
+  }
+
+  public Integer getVersion() {
+    SqlSession session = mybatis.openSession();
+    try {
+      List<Integer> versions = session.getMapper(SchemaMigrationMapper.class).selectVersions();
+      if (!versions.isEmpty()) {
+        Collections.sort(versions);
+        return versions.get(versions.size() - 1);
+      }
+      return null;
+    } catch (Exception e) {
+      // The table SCHEMA_MIGRATIONS does not exist.
+      // Ignore this exception -> it will be created by Ruby on Rails migrations.
+      return null;
+
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  public Status getStatus() {
+    return getStatus(getVersion(), LAST_VERSION);
+  }
+
+  @VisibleForTesting
+  static Status getStatus(Integer currentVersion, int lastVersion) {
+    Status status = Status.REQUIRES_UPGRADE;
+    if (currentVersion != null) {
+      if (currentVersion == lastVersion) {
+        status = Status.UP_TO_DATE;
+      } else if (currentVersion > lastVersion) {
+        status = Status.REQUIRES_DOWNGRADE;
+      }
+    }
+    return status;
+  }
+}
index 073fda4048e09b63eb9b8ccaec7cbe6ba8dec38c..68a0b83adb1c1b775a6820e63bf02d4b0b5c8530 100644 (file)
@@ -75,6 +75,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
     loadAlias(conf, "ResourceIndex", ResourceIndexDto.class);
     loadAlias(conf, "Rule", RuleDto.class);
     loadAlias(conf, "Snapshot", SnapshotDto.class);
+    loadAlias(conf, "SchemaMigration", SchemaMigrationDto.class);
     loadAlias(conf, "Widget", WidgetDto.class);
     loadAlias(conf, "WidgetProperty", WidgetPropertyDto.class);
 
@@ -89,6 +90,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
     loadMapper(conf, ReviewMapper.class);
     loadMapper(conf, ResourceIndexerMapper.class);
     loadMapper(conf, RuleMapper.class);
+    loadMapper(conf, SchemaMigrationMapper.class);
     loadMapper(conf, WidgetMapper.class);
     loadMapper(conf, WidgetPropertyMapper.class);
 
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/SchemaMigrationDto.java b/sonar-core/src/main/java/org/sonar/core/persistence/SchemaMigrationDto.java
new file mode 100644 (file)
index 0000000..2d02562
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.core.persistence;
+
+/**
+ * Maps the table SCHEMA_MIGRATIONS that is fed by Ruby on Rails Migrations
+ * @since 2.15
+ */
+public class SchemaMigrationDto {
+  private String version;//NOSONAR this field is assigned by MyBatis
+
+  public String getVersion() {
+    return version;
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/SchemaMigrationMapper.java b/sonar-core/src/main/java/org/sonar/core/persistence/SchemaMigrationMapper.java
new file mode 100644 (file)
index 0000000..b86ae41
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.core.persistence;
+
+import java.util.List;
+
+public interface SchemaMigrationMapper {
+  List<Integer> selectVersions();
+}
index 8598d2a68e555fcdc131c818821ad3b3c4ea4ca2..979104590be81c5a2c60eebf647682eec5feed80 100644 (file)
@@ -24,22 +24,10 @@ import org.apache.commons.lang.builder.ToStringStyle;
 
 import javax.persistence.*;
 
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-
 @Entity
-@Table(name = SchemaMigration.TABLE_NAME, uniqueConstraints = {@UniqueConstraint(columnNames = {"version"})})
+@Table(name = "schema_migrations", uniqueConstraints = {@UniqueConstraint(columnNames = {"version"})})
 public class SchemaMigration {
 
-  public static final int VERSION_UNKNOWN = -1;
-
-  public static final int LAST_VERSION = 263;
-  public static final int VERSION_2_13 = 241;
-
-  public static final String TABLE_NAME = "schema_migrations";
-
   @Id
   @Column(name = "version", updatable = true)
   private String version;
@@ -56,49 +44,6 @@ public class SchemaMigration {
     this.version = String.valueOf(i);
   }
 
-  public static int getCurrentVersion(Connection connection) {
-    Statement stmt = null;
-    ResultSet rs = null;
-    int version = VERSION_UNKNOWN;
-    try {
-      stmt = connection.createStatement();
-      rs = stmt.executeQuery("SELECT version FROM " + SchemaMigration.TABLE_NAME);
-      while (rs.next()) {
-        int i = Integer.parseInt(rs.getString(1));
-        if (i > version) {
-          version = i;
-        }
-      }
-    } catch (SQLException e) {
-      // ignore
-    } finally {
-      close(rs);
-      close(stmt);
-    }
-
-    return version;
-  }
-
-  private static void close(ResultSet rs) {
-    if (rs != null) {
-      try {
-        rs.close();
-      } catch (SQLException e) {
-        // why does close() throw a checked-exception ???
-      }
-    }
-  }
-
-  private static void close(Statement st) {
-    if (st != null) {
-      try {
-        st.close();
-      } catch (SQLException e) {
-        // why does close() throw a checked-exception ???
-      }
-    }
-  }
-
   @Override
   public String toString() {
     return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
index 7edc135bb2bbc8d047ef47c30d471b3e56448ac7..a7d34a9c2966919c90f2527b30da06158af2292e 100644 (file)
@@ -21,16 +21,13 @@ package org.sonar.jpa.session;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.sonar.api.utils.Logs;
 import org.sonar.core.persistence.Database;
+import org.sonar.core.persistence.DatabaseVersion;
 import org.sonar.core.persistence.dialect.Dialect;
-import org.sonar.jpa.entity.SchemaMigration;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.Persistence;
-import java.sql.Connection;
-import java.sql.SQLException;
 import java.util.Map;
 import java.util.Properties;
 
@@ -39,45 +36,15 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector {
 
   protected Database database;
   private EntityManagerFactory factory = null;
-  private int databaseVersion = SchemaMigration.VERSION_UNKNOWN;
-  private boolean operational = false;
-  private boolean started = false;
 
   protected AbstractDatabaseConnector(Database database) {
     this.database = database;
   }
 
-  public String getDialectId() {
-    return database.getDialect().getId();
-  }
-
-  /**
-   * Indicates if the connector is operational : database connection OK and schema version OK
-   */
-  public boolean isOperational() {
-    return operational;
-  }
-
-  /**
-   * Indicates if the connector is started : database connection OK and schema version OK or KO
-   */
-  protected boolean isStarted() {
-    return started;
-  }
-
   public void start() {
-    if (!started) {
-      testConnection();
-      started = true;
-    }
-    if (!operational) {
-      boolean upToDate = upToDateSchemaVersion();
-      if (upToDate) {
-        Logs.INFO.info("Initializing Hibernate");
-        factory = createEntityManagerFactory();
-        operational = true;
-      }
-    }
+    LOG.info("Initializing Hibernate");
+    factory = createEntityManagerFactory();
+
   }
 
   public void stop() {
@@ -85,8 +52,6 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector {
       factory.close();
       factory = null;
     }
-    operational = false;
-    started = false;
     database = null;
   }
 
@@ -94,10 +59,6 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector {
     return factory;
   }
 
-  protected void setEntityManagerFactory(EntityManagerFactory factory) {
-    this.factory = factory;
-  }
-
   protected EntityManagerFactory createEntityManagerFactory() {
     // other settings are stored into /META-INF/persistence.xml
     Properties props = database.getHibernateProperties();
@@ -117,54 +78,8 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector {
     return factory.createEntityManager();
   }
 
-  private String testConnection() throws DatabaseException {
-    Connection connection = null;
-    try {
-      connection = getConnection();
-      return connection.getMetaData().getURL();
-
-    } catch (SQLException e) {
-      throw new DatabaseException("Cannot open connection to database: " + e.getMessage(), e);
-
-    } finally {
-      close(connection);
-    }
-  }
-
-  protected int loadVersion() {
-    Connection connection = null;
-    try {
-      connection = getConnection();
-      return SchemaMigration.getCurrentVersion(connection);
-
-    } catch (SQLException e) {
-      // schema not created
-      return 0;
-    } finally {
-      close(connection);
-    }
-  }
-
-  private void close(Connection connection) {
-    if (connection != null) {
-      try {
-        connection.close();
-      } catch (SQLException e) {
-        // why does close() throw a checked-exception ???
-      }
-    }
-  }
-
-  protected boolean upToDateSchemaVersion() {
-    if (databaseVersion == SchemaMigration.LAST_VERSION) {
-      return true;
-    }
-    databaseVersion = loadVersion();
-    return databaseVersion == SchemaMigration.LAST_VERSION;
-  }
-
   public final int getDatabaseVersion() {
-    return databaseVersion;
+    throw new UnsupportedOperationException("Moved to " + DatabaseVersion.class.getCanonicalName());
   }
 
   public final Dialect getDialect() {
index d55e0134f181a1030aabd1ae9a99d89116629ecd..3c7a6a56579de523d7728ab956cf0d2c1bce8c51 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.jpa.session;
 
 import org.sonar.api.utils.SonarException;
 import org.sonar.core.persistence.Database;
-import org.sonar.jpa.entity.SchemaMigration;
 
 import java.sql.Connection;
 import java.sql.SQLException;
@@ -32,24 +31,10 @@ public class DefaultDatabaseConnector extends AbstractDatabaseConnector {
     super(database);
   }
 
-  @Override
-  public boolean isOperational() {
-    if (isStarted() && getDatabaseVersion() != SchemaMigration.LAST_VERSION) {
-      // connector was started and connection OK but schema version was not OK
-      // call start again to check if this is now ok (schema created by rails)
-      start();
-    }
-    return super.isOperational();
-  }
-
   @Override
   public void start() {
-    if (!isStarted()) {
-      createDatasource();
-    }
-    if (!super.isOperational()) {
-      super.start();
-    }
+    createDatasource();
+    super.start();
   }
 
   private void createDatasource() {
index 1484a88f9794d4c85a29a70fc3fb27af4d28aeb0..488898e77611ba4458fa681c7838f0b45986e088 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.jpa.session;
 
 import org.sonar.core.persistence.Database;
+import org.sonar.core.persistence.DatabaseVersion;
 import org.sonar.jpa.entity.SchemaMigration;
 
 import javax.persistence.EntityManager;
@@ -29,24 +30,12 @@ public class MemoryDatabaseConnector extends DefaultDatabaseConnector {
 
   public MemoryDatabaseConnector(Database database) {
     super(database);
-    version = SchemaMigration.LAST_VERSION;
-  }
-
-  public MemoryDatabaseConnector(Database database, int version) {
-    this(database);
-    this.version = version;
+    version = DatabaseVersion.LAST_VERSION;
   }
 
   @Override
   public void start() {
-    try {
-      super.start();
-    } catch (DatabaseException ex) {
-      if (!isStarted()) {
-        throw ex;
-      }
-    }
-    setEntityManagerFactory(createEntityManagerFactory());
+    super.start();
     setupSchemaVersion(version);
   }
 
diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/SchemaMigrationMapper.xml b/sonar-core/src/main/resources/org/sonar/core/persistence/SchemaMigrationMapper.xml
new file mode 100644 (file)
index 0000000..2181a80
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.core.persistence.SchemaMigrationMapper">
+
+  <select id="selectVersions" resultType="int">
+    select * from schema_migrations
+  </select>
+
+</mapper>
+
diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DatabaseVersionTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/DatabaseVersionTest.java
new file mode 100644 (file)
index 0000000..03d6033
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.core.persistence;
+
+import org.hamcrest.core.Is;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class DatabaseVersionTest extends DaoTestCase {
+  @Test
+  public void getVersion() {
+    setupData("getVersion");
+
+    Integer version = new DatabaseVersion(getMyBatis()).getVersion();
+
+    assertThat(version, Is.is(123));
+  }
+
+  @Test
+  public void getVersion_no_rows() {
+    setupData("getVersion_no_rows");
+
+    Integer version = new DatabaseVersion(getMyBatis()).getVersion();
+
+    assertThat(version, nullValue());
+  }
+
+  @Test
+  public void getStatus() {
+    assertThat(DatabaseVersion.getStatus(null, 150), is(DatabaseVersion.Status.REQUIRES_UPGRADE));
+    assertThat(DatabaseVersion.getStatus(123, 150), is(DatabaseVersion.Status.REQUIRES_UPGRADE));
+    assertThat(DatabaseVersion.getStatus(150, 150), is(DatabaseVersion.Status.UP_TO_DATE));
+    assertThat(DatabaseVersion.getStatus(200, 150), is(DatabaseVersion.Status.REQUIRES_DOWNGRADE));
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/jpa/entity/SchemaMigrationTest.java b/sonar-core/src/test/java/org/sonar/jpa/entity/SchemaMigrationTest.java
deleted file mode 100644 (file)
index cd2e5a8..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.jpa.entity;
-
-import org.junit.Test;
-import org.sonar.core.persistence.Database;
-import org.sonar.core.persistence.InMemoryDatabase;
-import org.sonar.jpa.session.MemoryDatabaseConnector;
-
-import java.sql.Connection;
-
-import static org.junit.Assert.assertEquals;
-
-public class SchemaMigrationTest {
-
-  @Test
-  public void currentVersionShouldBeUnknownWhenSchemaIsEmpty() throws Exception {
-    Database database = new InMemoryDatabase();
-    database.start();
-
-    MemoryDatabaseConnector connector = new MemoryDatabaseConnector(database, SchemaMigration.VERSION_UNKNOWN);
-    connector.start();
-
-    Connection connection = null;
-    try {
-      connection = connector.getConnection();
-      assertEquals(SchemaMigration.VERSION_UNKNOWN, SchemaMigration.getCurrentVersion(connection));
-    } finally {
-      if (connection != null) {
-        connection.close();
-      }
-    }
-    connector.stop();
-    database.stop();
-  }
-
-  @Test
-  public void versionShouldBeLoadedFromSchemaMigrationsTable() throws Exception {
-    Database database = new InMemoryDatabase();
-    database.start();
-    MemoryDatabaseConnector connector = new MemoryDatabaseConnector(database, 30);
-    connector.start();
-
-    Connection connection = null;
-    try {
-      connection = connector.getConnection();
-      assertEquals(30, SchemaMigration.getCurrentVersion(connection));
-
-    } finally {
-      if (connection != null) {
-        connection.close();
-      }
-    }
-    connector.stop();
-    database.stop();
-  }
-}
diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DatabaseVersionTest/getVersion.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DatabaseVersionTest/getVersion.xml
new file mode 100644 (file)
index 0000000..867616d
--- /dev/null
@@ -0,0 +1,8 @@
+<dataset>
+
+  <schema_migrations version="1"/>
+  <schema_migrations version="2"/>
+  <schema_migrations version="4"/>
+  <schema_migrations version="123"/>
+  <schema_migrations version="50"/>
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DatabaseVersionTest/getVersion_no_rows.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DatabaseVersionTest/getVersion_no_rows.xml
new file mode 100644 (file)
index 0000000..5ed00ba
--- /dev/null
@@ -0,0 +1 @@
+<dataset></dataset>
\ No newline at end of file
index 8620bfd44ca8f3af239610e5eb626590299ea8e9..8b6583a959fc36573e4de6878f7fc8778378ed66 100644 (file)
@@ -30,7 +30,7 @@ import org.apache.commons.lang.CharEncoding;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.database.DatabaseSession;
-import org.sonar.jpa.entity.SchemaMigration;
+import org.sonar.core.persistence.DatabaseVersion;
 
 import javax.annotation.Nullable;
 import java.io.IOException;
@@ -144,7 +144,7 @@ public class Backup {
    * Utils methods
    */
   protected int getVersion() {
-    return SchemaMigration.LAST_VERSION;
+    return DatabaseVersion.LAST_VERSION;
   }
 
   protected Date getCurrentDate() {
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java b/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java
new file mode 100644 (file)
index 0000000..7a1a925
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.server.platform;
+
+import org.slf4j.LoggerFactory;
+import org.sonar.api.ServerComponent;
+import org.sonar.core.persistence.BadDatabaseVersion;
+import org.sonar.core.persistence.DatabaseVersion;
+
+public class DatabaseServerCompatibility implements ServerComponent {
+  
+  private DatabaseVersion version;
+
+  public DatabaseServerCompatibility(DatabaseVersion version) {
+    this.version = version;
+  }
+
+  public void start() {
+    DatabaseVersion.Status status = version.getStatus();
+    if (status== DatabaseVersion.Status.REQUIRES_DOWNGRADE) {
+      throw new BadDatabaseVersion("Database relates to a more recent version of sonar. Please check your settings.");
+    }
+    if (status== DatabaseVersion.Status.REQUIRES_UPGRADE) {
+      LoggerFactory.getLogger(DatabaseServerCompatibility.class).info("Database must be upgraded. Please browse /setup");
+    }
+  }
+
+}
index 64c47d5c88060b20e0b0e872ddd8afe160441675..3aebf626cb1fad83cf435bd4c24078a95caec2d0 100644 (file)
@@ -22,8 +22,7 @@ package org.sonar.server.platform;
 import org.apache.commons.lang.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang.builder.ToStringStyle;
 import org.sonar.api.platform.ServerUpgradeStatus;
-import org.sonar.jpa.entity.SchemaMigration;
-import org.sonar.jpa.session.DatabaseConnector;
+import org.sonar.core.persistence.DatabaseVersion;
 
 /**
  * @since 2.5
@@ -31,22 +30,23 @@ import org.sonar.jpa.session.DatabaseConnector;
 public final class DefaultServerUpgradeStatus implements ServerUpgradeStatus {
 
   private int initialDbVersion;
-  private DatabaseConnector dbConnector;
+  private DatabaseVersion dbVersion;
 
-  public DefaultServerUpgradeStatus(DatabaseConnector dbConnector) {
-    this.dbConnector = dbConnector;
+  public DefaultServerUpgradeStatus(DatabaseVersion dbVersion) {
+    this.dbVersion = dbVersion;
   }
 
   public void start() {
-    this.initialDbVersion = dbConnector.getDatabaseVersion();
+    Integer v = dbVersion.getVersion();
+    this.initialDbVersion = (v != null ? v : -1);
   }
 
   public boolean isUpgraded() {
-    return !isFreshInstall() &&(initialDbVersion < SchemaMigration.LAST_VERSION);
+    return !isFreshInstall() && (initialDbVersion < DatabaseVersion.LAST_VERSION);
   }
 
   public boolean isFreshInstall() {
-    return initialDbVersion <= 0;
+    return initialDbVersion<0;
   }
 
   public int getInitialDbVersion() {
index 13f29b6b0791d88ad66ea00a8f94636e426f67ec..ce7193fd5b049f0a2a94578289a3c48c770eeef7 100644 (file)
@@ -40,10 +40,7 @@ import org.sonar.core.i18n.I18nManager;
 import org.sonar.core.i18n.RuleI18nManager;
 import org.sonar.core.metric.DefaultMetricFinder;
 import org.sonar.core.notification.DefaultNotificationManager;
-import org.sonar.core.persistence.DaoUtils;
-import org.sonar.core.persistence.DatabaseMigrator;
-import org.sonar.core.persistence.DefaultDatabase;
-import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.persistence.*;
 import org.sonar.core.qualitymodel.DefaultModelFinder;
 import org.sonar.core.rule.DefaultRuleFinder;
 import org.sonar.core.user.DefaultUserFinder;
@@ -108,9 +105,9 @@ public final class Platform {
   }
 
   public void start() {
-    if (!started && isUpToDateDatabase()) {
+    if (!started && getDatabaseStatus()== DatabaseVersion.Status.UP_TO_DATE) {
       try {
-        TimeProfiler profiler = new TimeProfiler().start("Start services");
+        TimeProfiler profiler = new TimeProfiler().start("Start components");
         startCoreComponents();
         startServiceComponents();
         executeStartupTasks();
@@ -133,22 +130,24 @@ public final class Platform {
     rootContainer.addSingleton(EmbeddedDatabaseFactory.class);
     rootContainer.addSingleton(DefaultDatabase.class);
     rootContainer.addSingleton(MyBatis.class);
-    rootContainer.addSingleton(DefaultDatabaseConnector.class);
     rootContainer.addSingleton(DefaultServerUpgradeStatus.class);
+    rootContainer.addSingleton(DatabaseServerCompatibility.class);
     rootContainer.addSingleton(DatabaseMigrator.class);
+    rootContainer.addSingleton(DatabaseVersion.class);
     for (Class daoClass : DaoUtils.getDaoClasses()) {
       rootContainer.addSingleton(daoClass);
     }
     rootContainer.startComponents();
   }
 
-  private boolean isUpToDateDatabase() {
-    DefaultDatabaseConnector databaseConnector = getContainer().getComponentByType(DefaultDatabaseConnector.class);
-    return databaseConnector.isOperational();
+  private DatabaseVersion.Status getDatabaseStatus() {
+    DatabaseVersion version = getContainer().getComponentByType(DatabaseVersion.class);
+    return version.getStatus();
   }
 
   private void startCoreComponents() {
     coreContainer = rootContainer.createChild();
+    coreContainer.addSingleton(DefaultDatabaseConnector.class);
     coreContainer.addSingleton(PluginDeployer.class);
     coreContainer.addSingleton(DefaultServerPluginRepository.class);
     coreContainer.addSingleton(ServerExtensionInstaller.class);
index 1a2dcc99bc45c3667ee038a1460a0e2aa263757a..f1d93735e1364131d68003dd585ebc0fcbbe7f3a 100644 (file)
@@ -5,7 +5,7 @@ HOW TO ADD A MIGRATION
   + sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl
   + sonar-core/src/main/resources/org/sonar/core/persistence/rows-derby.sql :
     - add "INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('<THE MIGRATION ID>')"
-* Update the migration id defined in sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java
+* Update the migration id defined in sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
 * If a table is added or removed, then edit sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java
 
 
diff --git a/sonar-server/src/test/java/org/sonar/server/platform/DatabaseServerCompatibilityTest.java b/sonar-server/src/test/java/org/sonar/server/platform/DatabaseServerCompatibilityTest.java
new file mode 100644 (file)
index 0000000..7ff5a20
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.server.platform;
+
+import org.junit.Test;
+import org.sonar.core.persistence.BadDatabaseVersion;
+import org.sonar.core.persistence.DatabaseVersion;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DatabaseServerCompatibilityTest {
+
+  @Test(expected = BadDatabaseVersion.class)
+  public void shouldFailIfRequiresDowngrade() {
+    DatabaseVersion version = mock(DatabaseVersion.class);
+    when(version.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_DOWNGRADE);
+    new DatabaseServerCompatibility(version).start();
+  }
+
+  @Test
+  public void shouldLogWarningIfRequiresUpgrade() {
+    DatabaseVersion version = mock(DatabaseVersion.class);
+    when(version.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE);
+    new DatabaseServerCompatibility(version).start();
+    // oh well... how to simply test logging ?
+    // Let's assume that this test verifies that no error is raised.
+  }
+
+  @Test
+  public void shouldDoNothingIfUpToDate() {
+    DatabaseVersion version = mock(DatabaseVersion.class);
+    when(version.getStatus()).thenReturn(DatabaseVersion.Status.UP_TO_DATE);
+    new DatabaseServerCompatibility(version).start();
+    // no error
+  }
+}
index dc271ffca8f5d2bac619a56cb0251a09812145fe..2b59007390cb7de498550e5ddde8ee1adb342e03 100644 (file)
@@ -20,8 +20,7 @@
 package org.sonar.server.platform;
 
 import org.junit.Test;
-import org.sonar.jpa.entity.SchemaMigration;
-import org.sonar.jpa.session.DatabaseConnector;
+import org.sonar.core.persistence.DatabaseVersion;
 
 import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertThat;
@@ -32,10 +31,10 @@ public class DefaultServerUpgradeStatusTest {
 
   @Test
   public void shouldBeFreshInstallation() {
-    DatabaseConnector connector = mock(DatabaseConnector.class);
-    when(connector.getDatabaseVersion()).thenReturn(-1);
+    DatabaseVersion dbVersion = mock(DatabaseVersion.class);
+    when(dbVersion.getVersion()).thenReturn(null);
 
-    DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(connector);
+    DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(dbVersion);
     status.start();
 
     assertThat(status.isFreshInstall(), is(true));
@@ -45,10 +44,10 @@ public class DefaultServerUpgradeStatusTest {
 
   @Test
   public void shouldBeUpgraded() {
-    DatabaseConnector connector = mock(DatabaseConnector.class);
-    when(connector.getDatabaseVersion()).thenReturn(50);
+    DatabaseVersion dbVersion = mock(DatabaseVersion.class);
+    when(dbVersion.getVersion()).thenReturn(50);
 
-    DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(connector);
+    DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(dbVersion);
     status.start();
 
     assertThat(status.isFreshInstall(), is(false));
@@ -58,14 +57,14 @@ public class DefaultServerUpgradeStatusTest {
 
   @Test
   public void shouldNotBeUpgraded() {
-    DatabaseConnector connector = mock(DatabaseConnector.class);
-    when(connector.getDatabaseVersion()).thenReturn(SchemaMigration.LAST_VERSION);
+    DatabaseVersion dbVersion = mock(DatabaseVersion.class);
+    when(dbVersion.getVersion()).thenReturn(DatabaseVersion.LAST_VERSION);
 
-    DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(connector);
+    DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(dbVersion);
     status.start();
-    
+
     assertThat(status.isFreshInstall(), is(false));
     assertThat(status.isUpgraded(), is(false));
-    assertThat(status.getInitialDbVersion(), is(SchemaMigration.LAST_VERSION));
+    assertThat(status.getInitialDbVersion(), is(DatabaseVersion.LAST_VERSION));
   }
 }
index f7a0a3e04a90f4bec0420160ddf1d26a2d2342a2..6747944556342abcd4a69326339aedc8b60ef45b 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.startup;
 import org.junit.Test;
 import org.sonar.api.database.model.MeasureModel;
 import org.sonar.api.platform.ServerUpgradeStatus;
-import org.sonar.jpa.entity.SchemaMigration;
+import org.sonar.core.persistence.DatabaseVersion;
 import org.sonar.jpa.test.AbstractDbUnitTestCase;
 
 import java.sql.SQLException;
@@ -98,7 +98,7 @@ public class DeleteDeprecatedMeasuresTest extends AbstractDbUnitTestCase {
   public void shouldNotDoPurgeOnStandardStartup() {
     ServerUpgradeStatus upgradeStatus = mock(ServerUpgradeStatus.class);
     when(upgradeStatus.isUpgraded()).thenReturn(false);
-    when(upgradeStatus.getInitialDbVersion()).thenReturn(SchemaMigration.LAST_VERSION);
+    when(upgradeStatus.getInitialDbVersion()).thenReturn(DatabaseVersion.LAST_VERSION);
 
     final DeleteDeprecatedMeasures purge = new DeleteDeprecatedMeasures(getSessionFactory(), upgradeStatus);
     assertThat(purge.mustDoPurge(), is(false));