import org.apache.commons.lang.StringUtils;
import org.h2.Driver;
import org.h2.tools.Server;
+import org.picocontainer.Startable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import java.sql.DriverManager;
import java.sql.SQLException;
-public class EmbeddedDatabase {
+public class EmbeddedDatabase implements Startable {
private static final Logger LOG = LoggerFactory.getLogger(EmbeddedDatabase.class);
private final Settings settings;
private Server server;
this.settings = settings;
}
+ @Override
public void start() {
File dbHome = getDataDirectory(settings);
if (!dbHome.exists()) {
}
}
+ @Override
public void stop() {
if (server != null) {
server.stop();
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.dbutils.DbUtils;
import org.apache.ibatis.session.SqlSession;
+import org.picocontainer.Startable;
import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
+import org.sonar.api.platform.ServerUpgradeStatus;
import org.sonar.core.persistence.Database;
import org.sonar.core.persistence.DdlUtils;
import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.plugins.ServerPluginRepository;
import java.sql.Connection;
*
* @since 2.12
*/
-public class DatabaseMigrator implements ServerComponent {
+public class DatabaseMigrator implements ServerComponent, Startable {
private final MyBatis myBatis;
private final Database database;
private final DatabaseMigration[] migrations;
+ private final ServerUpgradeStatus serverUpgradeStatus;
- public DatabaseMigrator(MyBatis myBatis, Database database, DatabaseMigration[] migrations) {
+ /**
+ * ServerPluginRepository is used to ensure H2 schema creation is done only after copy of bundle plugins have been done
+ */
+ public DatabaseMigrator(MyBatis myBatis, Database database, DatabaseMigration[] migrations, ServerUpgradeStatus serverUpgradeStatus,
+ ServerPluginRepository serverPluginRepository) {
this.myBatis = myBatis;
this.database = database;
this.migrations = migrations;
+ this.serverUpgradeStatus = serverUpgradeStatus;
+ }
+
+ @Override
+ public void start(){
+ createDatabase();
+ }
+
+ @Override
+ public void stop(){
+ // Nothing to do
}
/**
- * @return true if the database has been created, false if this database is not supported
+ * @return true if the database has been created, false if this database is not supported or if database has already been created
*/
- public boolean createDatabase() {
- if (!DdlUtils.supportsDialect(database.getDialect().getId())) {
- return false;
- }
-
- LoggerFactory.getLogger(getClass()).info("Create database");
- SqlSession session = null;
- Connection connection = null;
- try {
- session = myBatis.openSession();
- connection = session.getConnection();
- createSchema(connection, database.getDialect().getId());
- return true;
- } finally {
- MyBatis.closeQuietly(session);
+ @VisibleForTesting
+ boolean createDatabase() {
+ if (DdlUtils.supportsDialect(database.getDialect().getId()) && serverUpgradeStatus.isFreshInstall()) {
+ LoggerFactory.getLogger(getClass()).info("Create database");
+ SqlSession session = null;
+ Connection connection = null;
+ try {
+ session = myBatis.openSession();
+ connection = session.getConnection();
+ createSchema(connection, database.getDialect().getId());
+ return true;
+ } finally {
+ MyBatis.closeQuietly(session);
- // The connection is probably already closed by session.close()
- // but it's not documented in mybatis javadoc.
- DbUtils.closeQuietly(connection);
+ // The connection is probably already closed by session.close()
+ // but it's not documented in mybatis javadoc.
+ DbUtils.closeQuietly(connection);
+ }
}
+ return false;
}
public void executeMigration(String className) {
DefaultDatabase.class,
MyBatis.class,
DatabaseServerCompatibility.class,
- DatabaseMigrator.class,
DatabaseVersion.class,
PurgeProfiler.class,
DefaultServerFileSystem.class,
Collection level2Components() {
return Lists.newArrayList(
DefaultServerUpgradeStatus.class,
+ DatabaseMigrator.class,
+
// plugins
ServerPluginJarsInstaller.class,
ServerPluginJarInstaller.class,
import org.sonar.api.test.MutableTestable;
import org.sonar.api.test.TestPlan;
import org.sonar.api.test.Testable;
-import org.sonar.api.web.Footer;
-import org.sonar.api.web.NavigationSection;
-import org.sonar.api.web.Page;
-import org.sonar.api.web.RubyRailsWebservice;
-import org.sonar.api.web.Widget;
+import org.sonar.api.web.*;
import org.sonar.core.component.SnapshotPerspectives;
import org.sonar.core.measure.MeasureFilterEngine;
import org.sonar.core.measure.MeasureFilterResult;
import org.sonar.server.platform.ServerIdGenerator;
import org.sonar.server.platform.ServerSettings;
import org.sonar.server.platform.SettingsChangeNotifier;
-import org.sonar.server.plugins.InstalledPluginReferentialFactory;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.*;
import org.sonar.server.rule.RuleRepositories;
import org.sonar.server.source.CodeColorizers;
import org.sonar.server.user.NewUserNotifier;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.net.InetAddress;
import java.sql.Connection;
import java.util.Collection;
return get(Database.class);
}
+ // Only used by Java migration
public DatabaseMigrator databaseMigrator() {
return get(DatabaseMigrator.class);
}
def self.automatic_setup
if current_version<=0
- try_restore_structure_dump()
upgrade_and_start()
elsif uptodate?
load_java_web_services
ActiveRecord::Base.connected?
end
- def self.try_restore_structure_dump()
- ::Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().createDatabase()
- end
-
- def self.execute_sql_requests(requests)
- requests.each do |request|
- unless request.blank? || request.start_with?('--')
- request.chomp!
- request.chop! if request.end_with?(';')
- ActiveRecord::Base.connection.execute(request)
- end
- end
- end
-
def self.dialect
::Java::OrgSonarServerUi::JRubyFacade.getInstance().getDatabase().getDialect().getActiveRecordDialectCode()
end
package org.sonar.server.db.migrations;
import org.apache.ibatis.session.SqlSession;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.platform.ServerUpgradeStatus;
import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.persistence.Database;
import org.sonar.core.persistence.MyBatis;
MyBatis mybatis = mock(MyBatis.class);
Database database = mock(Database.class);
DatabaseMigration[] migrations = new DatabaseMigration[]{new FakeMigration()};
+ ServerUpgradeStatus serverUpgradeStatus = mock(ServerUpgradeStatus.class);
+
+ DatabaseMigrator migrator;
+
+ @Before
+ public void setUp() throws Exception {
+ migrator = new DatabaseMigrator(mybatis, database, migrations, serverUpgradeStatus, null);
+ }
@Test
public void should_support_only_creation_of_h2_database() throws Exception {
when(database.getDialect()).thenReturn(new MySql());
- DatabaseMigrator migrator = new DatabaseMigrator(mybatis, database, migrations);
-
assertThat(migrator.createDatabase()).isFalse();
verifyZeroInteractions(mybatis);
}
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Database migration not found: org.xxx.UnknownMigration");
- DatabaseMigrator migrator = new DatabaseMigrator(mybatis, database, migrations);
migrator.executeMigration("org.xxx.UnknownMigration");
}
@Test
public void execute_migration() throws Exception {
- DatabaseMigrator migrator = new DatabaseMigrator(mybatis, database, migrations);
assertThat(FakeMigration.executed).isFalse();
migrator.executeMigration(FakeMigration.class.getName());
assertThat(FakeMigration.executed).isTrue();
@Test
public void should_create_schema_on_h2() throws Exception {
-
Dialect supportedDialect = new H2();
when(database.getDialect()).thenReturn(supportedDialect);
Connection connection = mock(Connection.class);
SqlSession session = mock(SqlSession.class);
when(session.getConnection()).thenReturn(connection);
when(mybatis.openSession()).thenReturn(session);
+ when(serverUpgradeStatus.isFreshInstall()).thenReturn(true);
- DatabaseMigrator databaseMigrator = new DatabaseMigrator(mybatis, database, migrations) {
+ DatabaseMigrator databaseMigrator = new DatabaseMigrator(mybatis, database, migrations, serverUpgradeStatus, null) {
@Override
protected void createSchema(Connection connection, String dialectId) {
}
import org.apache.commons.io.FileUtils;
import org.sonar.api.CoreProperties;
-import org.sonar.server.db.migrations.DatabaseMigrator;
import org.sonar.server.platform.Platform;
import java.io.File;
properties.setProperty("sonar.jdbc.url", "jdbc:h2:" + temp.getAbsolutePath() + "/h2");
platform.init(properties);
- ((DatabaseMigrator) platform.getComponent(DatabaseMigrator.class)).createDatabase();
platform.doStart();
}