summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephane Gamard <stephane.gamard@searchbox.com>2014-06-18 13:57:09 +0200
committerStephane Gamard <stephane.gamard@searchbox.com>2014-06-18 13:57:09 +0200
commitb261040b47ddee53f91396909fe304543eab5bd0 (patch)
treec227b2ae62c78d297e63d4207683cee9ec48f260
parentc36d8a8dae8c323de0fb8fb6777f1d112a86e3e2 (diff)
downloadsonarqube-b261040b47ddee53f91396909fe304543eab5bd0.tar.gz
sonarqube-b261040b47ddee53f91396909fe304543eab5bd0.zip
SONAR-5329 - added ChangeLog Migration scripts
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java4
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql1
-rw-r--r--sonar-core/src/test/java/org/sonar/core/persistence/TestDatabase.java1
-rw-r--r--sonar-server/src/main/java/org/sonar/server/activity/db/ActivityDao.java2
-rw-r--r--sonar-server/src/main/java/org/sonar/server/db/BaseDao.java4
-rw-r--r--sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java14
-rw-r--r--sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLog.java55
-rw-r--r--sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMapper.java41
-rw-r--r--sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMigration.java224
-rw-r--r--sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java2
-rw-r--r--sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java1
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/db/migrate/548_update_logs_to_activities.rb31
-rw-r--r--sonar-server/src/test/java/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest.java74
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest/active_rules_changes.xml43
14 files changed, 489 insertions, 8 deletions
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
index 70fa98a5576..b6ff97835d5 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
@@ -33,7 +33,7 @@ import java.util.List;
*/
public class DatabaseVersion implements BatchComponent, ServerComponent {
- public static final int LAST_VERSION = 547;
+ public static final int LAST_VERSION = 548;
public static enum Status {
UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL
@@ -94,7 +94,7 @@ public class DatabaseVersion implements BatchComponent, ServerComponent {
"widgets",
"widget_properties",
"activities"
- );
+ );
private MyBatis mybatis;
diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
index e1764335391..40529333d55 100644
--- a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
+++ b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
@@ -241,6 +241,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('544');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('545');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('546');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('547');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('548');
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null);
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/TestDatabase.java b/sonar-core/src/test/java/org/sonar/core/persistence/TestDatabase.java
index 198b7def501..b42a4e36428 100644
--- a/sonar-core/src/test/java/org/sonar/core/persistence/TestDatabase.java
+++ b/sonar-core/src/test/java/org/sonar/core/persistence/TestDatabase.java
@@ -257,6 +257,7 @@ public class TestDatabase extends ExternalResource {
dataSet.addReplacementObject("[null]", null);
dataSet.addReplacementObject("[false]", Boolean.FALSE);
dataSet.addReplacementObject("[true]", Boolean.TRUE);
+
return dataSet;
} catch (Exception e) {
throw translateException("Could not read the dataset stream", e);
diff --git a/sonar-server/src/main/java/org/sonar/server/activity/db/ActivityDao.java b/sonar-server/src/main/java/org/sonar/server/activity/db/ActivityDao.java
index d009113dcf9..4c723ae668a 100644
--- a/sonar-server/src/main/java/org/sonar/server/activity/db/ActivityDao.java
+++ b/sonar-server/src/main/java/org/sonar/server/activity/db/ActivityDao.java
@@ -71,6 +71,6 @@ public class ActivityDao extends BaseDao<ActivityMapper, ActivityDto, ActivityKe
@Override
public void synchronizeAfter(DbSession session, long timestamp) {
- throw new IllegalStateException("Log Index does not synchronize!");
+
}
}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/BaseDao.java b/sonar-server/src/main/java/org/sonar/server/db/BaseDao.java
index a1e7ea9c0cf..b79ee901583 100644
--- a/sonar-server/src/main/java/org/sonar/server/db/BaseDao.java
+++ b/sonar-server/src/main/java/org/sonar/server/db/BaseDao.java
@@ -214,7 +214,9 @@ public abstract class BaseDao<M, E extends Dto<K>, K extends Serializable> imple
}
private void insert(DbSession session, E item, Date now) {
- item.setCreatedAt(now);
+ if (item.getCreatedAt() == null) {
+ item.setCreatedAt(now);
+ }
item.setUpdatedAt(now);
doInsert(session, item);
if (hasIndex()) {
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java
index 4cb30bd9a56..414c27a7e3d 100644
--- a/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java
+++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java
@@ -23,8 +23,15 @@ import com.google.common.collect.ImmutableList;
import org.sonar.server.db.migrations.v36.ViolationMigration;
import org.sonar.server.db.migrations.v42.CompleteIssueMessageMigration;
import org.sonar.server.db.migrations.v42.PackageKeysMigration;
-import org.sonar.server.db.migrations.v43.*;
-import org.sonar.server.db.migrations.v44.*;
+import org.sonar.server.db.migrations.v43.DevelopmentCostMeasuresMigration;
+import org.sonar.server.db.migrations.v43.IssueChangelogMigration;
+import org.sonar.server.db.migrations.v43.IssueMigration;
+import org.sonar.server.db.migrations.v43.NotResolvedIssuesOnRemovedComponentsMigration;
+import org.sonar.server.db.migrations.v43.RequirementMeasuresMigration;
+import org.sonar.server.db.migrations.v43.TechnicalDebtMeasuresMigration;
+import org.sonar.server.db.migrations.v44.ChangeLogMigration;
+import org.sonar.server.db.migrations.v44.IssueActionPlanKeyMigration;
+import org.sonar.server.db.migrations.v44.MeasureDataMigration;
import java.util.List;
@@ -47,7 +54,8 @@ public interface DatabaseMigrations {
// 4.4
IssueActionPlanKeyMigration.class,
- MeasureDataMigration.class
+ MeasureDataMigration.class,
+ ChangeLogMigration.class
);
}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLog.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLog.java
new file mode 100644
index 00000000000..59729fdbf0d
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLog.java
@@ -0,0 +1,55 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.db.migrations.v44;
+
+import org.apache.ibatis.type.Alias;
+
+import java.util.Date;
+
+/**
+ * SONAR-5329
+ * Transition ActiveRuleChanges to ActivityLog
+ * <p/>
+ * Used in the Active Record Migration 548.
+ *
+ * @since 4.4
+ */
+@Alias("ChangeLogMigration")
+public class ChangeLog {
+
+ private Date createdAt;
+ private String userLogin;
+
+ public Date getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(Date createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public String getUserLogin() {
+ return userLogin;
+ }
+
+ public void setUserLogin(String userLogin) {
+ this.userLogin = userLogin;
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMapper.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMapper.java
new file mode 100644
index 00000000000..45a34c9d463
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMapper.java
@@ -0,0 +1,41 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.db.migrations.v44;
+
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * SONAR-5329
+ * Transition ActiveRuleChanges to ActivityLog
+ * <p/>
+ * Used in the Active Record Migration 548.
+ *
+ * @since 4.4
+ */
+public interface ChangeLogMapper {
+
+ @Select("select rule_change.change_date as createdAt," +
+ " rule_change.username as userLogin " +
+ "from active_rule_changes rule_change")
+ List<ChangeLog> selectAll();
+}
+
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMigration.java
new file mode 100644
index 00000000000..395d504daea
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/v44/ChangeLogMigration.java
@@ -0,0 +1,224 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.db.migrations.v44;
+
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.core.activity.Activity;
+import org.sonar.core.activity.db.ActivityDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.ActiveRuleKey;
+import org.sonar.core.qualityprofile.db.QualityProfileKey;
+import org.sonar.core.rule.SeverityUtil;
+import org.sonar.server.activity.ActivityService;
+import org.sonar.server.activity.db.ActivityDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.db.migrations.DatabaseMigration;
+import org.sonar.server.qualityprofile.ActiveRuleChange;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Date;
+
+/**
+ * SONAR-5329
+ * Transition ActiveRuleChanges to ActivityLog
+ * <p/>
+ * Used in the Active Record Migration 548.
+ *
+ * @since 4.4
+ */
+public class ChangeLogMigration implements DatabaseMigration {
+
+ private static final String PARAM_VALUE = "param_value";
+ private static final String PARAM_NAME = "param_name";
+ private static final String RULE_NAME = "rule_name";
+ private static final String PROFILE_KEY = "profile_key";
+ private static final String RULE_KEY = "rule_key";
+ private static final String CREATED_AT = "created_at";
+ private static final String SEVERITY = "severity";
+ private static final String USER_LOGIN = "user_login";
+
+ private final ActivityDao dao;
+ private DbSession session;
+ private final DbClient db;
+
+
+ private final String allActivation =
+ "select" +
+ " rule_change.id," +
+ " rule_change.change_date as " + CREATED_AT + "," +
+ " users.login as " + USER_LOGIN + "," +
+ " CONCAT(rule_def.plugin_name,':',rule_def.plugin_rule_key) as " + RULE_KEY + "," +
+ " CONCAT(profile.name,':',profile.language) as " + PROFILE_KEY + "," +
+ " rule_change.new_severity as " + SEVERITY + "," +
+ " rule_def.name as " + RULE_NAME + "," +
+ " rule_def_param.name as " + PARAM_NAME + "," +
+ " rule_param_change.new_value as " + PARAM_VALUE +
+ " from active_rule_changes rule_change" +
+ " left join users on users.name = rule_change.username" +
+ " left join rules rule_def on rule_def.id = rule_change.rule_id" +
+ " left join rules_profiles profile on profile.id = rule_change.profile_id" +
+ " left join active_rule_param_changes rule_param_change on rule_param_change.active_rule_change_id = rule_change.id" +
+ " left join rules_parameters rule_def_param on rule_def_param.id = rule_param_change.rules_parameter_id" +
+ " WHERE rule_change.enabled is true" +
+ " AND profile.name is not null" +
+ " AND profile.language is not null" +
+ " AND rule_def.plugin_name is not null" +
+ " AND rule_def.plugin_name is not null" +
+ " order by rule_change.id ASC;";
+
+ private final String allUpdates =
+ "select" +
+ " rule_change.id," +
+ " rule_change.change_date as " + CREATED_AT + "," +
+ " users.login as " + USER_LOGIN + "," +
+ " CONCAT(rule_def.plugin_name,':',rule_def.plugin_rule_key) as " + RULE_KEY + "," +
+ " CONCAT(profile.name,':',profile.language) as " + PROFILE_KEY + "," +
+ " rule_change.new_severity as " + SEVERITY + "," +
+ " rule_def.name as " + RULE_NAME + "," +
+ " rule_def_param.name as " + PARAM_NAME + "," +
+ " rule_param_change.new_value as " + PARAM_VALUE +
+ " from active_rule_changes rule_change" +
+ " left join users on users.name = rule_change.username" +
+ " left join rules rule_def on rule_def.id = rule_change.rule_id" +
+ " left join rules_profiles profile on profile.id = rule_change.profile_id" +
+ " left join active_rule_param_changes rule_param_change on rule_param_change.active_rule_change_id = rule_change.id" +
+ " left join rules_parameters rule_def_param on rule_def_param.id = rule_param_change.rules_parameter_id" +
+ " WHERE rule_change.enabled is null" +
+ " AND profile.name is not null" +
+ " AND profile.language is not null" +
+ " AND rule_def.plugin_name is not null" +
+ " AND rule_def.plugin_name is not null" +
+ " order by rule_change.id ASC;";
+
+ private String allDeactivation =
+ "select" +
+ " rule_change.id as id," +
+ " rule_change.change_date as " + CREATED_AT + "," +
+ " users.login as " + USER_LOGIN + "," +
+ " CONCAT(rule_def.plugin_name,':',rule_def.plugin_rule_key) as " + RULE_KEY + "," +
+ " CONCAT(profile.name,':',profile.language) as " + PROFILE_KEY +
+ " from active_rule_changes rule_change" +
+ " left join users on users.name = rule_change.username" +
+ " left join rules rule_def on rule_def.id = rule_change.rule_id" +
+ " left join rules_profiles profile on profile.id = rule_change.profile_id" +
+ " WHERE rule_change.enabled is false" +
+ " AND profile.name is not null" +
+ " AND profile.language is not null" +
+ " AND rule_def.plugin_name is not null" +
+ " AND rule_def.plugin_name is not null" +
+ " order by rule_change.id ASC";
+
+ public ChangeLogMigration(ActivityService service, ActivityDao dao, DbClient db) {
+ this.dao = dao;
+ this.db = db;
+ }
+
+ @Override
+ public void execute() {
+ this.session = db.openSession(false);
+ executeUpsert(ActiveRuleChange.Type.ACTIVATED, allActivation);
+ executeUpsert(ActiveRuleChange.Type.UPDATED, allUpdates);
+ executeUpsert(ActiveRuleChange.Type.DEACTIVATED, allDeactivation);
+ session.commit();
+ session.close();
+ }
+
+ private void executeUpsert(ActiveRuleChange.Type type, String sql) {
+ try {
+ Connection connection = db.database().getDataSource().getConnection();
+ ResultSet result = connection.createStatement().executeQuery(sql);
+
+ //startCase
+ result.next();
+ int currentId = result.getInt("id");
+ Date currentTimeStamp = result.getTimestamp(CREATED_AT);
+ String currentAuthor = getAuthor(result);
+ ActiveRuleChange ruleChange = newActiveRuleChance(type, result);
+ processRuleChange(ruleChange, result);
+
+ while (result.next()) {
+ int id = result.getInt("id");
+ if (id != currentId) {
+ saveActiveRuleChange(ruleChange, currentAuthor, currentTimeStamp);
+ currentId = id;
+ currentTimeStamp = result.getTimestamp(CREATED_AT);
+ currentAuthor = getAuthor(result);
+ ruleChange = newActiveRuleChance(type, result);
+ }
+ processRuleChange(ruleChange, result);
+ }
+ //save the last
+ saveActiveRuleChange(ruleChange, currentAuthor, currentTimeStamp);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String getAuthor(ResultSet result) {
+ try {
+ String author = result.getString(USER_LOGIN);
+ if (StringUtils.isNotEmpty(author) && !author.equals("null")) {
+ return author;
+ } else {
+ return "unknown";
+ }
+ } catch (Exception e) {
+ return "unknown";
+ }
+ }
+
+
+ private void saveActiveRuleChange(ActiveRuleChange ruleChange, String author, Date currentTimeStamp) {
+ ActivityDto activity = ActivityDto.createFor(ruleChange);
+ activity.setType(Activity.Type.ACTIVE_RULE);
+ activity.setAuthor(author);
+ activity.setCreatedAt(currentTimeStamp);
+ dao.insert(session, activity);
+ }
+
+ private void processRuleChange(ActiveRuleChange ruleChange, ResultSet result) throws SQLException {
+
+ try {
+ ruleChange.setSeverity(SeverityUtil.getSeverityFromOrdinal(result.getInt(SEVERITY)));
+ } catch (Exception e) {
+ //System.out.println("e.getMessage() = " + e.getMessage());
+ }
+ try {
+ String param_value = result.getString(PARAM_VALUE);
+ String param_name = result.getString(PARAM_NAME);
+ if (StringUtils.isNotEmpty(param_name) && !param_name.equals("null")) {
+ ruleChange.setParameter(param_name, param_value);
+ }
+ } catch (Exception e) {
+ //System.out.println("e.getMessage() = " + e.getMessage());
+ }
+ }
+
+ private ActiveRuleChange newActiveRuleChance(ActiveRuleChange.Type type, ResultSet result) throws SQLException {
+ return ActiveRuleChange.createFor(
+ type, ActiveRuleKey.of(
+ QualityProfileKey.parse(result.getString(PROFILE_KEY)),
+ RuleKey.parse(result.getString(RULE_KEY))));
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java
index f783170a5c2..1239c2f5cf3 100644
--- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java
+++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java
@@ -32,7 +32,7 @@ import java.util.Map;
public class ActiveRuleChange implements ActivityLog {
- static enum Type {
+ public static enum Type {
ACTIVATED, DEACTIVATED, UPDATED
}
diff --git a/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java b/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
index 442298809e7..62c06b37bd0 100644
--- a/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
+++ b/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
@@ -46,6 +46,7 @@ public class IndexSynchronizer {
long start = System.currentTimeMillis();
db.ruleDao().synchronizeAfter(session, 0);
db.activeRuleDao().synchronizeAfter(session, 0);
+ db.activityDao().synchronizeAfter(session, 0);
session.commit();
LOG.info("Synchronization done in {}ms...", System.currentTimeMillis()-start);
session.close();
diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/548_update_logs_to_activities.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/548_update_logs_to_activities.rb
new file mode 100644
index 00000000000..5dc87440153
--- /dev/null
+++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/548_update_logs_to_activities.rb
@@ -0,0 +1,31 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube 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.
+#
+# SonarQube 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 this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+#
+# SonarQube 4.4
+# SONAR-5218
+#
+class UpdateLogsToActivities < ActiveRecord::Migration
+
+ def self.up
+ Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.v44.ChangeLogMigration')
+ end
+
+end
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest.java
new file mode 100644
index 00000000000..0fcc7f2a5d0
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest.java
@@ -0,0 +1,74 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.db.migrations.v44;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.TestDatabase;
+import org.sonar.server.activity.db.ActivityDao;
+import org.sonar.server.db.DbClient;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ChangeLogMigrationTest {
+
+ @ClassRule
+ public static TestDatabase db = new TestDatabase();
+
+ @Mock
+ System2 system2;
+
+ DbClient dbClient;
+ ActivityDao dao;
+ ChangeLogMigration migration;
+ DbSession session;
+
+ @Before
+ public void setUp() throws Exception {
+ when(system2.now()).thenReturn(DateUtils.parseDate("2014-03-13").getTime());
+ dao = new ActivityDao(system2);
+ dbClient = new DbClient(db.database(), db.myBatis(), dao);
+ migration = new ChangeLogMigration(null, dao, dbClient);
+ session = dbClient.openSession(false);
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void migrate() throws Exception {
+ db.prepareDbUnit(getClass(), "active_rules_changes.xml");
+ migration.execute();
+
+ assertThat(dao.findAll(session)).hasSize(5);
+ }
+} \ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest/active_rules_changes.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest/active_rules_changes.xml
new file mode 100644
index 00000000000..56840af9dc4
--- /dev/null
+++ b/sonar-server/src/test/resources/org/sonar/server/db/migrations/v44/ChangeLogMigrationTest/active_rules_changes.xml
@@ -0,0 +1,43 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<dataset>
+
+ <rules_profiles id="10" name="DB_Testing" language="java"/>
+
+ <active_rule_changes id="122" profile_id="10" profile_version="2" rule_id="1" change_date="2011-11-03 20:20:05.158"
+ enabled="true" old_severity="[null]" new_severity="1" username="Administrator"/>
+
+ <active_rule_changes id="123" profile_id="10" profile_version="2" rule_id="1" change_date="2011-12-04 10:20:05.158"
+ enabled="[null]" old_severity="1" new_severity="4" username="asdasads"/>
+
+ <active_rule_changes id="126" profile_id="10" profile_version="2" rule_id="1" change_date="2011-12-04 20:20:05.158"
+ enabled="[null]" old_severity="[null]" new_severity="[null]" username="Administrator"/>
+ <active_rule_param_changes id="1" active_rule_change_id="126" rules_parameter_id="11" old_value="[null]"
+ new_value="TODO"/>
+ <active_rule_param_changes id="2" active_rule_change_id="126" rules_parameter_id="12" old_value="[null]"
+ new_value="FIXME"/>
+ <active_rule_param_changes id="3" active_rule_change_id="126" rules_parameter_id="13" old_value="[null]"
+ new_value="NOSONAR"/>
+
+ <active_rule_changes id="124" profile_id="10" profile_version="2" rule_id="2" change_date="2011-12-05 20:20:05.158"
+ enabled="true" old_severity="[null]" new_severity="1" username="Administrator"/>
+ <active_rule_param_changes id="4" active_rule_change_id="124" rules_parameter_id="21" old_value="[null]"
+ new_value="TODO"/>
+ <active_rule_param_changes id="5" active_rule_change_id="124" rules_parameter_id="22" old_value="[null]"
+ new_value="FIXME"/>
+
+ <active_rule_changes id="125" profile_id="10" profile_version="2" rule_id="2" change_date="2011-12-06 20:20:05.158"
+ enabled="false" old_severity="1" new_severity="[null]" username="[null]"/>
+
+ <rules id="1" plugin_name="xoo" plugin_rule_key="S001"/>
+ <rules id="2" plugin_name="xoo" plugin_rule_key="S002"/>
+
+ <rules_parameters id="11" rule_id="1" param_type="STRING" name="param1"/>
+ <rules_parameters id="12" rule_id="1" param_type="STRING" name="param2"/>
+ <rules_parameters id="13" rule_id="1" param_type="STRING" name="param3"/>
+
+ <rules_parameters id="21" rule_id="2" param_type="STRING" name="PARAM1"/>
+ <rules_parameters id="22" rule_id="2" param_type="STRING" name="PARAM2"/>
+
+ <users id="1111" name="Administrator" login="admin"/>
+
+</dataset>