*/
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
"widgets",
"widget_properties",
"activities"
- );
+ );
private MyBatis mybatis;
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;
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);
@Override
public void synchronizeAfter(DbSession session, long timestamp) {
- throw new IllegalStateException("Log Index does not synchronize!");
+
}
}
}
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()) {
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;
// 4.4
IssueActionPlanKeyMigration.class,
- MeasureDataMigration.class
+ MeasureDataMigration.class,
+ ChangeLogMigration.class
);
}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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();
+}
+
--- /dev/null
+/*
+ * 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))));
+ }
+}
public class ActiveRuleChange implements ActivityLog {
- static enum Type {
+ public static enum Type {
ACTIVATED, DEACTIVATED, UPDATED
}
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();
--- /dev/null
+#
+# 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+<?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>