import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.lang.StringUtils;
import org.picocontainer.Startable;
+import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.ServerComponent;
import org.sonar.core.persistence.Database;
public class DatabaseChecker implements ServerComponent, Startable {
+ public static final int ORACLE_MIN_MAJOR_VERSION = 11;
+
private final Database db;
public DatabaseChecker(Database db) {
if (H2.ID.equals(db.getDialect().getId())) {
Loggers.get(DatabaseChecker.class).warn("H2 database should be used for evaluation purpose only");
} else if (Oracle.ID.equals(db.getDialect().getId())) {
- checkOracleDriverVersion();
+ checkOracleVersion();
}
} catch (Exception e) {
Throwables.propagate(e);
// nothing to do
}
- private void checkOracleDriverVersion() throws SQLException {
+ private void checkOracleVersion() throws SQLException {
Connection connection = db.getDataSource().getConnection();
try {
+ // check version of db
+ // See http://jira.codehaus.org/browse/SONAR-6434
+ int majorVersion = connection.getMetaData().getDatabaseMajorVersion();
+ if (majorVersion < ORACLE_MIN_MAJOR_VERSION) {
+ throw MessageException.of(String.format(
+ "Unsupported Oracle version: %s. Minimal required version is %d.", connection.getMetaData().getDatabaseProductVersion(), ORACLE_MIN_MAJOR_VERSION));
+ }
+
+ // check version of driver
String driverVersion = connection.getMetaData().getDriverVersion();
String[] parts = StringUtils.split(driverVersion, ".");
int intVersion = Integer.parseInt(parts[0]) * 100 + Integer.parseInt(parts[1]);
if (intVersion < 1102) {
- throw new IllegalStateException(String.format(
+ throw MessageException.of(String.format(
"Unsupported Oracle JDBC driver version: %s. Minimal required version is 11.2.", driverVersion));
}
+
} finally {
DbUtils.closeQuietly(connection);
}
*/
package org.sonar.server.db;
+import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.mockito.Mockito;
+import org.sonar.api.utils.MessageException;
import org.sonar.core.persistence.Database;
import org.sonar.core.persistence.dialect.Dialect;
import org.sonar.core.persistence.dialect.H2;
public class DatabaseCheckerTest {
@Test
- public void require_oracle_11_2() throws Exception {
- Database db = mockDb(new Oracle(), "11.2.0.0.1");
+ public void requires_oracle_driver_11_2() throws Exception {
+ Database db = mockDb(new Oracle(), "11.2.1", "11.2.0.0.1");
new DatabaseChecker(db).start();
// no error
- db = mockDb(new Oracle(), "11.3.1");
+ db = mockDb(new Oracle(), "11.2.1", "11.3.1");
new DatabaseChecker(db).start();
// no error
- db = mockDb(new Oracle(), "12.0.2");
+ db = mockDb(new Oracle(), "11.2.1", "12.0.2");
new DatabaseChecker(db).start();
// no error
- db = mockDb(new Oracle(), "11.1.0.2");
+ db = mockDb(new Oracle(), "11.2.1", "11.1.0.2");
try {
new DatabaseChecker(db).start();
fail();
- } catch (IllegalStateException e) {
+ } catch (MessageException e) {
assertThat(e).hasMessage("Unsupported Oracle JDBC driver version: 11.1.0.2. Minimal required version is 11.2.");
}
}
+ @Test
+ public void requires_oracle_11g_or_greater() throws Exception {
+ // oracle 11.0 is ok
+ Database db = mockDb(new Oracle(), "11.0.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 11.1 is ok
+ db = mockDb(new Oracle(), "11.1.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 11.2 is ok
+ db = mockDb(new Oracle(), "11.2.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 12 is ok
+ db = mockDb(new Oracle(), "12.0.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 10 is not supported
+ db = mockDb(new Oracle(), "10.2.1", "11.2.0.0.1");
+ try {
+ new DatabaseChecker(db).start();
+ fail();
+ } catch (MessageException e) {
+ assertThat(e).hasMessage("Unsupported Oracle version: 10.2.1. Minimal required version is 11.");
+ }
+ }
+
@Test
public void log_warning_if_h2() throws Exception {
- Database db = mockDb(new H2(), "13.4");
+ Database db = mockDb(new H2(), "13.4", "13.4");
DatabaseChecker checker = new DatabaseChecker(db);
checker.start();
checker.stop();
@Test
public void do_not_fail_if_mysql() throws Exception {
- Database db = mockDb(new MySql(), "5.7");
+ Database db = mockDb(new MySql(), "5.7", "5.7");
new DatabaseChecker(db).start();
// no error
}
- private Database mockDb(Dialect dialect, String driverVersion) throws SQLException {
+ private Database mockDb(Dialect dialect, String dbVersion, String driverVersion) throws SQLException {
Database db = mock(Database.class, Mockito.RETURNS_DEEP_STUBS);
when(db.getDialect()).thenReturn(dialect);
+ when(db.getDataSource().getConnection().getMetaData().getDatabaseMajorVersion()).thenReturn(Integer.parseInt(StringUtils.substringBefore(dbVersion, ".")));
+ when(db.getDataSource().getConnection().getMetaData().getDatabaseProductVersion()).thenReturn(dbVersion);
when(db.getDataSource().getConnection().getMetaData().getDriverVersion()).thenReturn(driverVersion);
return db;
}