diff options
63 files changed, 1395 insertions, 124 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index 4634bcb01fe..61d8a1380e1 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -196,6 +196,7 @@ public class CorePlugin extends SonarPlugin { // batch extensions.add(ProfileSensor.class); + extensions.add(ProfileEventsSensor.class); extensions.add(ProjectLinksSensor.class); extensions.add(AsynchronousMeasuresSensor.class); extensions.add(UnitTestDecorator.class); diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileEventsSensor.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileEventsSensor.java new file mode 100644 index 00000000000..76283ba34b9 --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileEventsSensor.java @@ -0,0 +1,82 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 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.plugins.core.sensors; + +import org.sonar.api.batch.*; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.resources.Project; + +import java.util.List; + +public class ProfileEventsSensor implements Sensor { + + private final RulesProfile profile; + private final TimeMachine timeMachine; + + public ProfileEventsSensor(RulesProfile profile, TimeMachine timeMachine) { + this.profile = profile; + this.timeMachine = timeMachine; + } + + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + public void analyse(Project project, SensorContext context) { + if (profile == null) { + return; + } + String currentProfile = profile.getName(); + int currentProfileId = profile.getId(); + int currentProfileVersion = profile.getVersion(); + + int pastProfileId = getPreviousMeasureValue(project, CoreMetrics.PROFILE, -1); + int pastProfileVersion = getPreviousMeasureValue(project, CoreMetrics.PROFILE, 1); + + if (pastProfileId != currentProfileId) { + // A different profile is used for this project + context.createEvent(project, currentProfile + " V" + currentProfileVersion, + "A different quality profile was used", Event.CATEGORY_PROFILE, null); + } else if (pastProfileVersion != currentProfileVersion) { + // Same profile but new version + context.createEvent(project, currentProfile + " V" + currentProfileVersion, + "A new version of the quality profile was used", Event.CATEGORY_PROFILE, null); + } + } + + private int getPreviousMeasureValue(Project project, Metric metric, int defaultValue) { + TimeMachineQuery query = new TimeMachineQuery(project) + .setOnlyLastAnalysis(true) + .setMetrics(metric); + List<Measure> measures = timeMachine.getMeasures(query); + if (measures.isEmpty()) { + return defaultValue; + } + return measures.get(0).getIntValue(); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileSensor.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileSensor.java index fb8787355d8..5468467055d 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileSensor.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileSensor.java @@ -21,6 +21,7 @@ package org.sonar.plugins.core.sensors; import org.sonar.api.batch.Sensor; import org.sonar.api.batch.SensorContext; +import org.sonar.api.database.DatabaseSession; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Measure; import org.sonar.api.profiles.RulesProfile; @@ -28,10 +29,12 @@ import org.sonar.api.resources.Project; public class ProfileSensor implements Sensor { - private RulesProfile profile; + private final RulesProfile profile; + private final DatabaseSession session; - public ProfileSensor(RulesProfile profile) { + public ProfileSensor(RulesProfile profile, DatabaseSession session) { this.profile = profile; + this.session = session; } public boolean shouldExecuteOnProject(Project project) { @@ -41,10 +44,15 @@ public class ProfileSensor implements Sensor { public void analyse(Project project, SensorContext context) { if (profile != null) { Measure measure = new Measure(CoreMetrics.PROFILE, profile.getName()); + Measure measureVersion = new Measure(CoreMetrics.PROFILE_VERSION, Integer.valueOf(profile.getVersion()).doubleValue()); if (profile.getId() != null) { measure.setValue(profile.getId().doubleValue()); + + profile.setUsed(true); + session.merge(profile); } context.saveMeasure(measure); + context.saveMeasure(measureVersion); } } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileEventsSensorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileEventsSensorTest.java new file mode 100644 index 00000000000..d0b44316eaf --- /dev/null +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileEventsSensorTest.java @@ -0,0 +1,162 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 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.plugins.core.sensors; + +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.Event; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.TimeMachine; +import org.sonar.api.batch.TimeMachineQuery; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; + +import java.text.ParseException; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; + +public class ProfileEventsSensorTest { + + private Project project; + private SensorContext context; + + @Before + public void prepare() { + project = mock(Project.class); + context = mock(SensorContext.class); + } + + @Test + public void shouldDoNothingIfNoProfile() throws ParseException { + ProfileEventsSensor sensor = new ProfileEventsSensor(null, null); + + sensor.analyse(project, context); + + verify(context, never()).createEvent((Resource) anyObject(), anyString(), anyString(), anyString(), (Date) anyObject()); + } + + @Test + public void shouldDoNothingIfNoProfileChange() throws ParseException { + RulesProfile profile = mockProfile(1); + TimeMachine timeMachine = mockTM(project, 22.0, 1.0); // Same profile, same version + ProfileEventsSensor sensor = new ProfileEventsSensor(profile, timeMachine); + + sensor.analyse(project, context); + + verify(context, never()).createEvent((Resource) anyObject(), anyString(), anyString(), anyString(), (Date) anyObject()); + } + + @Test + public void shouldCreateEventIfProfileChange() throws ParseException { + RulesProfile profile = mockProfile(1); + TimeMachine timeMachine = mockTM(project, 21.0, 1.0); // Different profile + ProfileEventsSensor sensor = new ProfileEventsSensor(profile, timeMachine); + + sensor.analyse(project, context); + + verify(context).createEvent(same(project), eq("Profile V1"), eq("A different quality profile was used"), + same(Event.CATEGORY_PROFILE), (Date) anyObject()); + } + + @Test + public void shouldCreateEventIfProfileVersionChange() throws ParseException { + RulesProfile profile = mockProfile(2); + TimeMachine timeMachine = mockTM(project, 22.0, 1.0); // Same profile, different version + ProfileEventsSensor sensor = new ProfileEventsSensor(profile, timeMachine); + + sensor.analyse(project, context); + + verify(context).createEvent(same(project), eq("Profile V2"), eq("A new version of the quality profile was used"), + same(Event.CATEGORY_PROFILE), (Date) anyObject()); + } + + @Test + public void shouldCreateEventIfFirstAnalysis() throws ParseException { + RulesProfile profile = mockProfile(2); + TimeMachine timeMachine = mockTM(project, null, null); + ProfileEventsSensor sensor = new ProfileEventsSensor(profile, timeMachine); + + sensor.analyse(project, context); + + verify(context).createEvent(same(project), eq("Profile V2"), eq("A different quality profile was used"), + same(Event.CATEGORY_PROFILE), (Date) anyObject()); + } + + @Test + public void shouldNotCreateEventIfFirstProfileVersionAndStillV1() throws ParseException { + RulesProfile profile = mockProfile(1); + TimeMachine timeMachine = mockTMWithNullVersion(project, 22.0); + ProfileEventsSensor sensor = new ProfileEventsSensor(profile, timeMachine); + + sensor.analyse(project, context); + + verify(context, never()).createEvent((Resource) anyObject(), anyString(), anyString(), anyString(), (Date) anyObject()); + } + + @Test + public void shouldCreateEventIfFirstProfileVersionAndMoreThanV1() throws ParseException { + RulesProfile profile = mockProfile(2); + TimeMachine timeMachine = mockTMWithNullVersion(project, 22.0); + ProfileEventsSensor sensor = new ProfileEventsSensor(profile, timeMachine); + + sensor.analyse(project, context); + + verify(context).createEvent(same(project), eq("Profile V2"), eq("A new version of the quality profile was used"), + same(Event.CATEGORY_PROFILE), (Date) anyObject()); + } + + private RulesProfile mockProfile(int version) { + RulesProfile profile = mock(RulesProfile.class); + when(profile.getId()).thenReturn(22); + when(profile.getName()).thenReturn("Profile"); + when(profile.getVersion()).thenReturn(version); // New version + return profile; + } + + private TimeMachine mockTM(Project project, double profileValue, double versionValue) { + return mockTM(project, new Measure(CoreMetrics.PROFILE, profileValue), + new Measure(CoreMetrics.PROFILE_VERSION, versionValue)); + } + + private TimeMachine mockTMWithNullVersion(Project project, double profileValue) { + return mockTM(project, new Measure(CoreMetrics.PROFILE, profileValue), null); + } + + private TimeMachine mockTM(Project project, Measure result1, Measure result2) { + TimeMachine timeMachine = mock(TimeMachine.class); + + when(timeMachine.getMeasures(any(TimeMachineQuery.class))) + .thenReturn(result1 == null ? Collections.<Measure> emptyList() : Arrays.asList(result1)) + .thenReturn(result2 == null ? Collections.<Measure> emptyList() : Arrays.asList(result2)); + + return timeMachine; + } + +} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileSensorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileSensorTest.java index 29ac9fad4ec..9357657db9d 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileSensorTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileSensorTest.java @@ -23,6 +23,7 @@ import org.junit.Test; import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.*; import org.sonar.api.batch.SensorContext; +import org.sonar.api.database.DatabaseSession; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.test.IsMeasure; @@ -34,11 +35,14 @@ public class ProfileSensorTest { RulesProfile profile = mock(RulesProfile.class); when(profile.getId()).thenReturn(22); when(profile.getName()).thenReturn("fake"); + when(profile.getVersion()).thenReturn(2); SensorContext context = mock(SensorContext.class); + DatabaseSession session = mock(DatabaseSession.class); - ProfileSensor sensor = new ProfileSensor(profile); + ProfileSensor sensor = new ProfileSensor(profile, session); sensor.analyse(null, context); verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.PROFILE, 22d))); + verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.PROFILE_VERSION, 2d))); } } diff --git a/sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java b/sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java index 039029276d7..25351acce12 100644 --- a/sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java +++ b/sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java @@ -40,7 +40,7 @@ public class SchemaMigration { - complete the Derby DDL file used for unit tests : sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl */ - public static final int LAST_VERSION = 201; + public static final int LAST_VERSION = 202; public final static String TABLE_NAME = "schema_migrations"; diff --git a/sonar-core/src/main/resources/META-INF/persistence.xml b/sonar-core/src/main/resources/META-INF/persistence.xml index 304887e52b7..4d287d8a0df 100644 --- a/sonar-core/src/main/resources/META-INF/persistence.xml +++ b/sonar-core/src/main/resources/META-INF/persistence.xml @@ -35,7 +35,9 @@ <class>org.sonar.api.database.model.AsyncMeasureSnapshot</class> <class>org.sonar.api.batch.Event</class> <class>org.sonar.api.profiles.Alert</class> - + <class>org.sonar.api.rules.ActiveRuleChange</class> + <class>org.sonar.api.rules.ActiveRuleParamChange</class> + <properties> <property name="hibernate.current_session_context_class" value="thread"/> <property name="hibernate.connection.release_mode" value="after_transaction"/> diff --git a/sonar-core/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java b/sonar-core/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java index 6e9aa22013a..834657bb7f9 100644 --- a/sonar-core/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java +++ b/sonar-core/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java @@ -29,7 +29,9 @@ import org.dbunit.database.IDatabaseConnection; import org.dbunit.dataset.CompositeDataSet; import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; import org.dbunit.dataset.ReplacementDataSet; +import org.dbunit.dataset.filter.DefaultColumnFilter; import org.dbunit.dataset.xml.FlatXmlDataSet; import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory; import org.dbunit.operation.DatabaseOperation; @@ -147,12 +149,17 @@ public abstract class AbstractDbUnitTestCase { } protected final void checkTables(String testName, String... tables) { + checkTables(testName, new String[] {}, tables); + } + + protected final void checkTables(String testName, String[] excludedColumnNames, String... tables) { getSession().commit(); try { IDataSet dataSet = getCurrentDataSet(); IDataSet expectedDataSet = getExpectedData(testName); for (String table : tables) { - Assertion.assertEquals(expectedDataSet.getTable(table), dataSet.getTable(table)); + ITable filteredTable = DefaultColumnFilter.excludedColumnsTable(dataSet.getTable(table), excludedColumnNames); + Assertion.assertEquals(expectedDataSet.getTable(table), filteredTable); } } catch (DataSetException e) { throw translateException("Error while checking results", e); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/Event.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/Event.java index b1a7f1e19b9..fa2263548d6 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/Event.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/Event.java @@ -35,6 +35,7 @@ import javax.persistence.*; public class Event extends BaseIdentifiable { public static final String CATEGORY_VERSION = "Version"; public static final String CATEGORY_ALERT = "Alert"; + public static final String CATEGORY_PROFILE = "Profile"; @Column(name = "name", updatable = true, nullable = true, length = 50) private String name; @@ -121,6 +122,10 @@ public class Event extends BaseIdentifiable { return CATEGORY_VERSION.equalsIgnoreCase(category); } + public boolean isProfileCategory() { + return CATEGORY_PROFILE.equalsIgnoreCase(category); + } + public Date getDate() { return date; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/TimeMachineQuery.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/TimeMachineQuery.java index 13f8818d0bc..20b0ee861c0 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/TimeMachineQuery.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/TimeMachineQuery.java @@ -19,6 +19,8 @@ */ package org.sonar.api.batch; +import org.apache.commons.lang.builder.EqualsBuilder; + import com.google.common.collect.Lists; import org.apache.commons.lang.builder.ToStringBuilder; import org.sonar.api.measures.Metric; @@ -231,4 +233,10 @@ public class TimeMachineQuery { .append("to", to) .toString(); } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java index 4e265bac406..2cf3d598b40 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java @@ -1141,6 +1141,12 @@ public final class CoreMetrics { .setDomain(DOMAIN_GENERAL) .create(); + public static final String PROFILE_VERSION_KEY = "profile_version"; + public static final Metric PROFILE_VERSION = new Metric.Builder(PROFILE_VERSION_KEY, "Profile version", Metric.ValueType.INT) + .setDescription("Selected quality profile version") + .setQualitative(false) + .setDomain(DOMAIN_GENERAL) + .create(); public static List<Metric> metrics = Lists.newLinkedList(); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/profiles/RulesProfile.java b/sonar-plugin-api/src/main/java/org/sonar/api/profiles/RulesProfile.java index 5b34326daf6..e7f61d92df6 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/profiles/RulesProfile.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/profiles/RulesProfile.java @@ -64,6 +64,9 @@ public class RulesProfile implements Cloneable { @Column(name = "name", updatable = true, nullable = false) private String name; + @Column(name = "version", updatable = true, nullable = false) + private int version = 1; + @Column(name = "default_profile", updatable = true, nullable = false) private Boolean defaultProfile = Boolean.FALSE; @@ -73,6 +76,9 @@ public class RulesProfile implements Cloneable { @Column(name = "enabled", updatable = true, nullable = false) private Boolean enabled = Boolean.TRUE; + @Column(name = "used_profile", updatable = true, nullable = false) + private Boolean used = Boolean.FALSE; + @Column(name = "language", updatable = true, nullable = false) private String language; @@ -135,6 +141,24 @@ public class RulesProfile implements Cloneable { this.name = s; return this; } + + public int getVersion() { + return version; + } + + public RulesProfile setVersion(int version) { + this.version = version; + return this; + } + + public Boolean getUsed() { + return used; + } + + public RulesProfile setUsed(Boolean used) { + this.used = used; + return this; + } /** * @return the list of active rules diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rules/ActiveRuleChange.java b/sonar-plugin-api/src/main/java/org/sonar/api/rules/ActiveRuleChange.java new file mode 100644 index 00000000000..a3b95213220 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/rules/ActiveRuleChange.java @@ -0,0 +1,213 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 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.api.rules; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.api.database.BaseIdentifiable; +import org.sonar.api.profiles.RulesProfile; + +/** + * A class to map a RuleChange to the hibernate model + * + * @since 2.9 + */ +@Entity +@Table(name = "active_rule_changes") +public class ActiveRuleChange extends BaseIdentifiable { + + @Column(name = "user_login", updatable = false, nullable = false) + private String modifierLogin; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "profile_id", updatable = false, nullable = false) + private RulesProfile rulesProfile; + + @Column(name = "profile_version", updatable = false, nullable = false) + private int profileVersion; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "rule_id", updatable = false, nullable = false) + private Rule rule; + + @Column(name = "change_date", updatable = false, nullable = false) + private Date date; + + /** + * true means rule was enabled + * false means rule was disabled + * null means rule stay enabled (another param was changed) + */ + @Column(name = "enabled") + private Boolean enabled; + + @Column(name = "old_severity", updatable = false, nullable = true) + @Enumerated(EnumType.ORDINAL) + private RulePriority oldSeverity; + + @Column(name = "new_severity", updatable = false, nullable = true) + @Enumerated(EnumType.ORDINAL) + private RulePriority newSeverity; + + @OneToMany(mappedBy = "activeRuleChange", fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }) + private List<ActiveRuleParamChange> activeRuleParamChanges = new ArrayList<ActiveRuleParamChange>(); + + public ActiveRuleChange(String modifierLogin, RulesProfile profile, Rule rule) { + this.modifierLogin = modifierLogin; + this.rulesProfile = profile; + this.profileVersion = profile.getVersion(); + this.rule = rule; + this.date = Calendar.getInstance().getTime(); + } + + public Rule getRule() { + return rule; + } + + public RulePriority getOldSeverity() { + return oldSeverity; + } + + public void setOldSeverity(RulePriority oldSeverity) { + this.oldSeverity = oldSeverity; + } + + public RulePriority getNewSeverity() { + return newSeverity; + } + + public void setNewSeverity(RulePriority newSeverity) { + this.newSeverity = newSeverity; + } + + public RulesProfile getRulesProfile() { + return rulesProfile; + } + + public int getProfileVersion() { + return profileVersion; + } + + public String getRepositoryKey() { + return rule.getRepositoryKey(); + } + + /** + * @return the config key the changed rule belongs to + */ + public String getConfigKey() { + return rule.getConfigKey(); + } + + /** + * @return the key of the changed rule + */ + public String getRuleKey() { + return rule.getKey(); + } + + public Boolean isEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public List<ActiveRuleParamChange> getActiveRuleParamChanges() { + return activeRuleParamChanges; + } + + public String getModifierLogin() { + return modifierLogin; + } + + public ActiveRuleChange setParameterChange(String key, String oldValue, String newValue) { + RuleParam ruleParameter = rule.getParam(key); + if (ruleParameter != null) { + activeRuleParamChanges.add(new ActiveRuleParamChange(this, ruleParameter, oldValue, newValue)); + } + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (obj.getClass() != getClass()) { + return false; + } + ActiveRuleChange rhs = (ActiveRuleChange) obj; + return new EqualsBuilder() + .appendSuper(super.equals(obj)) + .append(modifierLogin, rhs.modifierLogin) + .append(rulesProfile, rhs.rulesProfile) + .append(rule, rhs.rule) + .append(date, rhs.date) + .append(enabled, rhs.enabled) + .append(newSeverity, rhs.newSeverity) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(41, 33) + .append(modifierLogin) + .append(rulesProfile) + .append(rule) + .append(date) + .append(enabled) + .append(newSeverity) + .toHashCode(); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("id", getId()) + .append("profile", rulesProfile) + .append("rule", rule) + .append("modifier", modifierLogin) + .append("changed at", date) + .append("enabled", enabled) + .append("new severity", newSeverity) + .toString(); + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rules/ActiveRuleParamChange.java b/sonar-plugin-api/src/main/java/org/sonar/api/rules/ActiveRuleParamChange.java new file mode 100644 index 00000000000..be7d2cef003 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/rules/ActiveRuleParamChange.java @@ -0,0 +1,97 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 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.api.rules; + +import org.sonar.api.database.BaseIdentifiable; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +import javax.persistence.*; + +/** + * @since 2.9 + */ +@Entity +@Table(name = "active_rule_param_changes") +public class ActiveRuleParamChange extends BaseIdentifiable { + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "active_rule_change_id") + private ActiveRuleChange activeRuleChange; + + @ManyToOne(fetch = FetchType.LAZY, optional = true) + @JoinColumn(name = "rules_parameter_id") + private RuleParam ruleParam; + + @Column(name = "old_value", updatable = false, nullable = true, length = 4000) + private String oldValue; + + @Column(name = "new_value", updatable = false, nullable = true, length = 4000) + private String newValue; + + ActiveRuleParamChange(ActiveRuleChange activeRuleChange, RuleParam ruleParam, String oldValue, String newValue) { + this.activeRuleChange = activeRuleChange; + this.ruleParam = ruleParam; + this.oldValue = oldValue; + this.newValue = newValue; + } + + public ActiveRuleChange getActiveRuleChange() { + return activeRuleChange; + } + + public RuleParam getRuleParam() { + return ruleParam; + } + + public String getOldValue() { + return oldValue; + } + + public String getNewValue() { + return newValue; + } + + public String getKey() { + return ruleParam.getKey(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ActiveRuleParamChange)) { + return false; + } + if (this == obj) { + return true; + } + ActiveRuleParamChange other = (ActiveRuleParamChange) obj; + return new EqualsBuilder() + .append(getId(), other.getId()).isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 57) + .append(getId()) + .toHashCode(); + } + +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/profiles/RulesProfileTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/profiles/RulesProfileTest.java index 944805f866c..dd364486646 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/profiles/RulesProfileTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/profiles/RulesProfileTest.java @@ -54,4 +54,10 @@ public class RulesProfileTest { profile.activateRule(rule, RulePriority.MINOR); assertThat(profile.getActiveRule("repo", "key1").getSeverity(), is(RulePriority.MINOR)); } + + @Test + public void defaultVersionIs1() { + RulesProfile profile = RulesProfile.create(); + assertThat(profile.getVersion(), is(1)); + } } diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java b/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java index 4dcd6e1b1e3..958fe22220b 100644 --- a/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java +++ b/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesBackup.java @@ -85,10 +85,18 @@ public class ProfilesBackup implements Backupable { } public void importProfile(RulesDao rulesDao, RulesProfile toImport) { - if (toImport.getEnabled()==null) { + if (toImport.getEnabled() == null) { // backward-compatibility with versions < 2.6. The field "enabled" did not exist. Default value is true. toImport.setEnabled(true); } + if (toImport.getVersion() == 0) { + // backward-compatibility with versions < 2.9. The field "version" did not exist. Default value is 1. + toImport.setVersion(1); + } + if (toImport.getUsed() == null) { + // backward-compatibility with versions < 2.9. The field "used_profile" did not exist. Default value is false. + toImport.setUsed(false); + } importActiveRules(rulesDao, toImport); importAlerts(toImport); session.save(toImport); diff --git a/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesManager.java b/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesManager.java index 4734352e979..52549bc52c0 100644 --- a/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesManager.java +++ b/sonar-server/src/main/java/org/sonar/server/configuration/ProfilesManager.java @@ -23,7 +23,10 @@ import org.sonar.api.database.DatabaseSession; import org.sonar.api.database.model.ResourceModel; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.rules.ActiveRule; +import org.sonar.api.rules.ActiveRuleChange; import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleParam; +import org.sonar.api.rules.RulePriority; import org.sonar.api.utils.ValidationMessages; import org.sonar.jpa.dao.BaseDao; import org.sonar.jpa.dao.RulesDao; @@ -67,6 +70,10 @@ public class ProfilesManager extends BaseDao { public void deleteProfile(int profileId) { RulesProfile profile = getSession().getEntity(RulesProfile.class, profileId); if (profile != null && !profile.getProvided() && getChildren(profile).isEmpty()) { + //Remove history of rule changes + String hqlDeleteRc = "DELETE " + ActiveRuleChange.class.getSimpleName() + " rc WHERE rc.rulesProfile=:rulesProfile"; + getSession().createQuery(hqlDeleteRc).setParameter("rulesProfile", profile).executeUpdate(); + String hql = "UPDATE " + ResourceModel.class.getSimpleName() + " o SET o.rulesProfile=null WHERE o.rulesProfile=:rulesProfile"; getSession().createQuery(hql).setParameter("rulesProfile", profile).executeUpdate(); getSession().remove(profile); @@ -75,6 +82,10 @@ public class ProfilesManager extends BaseDao { } public void deleteAllProfiles() { + //Remove history of rule changes + String hqlDeleteRc = "DELETE " + ActiveRuleChange.class.getSimpleName() + " rc"; + getSession().createQuery(hqlDeleteRc).executeUpdate(); + String hql = "UPDATE " + ResourceModel.class.getSimpleName() + " o SET o.rulesProfile = null WHERE o.rulesProfile IS NOT NULL"; getSession().createQuery(hql).executeUpdate(); List profiles = getSession().createQuery("FROM " + RulesProfile.class.getSimpleName()).getResultList(); @@ -86,7 +97,7 @@ public class ProfilesManager extends BaseDao { // Managing inheritance of profiles - public ValidationMessages changeParentProfile(Integer profileId, String parentName) { + public ValidationMessages changeParentProfile(Integer profileId, String parentName, String userLogin) { ValidationMessages messages = ValidationMessages.create(); RulesProfile profile = getSession().getEntity(RulesProfile.class, profileId); if (profile != null && !profile.getProvided()) { @@ -99,13 +110,13 @@ public class ProfilesManager extends BaseDao { // Deactivate all inherited rules if (oldParent != null) { for (ActiveRule activeRule : oldParent.getActiveRules()) { - deactivate(profile, activeRule.getRule()); + deactivate(profile, activeRule.getRule(), userLogin); } } // Activate all inherited rules if (newParent != null) { for (ActiveRule activeRule : newParent.getActiveRules()) { - activateOrChange(profile, activeRule); + activateOrChange(profile, activeRule, userLogin); } } profile.setParentName(newParent == null ? null : newParent.getName()); @@ -116,16 +127,53 @@ public class ProfilesManager extends BaseDao { } /** + * Rule was activated + */ + public void activated(int profileId, int activeRuleId, String userLogin) { + ActiveRule activeRule = getSession().getEntity(ActiveRule.class, activeRuleId); + RulesProfile profile = getSession().getEntity(RulesProfile.class, profileId); + ruleEnabled(profile, activeRule, userLogin); + //Notify child profiles + activatedOrChanged(profileId, activeRuleId, userLogin); + } + + /** + * Rule param was changed + */ + public void ruleParamChanged(int profileId, int activeRuleId, String paramKey, String oldValue, String newValue, String userLogin) { + ActiveRule activeRule = getSession().getEntity(ActiveRule.class, activeRuleId); + RulesProfile profile = getSession().getEntity(RulesProfile.class, profileId); + + ruleParamChanged(profile, activeRule.getRule(), paramKey, oldValue, newValue, userLogin); + + //Notify child profiles + activatedOrChanged(profileId, activeRuleId, userLogin); + } + + /** + * Rule severity was changed + */ + public void ruleSeverityChanged(int profileId, int activeRuleId, RulePriority oldSeverity, RulePriority newSeverity, String userLogin) { + ActiveRule activeRule = getSession().getEntity(ActiveRule.class, activeRuleId); + RulesProfile profile = getSession().getEntity(RulesProfile.class, profileId); + + ruleSeverityChanged(profile, activeRule.getRule(), oldSeverity, newSeverity, userLogin); + + //Notify child profiles + activatedOrChanged(profileId, activeRuleId, userLogin); + } + + /** * Rule was activated/changed in parent profile. */ - public void activatedOrChanged(int parentProfileId, int activeRuleId) { + private void activatedOrChanged(int parentProfileId, int activeRuleId, String userLogin) { ActiveRule parentActiveRule = getSession().getEntity(ActiveRule.class, activeRuleId); if (parentActiveRule.isInherited()) { parentActiveRule.setInheritance(ActiveRule.OVERRIDES); getSession().saveWithoutFlush(parentActiveRule); } for (RulesProfile child : getChildren(parentProfileId)) { - activateOrChange(child, parentActiveRule); + activateOrChange(child, parentActiveRule, userLogin); } getSession().commit(); } @@ -133,10 +181,12 @@ public class ProfilesManager extends BaseDao { /** * Rule was deactivated in parent profile. */ - public void deactivated(int parentProfileId, int ruleId) { - Rule rule = getSession().getEntity(Rule.class, ruleId); + public void deactivated(int parentProfileId, int deactivatedRuleId, String userLogin) { + ActiveRule parentActiveRule = getSession().getEntity(ActiveRule.class, deactivatedRuleId); + RulesProfile profile = getSession().getEntity(RulesProfile.class, parentProfileId); + ruleDisabled(profile, parentActiveRule, userLogin); for (RulesProfile child : getChildren(parentProfileId)) { - deactivate(child, rule); + deactivate(child, parentActiveRule.getRule(), userLogin); } getSession().commit(); } @@ -154,52 +204,158 @@ public class ProfilesManager extends BaseDao { return false; } - public void revert(int profileId, int activeRuleId) { + public void revert(int profileId, int activeRuleId, String userLogin) { RulesProfile profile = getSession().getEntity(RulesProfile.class, profileId); - ActiveRule activeRule = getSession().getEntity(ActiveRule.class, activeRuleId); - if (activeRule != null && activeRule.doesOverride()) { - ActiveRule parentActiveRule = getParentProfile(profile).getActiveRule(activeRule.getRule()); - removeActiveRule(profile, activeRule); - activeRule = (ActiveRule) parentActiveRule.clone(); - activeRule.setRulesProfile(profile); - activeRule.setInheritance(ActiveRule.INHERITED); - profile.addActiveRule(activeRule); - getSession().saveWithoutFlush(activeRule); + ActiveRule oldActiveRule = getSession().getEntity(ActiveRule.class, activeRuleId); + if (oldActiveRule != null && oldActiveRule.doesOverride()) { + ActiveRule parentActiveRule = getParentProfile(profile).getActiveRule(oldActiveRule.getRule()); + removeActiveRule(profile, oldActiveRule); + ActiveRule newActiveRule = (ActiveRule) parentActiveRule.clone(); + newActiveRule.setRulesProfile(profile); + newActiveRule.setInheritance(ActiveRule.INHERITED); + profile.addActiveRule(newActiveRule); + getSession().saveWithoutFlush(newActiveRule); + + //Compute change + ruleChanged(profile, oldActiveRule, newActiveRule, userLogin); for (RulesProfile child : getChildren(profile)) { - activateOrChange(child, activeRule); + activateOrChange(child, newActiveRule, userLogin); } getSession().commit(); } } + + private synchronized void incrementProfileVersionIfNeeded(RulesProfile profile) { + if (profile.getUsed()) { + profile.setVersion(profile.getVersion() + 1); + profile.setUsed(false); + getSession().saveWithoutFlush(profile); + } + } + + /** + * Deal with creation of ActiveRuleChange item when a rule param is changed on a profile + */ + private void ruleParamChanged(RulesProfile profile, Rule rule, String paramKey, String oldValue, String newValue, String userLogin) { + incrementProfileVersionIfNeeded(profile); + ActiveRuleChange rc = new ActiveRuleChange(userLogin, profile, rule); + if (oldValue != newValue) { + rc.setParameterChange(paramKey, oldValue, newValue); + getSession().saveWithoutFlush(rc); + } + } - private void activateOrChange(RulesProfile profile, ActiveRule parentActiveRule) { - ActiveRule activeRule = profile.getActiveRule(parentActiveRule.getRule()); - if (activeRule != null) { - if (activeRule.isInherited()) { - removeActiveRule(profile, activeRule); + /** + * Deal with creation of ActiveRuleChange item when a rule severity is changed on a profile + */ + private void ruleSeverityChanged(RulesProfile profile, Rule rule, RulePriority oldSeverity, RulePriority newSeverity, String userLogin) { + incrementProfileVersionIfNeeded(profile); + ActiveRuleChange rc = new ActiveRuleChange(userLogin, profile, rule); + if (oldSeverity != newSeverity) { + rc.setOldSeverity(oldSeverity); + rc.setNewSeverity(newSeverity); + getSession().saveWithoutFlush(rc); + } + } + + /** + * Deal with creation of ActiveRuleChange item when a rule is changed (severity and/or param(s)) on a profile + */ + private void ruleChanged(RulesProfile profile, ActiveRule oldActiveRule, ActiveRule newActiveRule, String userLogin) { + incrementProfileVersionIfNeeded(profile); + ActiveRuleChange rc = new ActiveRuleChange(userLogin, profile, newActiveRule.getRule()); + + if (oldActiveRule.getSeverity() != newActiveRule.getSeverity()) { + rc.setOldSeverity(oldActiveRule.getSeverity()); + rc.setNewSeverity(newActiveRule.getSeverity()); + } + if (oldActiveRule.getRule().getParams() != null) { + for (RuleParam p : oldActiveRule.getRule().getParams()) { + String oldParam = oldActiveRule.getParameter(p.getKey()); + String newParam = newActiveRule.getParameter(p.getKey()); + if (oldParam != newParam) { + rc.setParameterChange(p.getKey(), oldParam, newParam); + } + } + } + + getSession().saveWithoutFlush(rc); + } + + /** + * Deal with creation of ActiveRuleChange item when a rule is enabled on a profile + */ + private void ruleEnabled(RulesProfile profile, ActiveRule newActiveRule, String userLogin) { + incrementProfileVersionIfNeeded(profile); + ActiveRuleChange rc = new ActiveRuleChange(userLogin, profile, newActiveRule.getRule()); + rc.setEnabled(true); + rc.setNewSeverity(newActiveRule.getSeverity()); + if (newActiveRule.getRule().getParams() != null) { + for (RuleParam p : newActiveRule.getRule().getParams()) { + String newParam = newActiveRule.getParameter(p.getKey()); + if (newParam != null) { + rc.setParameterChange(p.getKey(), null, newParam); + } + } + } + getSession().saveWithoutFlush(rc); + } + + /** + * Deal with creation of ActiveRuleChange item when a rule is disabled on a profile + */ + private void ruleDisabled(RulesProfile profile, ActiveRule disabledRule, String userLogin) { + incrementProfileVersionIfNeeded(profile); + ActiveRuleChange rc = new ActiveRuleChange(userLogin, profile, disabledRule.getRule()); + rc.setEnabled(false); + rc.setOldSeverity(disabledRule.getSeverity()); + if (disabledRule.getRule().getParams() != null) { + for (RuleParam p : disabledRule.getRule().getParams()) { + String oldParam = disabledRule.getParameter(p.getKey()); + if (oldParam != null) { + rc.setParameterChange(p.getKey(), oldParam, null); + } + } + } + getSession().saveWithoutFlush(rc); + } + + private void activateOrChange(RulesProfile profile, ActiveRule parentActiveRule, String userLogin) { + ActiveRule oldActiveRule = profile.getActiveRule(parentActiveRule.getRule()); + if (oldActiveRule != null) { + if (oldActiveRule.isInherited()) { + removeActiveRule(profile, oldActiveRule); } else { - activeRule.setInheritance(ActiveRule.OVERRIDES); - getSession().saveWithoutFlush(activeRule); + oldActiveRule.setInheritance(ActiveRule.OVERRIDES); + getSession().saveWithoutFlush(oldActiveRule); return; // no need to change in children } } - activeRule = (ActiveRule) parentActiveRule.clone(); - activeRule.setRulesProfile(profile); - activeRule.setInheritance(ActiveRule.INHERITED); - profile.addActiveRule(activeRule); - getSession().saveWithoutFlush(activeRule); + ActiveRule newActiveRule = (ActiveRule) parentActiveRule.clone(); + newActiveRule.setRulesProfile(profile); + newActiveRule.setInheritance(ActiveRule.INHERITED); + profile.addActiveRule(newActiveRule); + getSession().saveWithoutFlush(newActiveRule); + + if (oldActiveRule != null) { + ruleChanged(profile, oldActiveRule, newActiveRule, userLogin); + } + else { + ruleEnabled(profile, newActiveRule, userLogin); + } for (RulesProfile child : getChildren(profile)) { - activateOrChange(child, activeRule); + activateOrChange(child, newActiveRule, userLogin); } } - private void deactivate(RulesProfile profile, Rule rule) { + private void deactivate(RulesProfile profile, Rule rule, String userLogin) { ActiveRule activeRule = profile.getActiveRule(rule); if (activeRule != null) { if (activeRule.isInherited()) { + ruleDisabled(profile, activeRule, userLogin); removeActiveRule(profile, activeRule); } else { activeRule.setInheritance(null); @@ -208,7 +364,7 @@ public class ProfilesManager extends BaseDao { } for (RulesProfile child : getChildren(profile)) { - deactivate(child, rule); + deactivate(child, rule, userLogin); } } } diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index dbadf5ac349..8b8cf857bbb 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -27,6 +27,7 @@ import org.sonar.api.Property; import org.sonar.api.profiles.ProfileExporter; import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.resources.Language; +import org.sonar.api.rules.RulePriority; import org.sonar.api.rules.RuleRepository; import org.sonar.api.utils.ValidationMessages; import org.sonar.api.web.*; @@ -228,20 +229,29 @@ public final class JRubyFacade { getProfilesManager().deleteProfile((int) profileId); } - public ValidationMessages changeParentProfile(int profileId, String parentName) { - return getProfilesManager().changeParentProfile(profileId, parentName); + public ValidationMessages changeParentProfile(int profileId, String parentName, String userLogin) { + return getProfilesManager().changeParentProfile(profileId, parentName, userLogin); } - public void ruleActivatedOrChanged(int parentProfileId, int activeRuleId) { - getProfilesManager().activatedOrChanged(parentProfileId, activeRuleId); + public void ruleActivated(int parentProfileId, int activeRuleId, String userLogin) { + getProfilesManager().activated(parentProfileId, activeRuleId, userLogin); } - public void ruleDeactivated(int parentProfileId, int ruleId) { - getProfilesManager().deactivated(parentProfileId, ruleId); + public void ruleParamChanged(int parentProfileId, int activeRuleId, String paramKey, String oldValue, String newValue, String userLogin) { + getProfilesManager().ruleParamChanged(parentProfileId, activeRuleId, paramKey, oldValue, newValue, userLogin); } - public void revertRule(int profileId, int activeRuleId) { - getProfilesManager().revert(profileId, activeRuleId); + public void ruleSeverityChanged(int parentProfileId, int activeRuleId, int oldSeverityId, int newSeverityId, String userLogin) { + getProfilesManager().ruleSeverityChanged(parentProfileId, activeRuleId, RulePriority.values()[oldSeverityId], + RulePriority.values()[newSeverityId], userLogin); + } + + public void ruleDeactivated(int parentProfileId, int deactivatedRuleId, String userLogin) { + getProfilesManager().deactivated(parentProfileId, deactivatedRuleId, userLogin); + } + + public void revertRule(int profileId, int activeRuleId, String userLogin) { + getProfilesManager().revert(profileId, activeRuleId, userLogin); } public List<Footer> getWebFooters() { diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb index 24339483e4a..81160982d52 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb @@ -196,7 +196,18 @@ class ProfilesController < ApplicationController profiles=Profile.find(:all, :conditions => ['language=? and id<>? and (parent_name is null or parent_name<>?) and enabled=?', @profile.language, @profile.id, @profile.name, true], :order => 'name') @select_parent = [['None', nil]] + profiles.collect{ |profile| [profile.name, profile.name] } end - + + # + # + # GET /profiles/changelog?id=<profile id> + # + # + def changelog + @profile = Profile.find(params[:id]) + + @changes=ActiveRuleChange.find(:all, :conditions => ['profile_id=?', @profile.id], :order => 'id desc') + + end # @@ -208,9 +219,9 @@ class ProfilesController < ApplicationController id = params[:id].to_i parent_name = params[:parent_name] if parent_name.blank? - messages = java_facade.changeParentProfile(id, nil) + messages = java_facade.changeParentProfile(id, nil, current_user.login) else - messages = java_facade.changeParentProfile(id, parent_name) + messages = java_facade.changeParentProfile(id, parent_name, current_user.login) end flash_validation_messages(messages) redirect_to :action => 'inheritance', :id => id diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb index b268f71715c..6659d8d0cc0 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb @@ -84,7 +84,7 @@ class RulesConfigurationController < ApplicationController def revert_rule id = params[:id].to_i rule_id = params[:active_rule_id].to_i - java_facade.revertRule(id, rule_id) + java_facade.revertRule(id, rule_id, current_user.login) redirect_to request.query_parameters.merge({:action => 'index', :id => params[:id], :commit => nil}) end @@ -105,20 +105,29 @@ class RulesConfigurationController < ApplicationController active_rule=profile.active_by_rule_id(rule.id) if priority.blank? # deactivate the rule - active_rule.destroy if active_rule - active_rule=nil - java_facade.ruleDeactivated(profile.id, rule.id) + if active_rule + java_facade.ruleDeactivated(profile.id, active_rule.id, current_user.login) + active_rule.destroy + active_rule=nil + end else # activate the rule + activated = false if active_rule.nil? active_rule = ActiveRule.new(:profile_id => profile.id, :rule => rule) rule.parameters.select{|p| p.default_value.present?}.each do |p| active_rule.active_rule_parameters.build(:rules_parameter => p, :value => p.default_value) end + activated = true end + old_severity = active_rule.failure_level active_rule.failure_level=Sonar::RulePriority.id(priority) active_rule.save! - java_facade.ruleActivatedOrChanged(profile.id, active_rule.id) + if activated + java_facade.ruleActivated(profile.id, active_rule.id, current_user.login) + else + java_facade.ruleSeverityChanged(profile.id, active_rule.id, old_severity, active_rule.failure_level, current_user.login) + end end if active_rule active_rule.reload @@ -286,15 +295,18 @@ class RulesConfigurationController < ApplicationController if !profile.provided? if value != "" active_param = ActiveRuleParameter.new(:rules_parameter => rule_param, :active_rule => active_rule ) if active_param.nil? + old_value = active_param.value active_param.value = value active_param.save active_param.valid? active_param.reload + java_facade.ruleParamChanged(profile.id, active_rule.id, rule_param.name, old_value, value, current_user.login) elsif !active_param.nil? + old_value = active_param.value active_param.destroy active_param = nil + java_facade.ruleParamChanged(profile.id, active_rule.id, rule_param.name, old_value, nil, current_user.login) end - java_facade.ruleActivatedOrChanged(profile.id, active_rule.id) end render :partial => 'rule_param', :object => nil, :locals => {:parameter => rule_param, :active_parameter => active_param, :profile => profile, :active_rule => active_rule, :is_admin => is_admin } @@ -311,7 +323,7 @@ class RulesConfigurationController < ApplicationController count = rules_to_activate.size rules_to_activate.each do |rule| active_rule = profile.active_rules.create(:rule => rule, :failure_level => rule.priority) - java_facade.ruleActivatedOrChanged(profile.id, active_rule.id) + java_facade.ruleActivated(profile.id, active_rule.id, current_user.login) end end count @@ -322,7 +334,7 @@ class RulesConfigurationController < ApplicationController profile.active_rules.each do |ar| if rule_ids.include?(ar.rule_id) && !ar.inheritance.present? ar.destroy - java_facade.ruleDeactivated(profile.id, ar.rule_id) + java_facade.ruleDeactivated(profile.id, ar.rule_id, current_user.login) count+=1 end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/active_rule_change.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/active_rule_change.rb new file mode 100644 index 00000000000..d52c149b6ea --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/active_rule_change.rb @@ -0,0 +1,37 @@ +# +# Sonar, entreprise quality control tool. +# Copyright (C) 2008-2011 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 +# +class ActiveRuleChange < ActiveRecord::Base + belongs_to :rules_profile, :class_name => 'Profile', :foreign_key => 'profile_id' + belongs_to :rule + has_many :active_rule_param_changes, :dependent => :destroy + + def old_severity_text + Sonar::RulePriority.to_s old_severity + end + + def new_severity_text + Sonar::RulePriority.to_s new_severity + end + + def parameters + active_rule_param_changes + end + +end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/active_rule_param_change.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/active_rule_param_change.rb new file mode 100644 index 00000000000..5d91dc78eb8 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/active_rule_param_change.rb @@ -0,0 +1,32 @@ +# +# Sonar, entreprise quality control tool. +# Copyright (C) 2008-2011 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 {library}; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 +# + class ActiveRuleParamChange < ActiveRecord::Base + belongs_to :active_rule_change + belongs_to :rules_parameter + + def name + rules_parameter.name + end + + def parameter + rules_parameter + end + + end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/event_category.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/event_category.rb index 85d76c17fc3..89e957bc7df 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/event_category.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/event_category.rb @@ -23,6 +23,7 @@ class EventCategory KEY_VERSION='Version' KEY_ALERT='Alert' + KEY_PROFILE='Profile' def initialize(name=nil, description=nil) @name=name @@ -80,13 +81,14 @@ class EventCategory end def editable? - !([KEY_VERSION, KEY_ALERT].include?(name)) + !([KEY_VERSION, KEY_ALERT, KEY_PROFILE].include?(name)) end def self.defaults [ EventCategory.new(KEY_VERSION, 'Application version'), - EventCategory.new(KEY_ALERT, 'Alert') + EventCategory.new(KEY_ALERT, 'Alert'), + EventCategory.new(KEY_PROFILE, 'Profile change') ] end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_tabs.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_tabs.html.erb index 2c42cc69e81..5fa8fce9926 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_tabs.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_tabs.html.erb @@ -18,6 +18,9 @@ <li> <a href="<%= url_for :controller => 'profiles', :action => 'inheritance', :id => @profile.id -%>" <%= "class='selected'" if selected_tab=='inheritance' -%>>Profile inheritance</a> </li> + <li> + <a href="<%= url_for :controller => 'profiles', :action => 'changelog', :id => @profile.id -%>" <%= "class='selected'" if selected_tab=='changelog' -%>>Changelog</a> + </li> <% if new_tab %> <li> <a href="#" class='selected'><%= new_tab -%></a> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/changelog.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/changelog.html.erb new file mode 100644 index 00000000000..6a616bfe06c --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/changelog.html.erb @@ -0,0 +1,77 @@ +<h1 class="marginbottom10"><%= link_to 'Quality profiles', :controller => 'profiles', :action => 'index' -%> / <%= h @profile.language -%> / <%= h @profile.name %></h1> +<%= render :partial => 'profiles/tabs', :locals => {:selected_tab=>'changelog'} %> + +<div class="tabs-panel marginbottom10"> + + <table class="data width100"> + <thead> + <tr> + <th>Action</th> + <th>By</th> + <th>Date</th> + <th>Rule name</th> + <th>Parameters</th> + </tr> + </thead> + <% current_version = -1 + @changes.each do |change| + %> + <% if current_version != change.profile_version %> + <tr> + <td align="left" colspan="5"> + <div class="line-block"> + <h2>Version <%=change.profile_version%></h2> + </div> + </td> + </tr> + <% current_version = change.profile_version + end + %> + <tr class="<%= cycle 'even', 'odd', :name => change.profile_version -%>"> + <td valign="top"><%=case change.enabled + when true then "Enabled" + when false then "Disabled" + when nil then "Modified" + end%></td> + <td valign="top"><%=change.user_login%></td> + <td valign="top"><%=change.change_date.strftime("%Y-%m-%d %H:%M:%S")%></td> + <td valign="top"><%=change.rule.name%></td> + <td valign="top"> + <% if change.old_severity + if change.new_severity %> + Severity changed from <i><%= change.old_severity_text %></i> to + <% else %> + Severity was <i><%= change.old_severity_text %></i> + <% end + end %> + <% if change.new_severity + if change.old_severity %> + <i><%= change.new_severity_text %></i> + <% else %> + Severity set to <i><%= change.new_severity_text %></i> + <% end + end %> + <% if (change.old_severity or change.new_severity) and change.parameters.size > 0 %> + <br/> + <% end %> + <% change.parameters.each do |param_change| %> + Parameter <i><%=param_change.name %></i> + <% if not param_change.old_value %> + set to <i><%= param_change.new_value %></i> + <% elsif not param_change.new_value + if change.enabled == false %> + was <i><%= param_change.old_value %></i> + <% else %> + reset to default value (was <i><%= param_change.old_value %></i>) + <% end + else %> + changed from <i><%= param_change.old_value %></i> to <i><%= param_change.new_value %></i> + <% end %> + <%= "<br/>" unless param_change == change.parameters.last %> + <% end%> + </td> + </tr> + <% end %> + </table> + +</div> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb index c3d2cf5104e..c434bd19949 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb @@ -76,6 +76,7 @@ <thead> <tr> <th class="left">Name</th> + <th align="left">Version</th> <th class="right">Rules</th> <th class="right">Alerts</th> <th class="right">Projects</th> @@ -90,6 +91,8 @@ <tr class="<%= cycle 'even', 'odd', :name => language.getKey() -%>" id="<%= u profile.key %>"> <td><a href="<%= url_for :controller => 'rules_configuration', :action => 'index', :id => profile.id -%>" id="rules-<%= language.getKey() -%>-<%= u(profile.name) -%>"><%= h profile.name %></a></td> + <td align="left"><span id="version_<%= u profile.key -%>"><%= profile.version -%></span></td> + <td align="right"> <span id="activated_rules_<%= u profile.key -%>"><%= profile.count_active_rules -%></span> </td> diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/202_create_rule_changes.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/202_create_rule_changes.rb new file mode 100644 index 00000000000..d9a03e5a72d --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/202_create_rule_changes.rb @@ -0,0 +1,53 @@ +# +# Sonar, entreprise quality control tool. +# Copyright (C) 2008-2011 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 +# + +# +# Sonar 2.9 +# +class CreateRuleChanges < ActiveRecord::Migration + + def self.up + create_table :active_rule_changes do |t| + t.column :user_login, :string, :limit => 40, :null => false + t.column :profile_id, :integer, :null => false + t.column :profile_version, :integer, :null => false + t.column :rule_id, :integer, :null => false + t.column :change_date, :datetime, :null => false + t.column :enabled, :boolean, :null => true + t.column :old_severity, :integer, :null => true + t.column :new_severity, :integer, :null => true + end + add_index :active_rule_changes, [:profile_id], :name => 'active_rule_changes_pid' + + create_table :active_rule_param_changes do |t| + t.column :active_rule_change_id, :integer, :null => false + t.column :rules_parameter_id, :integer, :null => false + t.column :old_value, :string, :limit => 4000, :null => true + t.column :new_value, :string, :limit => 4000, :null => true + end + add_index :active_rule_param_changes, [:active_rule_change_id], :name => 'active_rule_param_changes_cid' + + add_column 'rules_profiles', 'version', :integer, :default => 1 + add_column 'rules_profiles', 'used_profile', :boolean, :default => false + Profile.reset_column_information + Profile.update_all(Profile.sanitize_sql_for_assignment({:used_profile => false, :version => 1})) + end + +end diff --git a/sonar-server/src/test/java/org/sonar/server/configuration/InheritedProfilesTest.java b/sonar-server/src/test/java/org/sonar/server/configuration/InheritedProfilesTest.java index 1b95129ad95..55eb7b378f9 100644 --- a/sonar-server/src/test/java/org/sonar/server/configuration/InheritedProfilesTest.java +++ b/sonar-server/src/test/java/org/sonar/server/configuration/InheritedProfilesTest.java @@ -71,35 +71,35 @@ public class InheritedProfilesTest extends AbstractDbUnitTestCase { @Test public void shouldSetParent() { setupData("shouldSetParent"); - profilesManager.changeParentProfile(2, "parent"); + profilesManager.changeParentProfile(2, "parent", "admin"); checkTables("shouldSetParent", "active_rules", "rules_profiles"); } @Test public void shouldChangeParent() { setupData("shouldChangeParent"); - profilesManager.changeParentProfile(3, "new_parent"); + profilesManager.changeParentProfile(3, "new_parent", "admin"); checkTables("shouldChangeParent", "active_rules", "rules_profiles"); } @Test public void shouldRemoveParent() { setupData("shouldRemoveParent"); - profilesManager.changeParentProfile(2, null); + profilesManager.changeParentProfile(2, null, "admin"); checkTables("shouldRemoveParent", "active_rules", "rules_profiles"); } @Test public void shouldDeactivateInChildren() { setupData("shouldDeactivateInChildren"); - profilesManager.deactivated(1, 1); + profilesManager.deactivated(1, 1, "admin"); checkTables("shouldDeactivateInChildren", "active_rules", "rules_profiles"); } @Test public void shouldActivateInChildren() { setupData("shouldActivateInChildren"); - profilesManager.activatedOrChanged(1, 1); + profilesManager.activated(1, 1, "admin"); checkTables("shouldActivateInChildren", "active_rules", "rules_profiles", "active_rule_parameters"); } diff --git a/sonar-server/src/test/java/org/sonar/server/configuration/RuleChangeTest.java b/sonar-server/src/test/java/org/sonar/server/configuration/RuleChangeTest.java new file mode 100644 index 00000000000..d6f3bfd26e4 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/configuration/RuleChangeTest.java @@ -0,0 +1,99 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 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.configuration; + +import org.sonar.api.rules.RulePriority; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.utils.ValidationMessages; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; + +public class RuleChangeTest extends AbstractDbUnitTestCase { + private ProfilesManager profilesManager; + + @Before + public void setUp() { + profilesManager = new ProfilesManager(getSession(), null); + } + + @Test + public void testVersionIncreaseIfUsed() { + setupData("initialData"); + profilesManager.activated(2, 3, "admin"); + checkTables("versionIncreaseIfUsed", "rules_profiles"); + } + + @Test + public void testVersionIncreaseIfUsedAndInChildren() { + setupData("initialData"); + profilesManager.activated(1, 1, "admin"); + checkTables("versionIncreaseIfUsedAndInChildren", "rules_profiles"); + } + + @Test + public void testRuleActivated() { + setupData("initialData"); + profilesManager.activated(2, 3, "admin"); + checkTables("ruleActivated", new String[] {"change_date"}, "active_rule_changes"); + } + + @Test + public void testRuleDeactivated() { + setupData("initialData"); + profilesManager.deactivated(2, 3, "admin"); + checkTables("ruleDeactivated", new String[] {"change_date"}, "active_rule_changes"); + } + + @Test + public void testRuleParamChanged() { + setupData("initialData"); + profilesManager.ruleParamChanged(2, 3, "param1", "20", "30", "admin"); + checkTables("ruleParamChanged", new String[] {"change_date"}, "active_rule_changes", "active_rule_param_changes"); + } + + @Test + public void testRuleSeverityChanged() { + setupData("initialData"); + profilesManager.ruleSeverityChanged(2, 3, RulePriority.BLOCKER, RulePriority.CRITICAL, "admin"); + checkTables("ruleSeverityChanged", new String[] {"change_date"}, "active_rule_changes"); + } + + @Test + public void testRuleReverted() { + setupData("ruleReverted"); + profilesManager.revert(2, 3, "admin"); + checkTables("ruleReverted", new String[] {"change_date"}, "active_rule_changes", "active_rule_param_changes"); + } + + @Test + public void testChangeParentProfile() { + setupData("changeParentProfile"); + profilesManager.changeParentProfile(2, "parent", "admin"); + checkTables("changeParentProfile", new String[] {"change_date"}, "active_rule_changes"); + } + + +} diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/BackupTest/backup-valid.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/BackupTest/backup-valid.xml index fb33ff6a535..b5df287f5ce 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/BackupTest/backup-valid.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/BackupTest/backup-valid.xml @@ -36,8 +36,10 @@ <profiles> <profile> <name><![CDATA[test name]]></name> + <version><![CDATA[1]]></version> <default-profile><![CDATA[true]]></default-profile> <provided><![CDATA[true]]></provided> + <used><![CDATA[false]]></used> <language><![CDATA[test language]]></language> <enabled><![CDATA[true]]></enabled> <active-rules> @@ -64,10 +66,12 @@ </profile> <profile> <name><![CDATA[test2 name]]></name> + <version><![CDATA[1]]></version> <default-profile><![CDATA[false]]></default-profile> <provided><![CDATA[false]]></provided> <language><![CDATA[test language]]></language> <enabled><![CDATA[true]]></enabled> + <used><![CDATA[false]]></used> <parentName><![CDATA[test name]]></parentName> <active-rules> <active-rule> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldActivateInChildren-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldActivateInChildren-result.xml index c6e3fb56922..f34a0b494fd 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldActivateInChildren-result.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldActivateInChildren-result.xml @@ -5,9 +5,9 @@ <rules_parameters id="1" rule_id="1" name="param1" description="[null]" param_type="r"/> - <rules_profiles id="1" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="2" used_profile="false" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + <rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="30"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldActivateInChildren.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldActivateInChildren.xml index 130072bb538..62081abc403 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldActivateInChildren.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldActivateInChildren.xml @@ -5,9 +5,9 @@ <rules_parameters id="1" rule_id="1" name="param1" description="[null]" param_type="r"/> - <rules_profiles id="1" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="30"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldChangeParent-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldChangeParent-result.xml index 524f5db30ea..84ca4c97e9d 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldChangeParent-result.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldChangeParent-result.xml @@ -6,11 +6,11 @@ <rules id="2" name="bar" description="test" plugin_config_key="checker/bar" plugin_rule_key="checkstyle.rule2" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="new_parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="new_parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="3" provided="false" name="child" default_profile="0" language="java" parent_name="new_parent" enabled="true"/> + <rules_profiles id="3" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="new_parent" enabled="true"/> <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldChangeParent.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldChangeParent.xml index a5d444cf42e..b2daef7a8eb 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldChangeParent.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldChangeParent.xml @@ -6,11 +6,11 @@ <rules id="2" name="bar" description="test" plugin_config_key="checker/bar" plugin_rule_key="checkstyle.rule2" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="new_parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="new_parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="3" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + <rules_profiles id="3" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldCheckCycles.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldCheckCycles.xml index 38df95e0995..5200875be21 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldCheckCycles.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldCheckCycles.xml @@ -3,10 +3,10 @@ <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="level1" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="level1" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="level2" default_profile="0" language="java" parent_name="level1" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="level2" default_profile="0" language="java" parent_name="level1" enabled="true"/> - <rules_profiles id="3" provided="false" name="level3" default_profile="0" language="java" parent_name="level2" enabled="true"/> + <rules_profiles id="3" version="1" used_profile="true" provided="false" name="level3" default_profile="0" language="java" parent_name="level2" enabled="true"/> </dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldDeactivateInChildren-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldDeactivateInChildren-result.xml index 18e99729416..3371d019f58 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldDeactivateInChildren-result.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldDeactivateInChildren-result.xml @@ -3,9 +3,9 @@ <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="2" used_profile="false" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + <rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldDeactivateInChildren.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldDeactivateInChildren.xml index b8489c1fbd2..8d4e2c9072c 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldDeactivateInChildren.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldDeactivateInChildren.xml @@ -3,9 +3,9 @@ <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldNotDeleteInheritedProfile-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldNotDeleteInheritedProfile-result.xml index 38df95e0995..5200875be21 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldNotDeleteInheritedProfile-result.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldNotDeleteInheritedProfile-result.xml @@ -3,10 +3,10 @@ <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="level1" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="level1" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="level2" default_profile="0" language="java" parent_name="level1" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="level2" default_profile="0" language="java" parent_name="level1" enabled="true"/> - <rules_profiles id="3" provided="false" name="level3" default_profile="0" language="java" parent_name="level2" enabled="true"/> + <rules_profiles id="3" version="1" used_profile="true" provided="false" name="level3" default_profile="0" language="java" parent_name="level2" enabled="true"/> </dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRemoveParent-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRemoveParent-result.xml index 540b18c3ace..a27f357b556 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRemoveParent-result.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRemoveParent-result.xml @@ -3,9 +3,9 @@ <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="child" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="[null]" enabled="true"/> <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRemoveParent.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRemoveParent.xml index b8489c1fbd2..8d4e2c9072c 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRemoveParent.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRemoveParent.xml @@ -3,9 +3,9 @@ <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRenameInheritedProfile-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRenameInheritedProfile-result.xml index a7374525f59..c7a2355a55a 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRenameInheritedProfile-result.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldRenameInheritedProfile-result.xml @@ -3,10 +3,10 @@ <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="newName" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="newName" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="level2" default_profile="0" language="java" parent_name="newName" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="level2" default_profile="0" language="java" parent_name="newName" enabled="true"/> - <rules_profiles id="3" provided="false" name="level3" default_profile="0" language="java" parent_name="level2" enabled="true"/> + <rules_profiles id="3" version="1" used_profile="true" provided="false" name="level3" default_profile="0" language="java" parent_name="level2" enabled="true"/> </dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldSetParent-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldSetParent-result.xml index b8489c1fbd2..5d9be47123b 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldSetParent-result.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldSetParent-result.xml @@ -3,9 +3,9 @@ <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + <rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldSetParent.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldSetParent.xml index 540b18c3ace..253e69aac65 100644 --- a/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldSetParent.xml +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/InheritedProfilesTest/shouldSetParent.xml @@ -3,9 +3,9 @@ <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> - <rules_profiles id="1" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> - <rules_profiles id="2" provided="false" name="child" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="[null]" enabled="true"/> <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/changeParentProfile-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/changeParentProfile-result.xml new file mode 100644 index 00000000000..62e8b337fec --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/changeParentProfile-result.xml @@ -0,0 +1,5 @@ +<dataset> + + <active_rule_changes id="1" user_login="admin" profile_id="2" profile_version="2" rule_id="1" enabled="true" old_severity="[null]" new_severity="2"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/changeParentProfile.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/changeParentProfile.xml new file mode 100644 index 00000000000..7c4d381feea --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/changeParentProfile.xml @@ -0,0 +1,22 @@ +<dataset> + + <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" + plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> + + <rules id="2" name="bar" description="test2" plugin_config_key="checker/bar" + plugin_rule_key="checkstyle.rule2" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> + <rules_parameters id="13" rule_id="2" name="param1" description="[null]" param_type="r"/> + + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + + <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> + + <active_rules id="3" profile_id="1" rule_id="2" failure_level="2" inheritance="[null]"/> + <active_rule_parameters id="1" active_rule_id="3" rules_parameter_id="13" value="30"/> + + <active_rules id="4" profile_id="2" rule_id="2" failure_level="2" inheritance="[null]"/> + <active_rule_parameters id="2" active_rule_id="4" rules_parameter_id="13" value="60"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/initialData.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/initialData.xml new file mode 100644 index 00000000000..aa0cb98276e --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/initialData.xml @@ -0,0 +1,21 @@ +<dataset> + + <rules id="1" name="foo" description="test" plugin_config_key="checker/foo" + plugin_rule_key="checkstyle.rule1" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> + + <rules id="2" name="bar" description="test2" plugin_config_key="checker/bar" + plugin_rule_key="checkstyle.rule2" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> + <rules_parameters id="13" rule_id="2" name="param1" description="[null]" param_type="r"/> + + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + + <active_rules id="1" profile_id="1" rule_id="1" failure_level="2" inheritance="[null]"/> + + <active_rules id="2" profile_id="2" rule_id="1" failure_level="2" inheritance="INHERITED"/> + + <active_rules id="3" profile_id="2" rule_id="2" failure_level="2" inheritance="[null]"/> + <active_rule_parameters id="1" active_rule_id="3" rules_parameter_id="13" value="30"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleActivated-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleActivated-result.xml new file mode 100644 index 00000000000..9af4ad48837 --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleActivated-result.xml @@ -0,0 +1,5 @@ +<dataset> + + <active_rule_changes id="1" user_login="admin" profile_id="2" profile_version="2" rule_id="2" enabled="true" old_severity="[null]" new_severity="2"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleDeactivated-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleDeactivated-result.xml new file mode 100644 index 00000000000..179a8ffd239 --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleDeactivated-result.xml @@ -0,0 +1,7 @@ +<dataset> + + <active_rule_changes id="1" user_login="admin" profile_id="2" profile_version="2" rule_id="2" enabled="false" old_severity="2" new_severity="[null]"/> + + <active_rule_param_changes id="1" active_rule_change_id="1" rules_parameter_id="13" old_value="30" new_value="[null]"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleParamChanged-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleParamChanged-result.xml new file mode 100644 index 00000000000..6704d22dea1 --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleParamChanged-result.xml @@ -0,0 +1,7 @@ +<dataset> + + <active_rule_changes id="1" user_login="admin" profile_id="2" profile_version="2" rule_id="2" enabled="[null]" old_severity="[null]" new_severity="[null]"/> + + <active_rule_param_changes id="1" active_rule_change_id="1" rules_parameter_id="13" old_value="20" new_value="30"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleReverted-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleReverted-result.xml new file mode 100644 index 00000000000..14b1c9d3c8b --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleReverted-result.xml @@ -0,0 +1,8 @@ +<dataset> + + <active_rule_changes id="1" user_login="admin" profile_id="2" profile_version="2" rule_id="2" enabled="[null]" old_severity="3" new_severity="2"/> + + <active_rule_param_changes id="1" active_rule_change_id="1" rules_parameter_id="13" old_value="30" new_value="[null]"/> + <active_rule_param_changes id="2" active_rule_change_id="1" rules_parameter_id="14" old_value="100" new_value="50"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleReverted.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleReverted.xml new file mode 100644 index 00000000000..2ec87b2cd7b --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleReverted.xml @@ -0,0 +1,19 @@ +<dataset> + + <rules id="2" name="bar" description="test2" plugin_config_key="checker/bar" + plugin_rule_key="checkstyle.rule2" plugin_name="plugin" enabled="true" cardinality="SINGLE" parent_id="[null]"/> + <rules_parameters id="13" rule_id="2" name="param1" description="[null]" param_type="r"/> + <rules_parameters id="14" rule_id="2" name="param2" description="[null]" param_type="r"/> + + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + + <active_rules id="2" profile_id="1" rule_id="2" failure_level="2" inheritance="[null]"/> + <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="14" value="50"/> + + <active_rules id="3" profile_id="2" rule_id="2" failure_level="3" inheritance="OVERRIDES"/> + <active_rule_parameters id="1" active_rule_id="3" rules_parameter_id="13" value="30"/> + <active_rule_parameters id="2" active_rule_id="3" rules_parameter_id="14" value="100"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleSeverityChanged-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleSeverityChanged-result.xml new file mode 100644 index 00000000000..cd395478a45 --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/ruleSeverityChanged-result.xml @@ -0,0 +1,5 @@ +<dataset> + + <active_rule_changes id="1" user_login="admin" profile_id="2" profile_version="2" rule_id="2" enabled="[null]" old_severity="4" new_severity="3"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/versionIncreaseIfUsed-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/versionIncreaseIfUsed-result.xml new file mode 100644 index 00000000000..b5be9280b9a --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/versionIncreaseIfUsed-result.xml @@ -0,0 +1,7 @@ +<dataset> + + <rules_profiles id="1" version="1" used_profile="true" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + + <rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/versionIncreaseIfUsedAndInChildren-result.xml b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/versionIncreaseIfUsedAndInChildren-result.xml new file mode 100644 index 00000000000..8c3d85e7418 --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/configuration/RuleChangeTest/versionIncreaseIfUsedAndInChildren-result.xml @@ -0,0 +1,7 @@ +<dataset> + + <rules_profiles id="1" version="2" used_profile="false" provided="false" name="parent" default_profile="0" language="java" parent_name="[null]" enabled="true"/> + + <rules_profiles id="2" version="2" used_profile="false" provided="false" name="child" default_profile="0" language="java" parent_name="parent" enabled="true"/> + +</dataset> diff --git a/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldDisableProfilesWithMissingLanguages-result.xml b/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldDisableProfilesWithMissingLanguages-result.xml index 62dce741d80..23de3e4d491 100644 --- a/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldDisableProfilesWithMissingLanguages-result.xml +++ b/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldDisableProfilesWithMissingLanguages-result.xml @@ -1,9 +1,9 @@ <dataset> - <rules_profiles id="1" provided="true" name="Java 1" default_profile="0" language="java" enabled="true" PARENT_NAME="[null]"/> - <rules_profiles id="2" provided="false" name="Java 2" default_profile="1" language="java" enabled="true" PARENT_NAME="[null]"/> - <rules_profiles id="3" provided="true" name="Php" default_profile="0" language="php" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="1" version="1" used_profile="true" provided="true" name="Java 1" default_profile="0" language="java" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="Java 2" default_profile="1" language="java" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="3" version="1" used_profile="true" provided="true" name="Php" default_profile="0" language="php" enabled="true" PARENT_NAME="[null]"/> <!-- disabled --> - <rules_profiles id="4" provided="true" name="Cobol 1" default_profile="1" language="cobol" enabled="false" PARENT_NAME="[null]"/> - <rules_profiles id="5" provided="false" name="Cobol 2" default_profile="0" language="cobol" enabled="false" PARENT_NAME="[null]"/> + <rules_profiles id="4" version="1" used_profile="true" provided="true" name="Cobol 1" default_profile="1" language="cobol" enabled="false" PARENT_NAME="[null]"/> + <rules_profiles id="5" version="1" used_profile="true" provided="false" name="Cobol 2" default_profile="0" language="cobol" enabled="false" PARENT_NAME="[null]"/> </dataset>
\ No newline at end of file diff --git a/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldDisableProfilesWithMissingLanguages.xml b/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldDisableProfilesWithMissingLanguages.xml index f2c684b5735..082f8785417 100644 --- a/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldDisableProfilesWithMissingLanguages.xml +++ b/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldDisableProfilesWithMissingLanguages.xml @@ -1,7 +1,7 @@ <dataset> - <rules_profiles id="1" provided="true" name="Java 1" default_profile="0" language="java" enabled="true" PARENT_NAME="[null]"/> - <rules_profiles id="2" provided="false" name="Java 2" default_profile="1" language="java" enabled="true" PARENT_NAME="[null]"/> - <rules_profiles id="3" provided="true" name="Php" default_profile="0" language="php" enabled="true" PARENT_NAME="[null]"/> - <rules_profiles id="4" provided="true" name="Cobol 1" default_profile="1" language="cobol" enabled="true" PARENT_NAME="[null]"/> - <rules_profiles id="5" provided="false" name="Cobol 2" default_profile="0" language="cobol" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="1" version="1" used_profile="true" provided="true" name="Java 1" default_profile="0" language="java" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="Java 2" default_profile="1" language="java" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="3" version="1" used_profile="true" provided="true" name="Php" default_profile="0" language="php" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="4" version="1" used_profile="true" provided="true" name="Cobol 1" default_profile="1" language="cobol" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="5" version="1" used_profile="true" provided="false" name="Cobol 2" default_profile="0" language="cobol" enabled="true" PARENT_NAME="[null]"/> </dataset>
\ No newline at end of file diff --git a/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldEnableProfilesWithKnownLanguages-result.xml b/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldEnableProfilesWithKnownLanguages-result.xml index d89acc7ae0b..505d4bc123f 100644 --- a/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldEnableProfilesWithKnownLanguages-result.xml +++ b/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldEnableProfilesWithKnownLanguages-result.xml @@ -1,11 +1,11 @@ <dataset> - <rules_profiles id="1" provided="true" name="Java 1" default_profile="0" language="java" enabled="true" PARENT_NAME="[null]"/> - <rules_profiles id="2" provided="false" name="Java 2" default_profile="1" language="java" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="1" version="1" used_profile="true" provided="true" name="Java 1" default_profile="0" language="java" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="Java 2" default_profile="1" language="java" enabled="true" PARENT_NAME="[null]"/> <!-- enabled --> - <rules_profiles id="3" provided="true" name="Disabled Php 1" default_profile="0" language="php" enabled="true" PARENT_NAME="[null]"/> - <rules_profiles id="4" provided="false" name="Disabled Php 2" default_profile="1" language="php" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="3" version="1" used_profile="true" provided="true" name="Disabled Php 1" default_profile="0" language="php" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="4" version="1" used_profile="true" provided="false" name="Disabled Php 2" default_profile="1" language="php" enabled="true" PARENT_NAME="[null]"/> <!-- keep disabled --> - <rules_profiles id="5" provided="true" name="Disabled Cobol" default_profile="1" language="cobol" enabled="false" PARENT_NAME="[null]"/> + <rules_profiles id="5" version="1" used_profile="true" provided="true" name="Disabled Cobol" default_profile="1" language="cobol" enabled="false" PARENT_NAME="[null]"/> </dataset>
\ No newline at end of file diff --git a/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldEnableProfilesWithKnownLanguages.xml b/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldEnableProfilesWithKnownLanguages.xml index c32281a33db..7d26e5127f0 100644 --- a/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldEnableProfilesWithKnownLanguages.xml +++ b/sonar-server/src/test/resources/org/sonar/server/startup/EnableProfilesTest/shouldEnableProfilesWithKnownLanguages.xml @@ -1,7 +1,7 @@ <dataset> - <rules_profiles id="1" provided="true" name="Java 1" default_profile="0" language="java" enabled="true" PARENT_NAME="[null]"/> - <rules_profiles id="2" provided="false" name="Java 2" default_profile="1" language="java" enabled="true" PARENT_NAME="[null]"/> - <rules_profiles id="3" provided="true" name="Disabled Php 1" default_profile="0" language="php" enabled="false" PARENT_NAME="[null]"/> - <rules_profiles id="4" provided="false" name="Disabled Php 2" default_profile="1" language="php" enabled="false" PARENT_NAME="[null]"/> - <rules_profiles id="5" provided="true" name="Disabled Cobol" default_profile="1" language="cobol" enabled="false" PARENT_NAME="[null]"/> + <rules_profiles id="1" version="1" used_profile="true" provided="true" name="Java 1" default_profile="0" language="java" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="2" version="1" used_profile="true" provided="false" name="Java 2" default_profile="1" language="java" enabled="true" PARENT_NAME="[null]"/> + <rules_profiles id="3" version="1" used_profile="true" provided="true" name="Disabled Php 1" default_profile="0" language="php" enabled="false" PARENT_NAME="[null]"/> + <rules_profiles id="4" version="1" used_profile="true" provided="false" name="Disabled Php 2" default_profile="1" language="php" enabled="false" PARENT_NAME="[null]"/> + <rules_profiles id="5" version="1" used_profile="true" provided="true" name="Disabled Cobol" default_profile="1" language="cobol" enabled="false" PARENT_NAME="[null]"/> </dataset>
\ No newline at end of file diff --git a/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/cleanAlerts-result.xml b/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/cleanAlerts-result.xml index 1bf29a3a0d2..a17525b594e 100644 --- a/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/cleanAlerts-result.xml +++ b/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/cleanAlerts-result.xml @@ -6,8 +6,8 @@ <metrics id="2" name="disabledkey2" val_type="INT" description="description" domain="domain" short_name="name2" qualitative="false" user_managed="false" enabled="false" origin="JAV" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="1" hidden="false"/> - <rules_profiles id="1" name="profile1" default_profile="true" provided="true" language="JAV" enabled="true"/> - <rules_profiles id="2" name="profile2" default_profile="false" provided="false" language="JAV" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" name="profile1" default_profile="true" provided="true" language="JAV" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" name="profile2" default_profile="false" provided="false" language="JAV" enabled="true"/> <!-- ok --> <alerts id="1" profile_id="1" metric_id="1" operator=">" value_error="30" value_warning="[null]"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/cleanAlerts.xml b/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/cleanAlerts.xml index 67ea704c420..9dc524b15d3 100644 --- a/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/cleanAlerts.xml +++ b/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/cleanAlerts.xml @@ -7,8 +7,8 @@ short_name="name2" qualitative="false" user_managed="false" enabled="false" origin="JAV" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="1" hidden="false"/> - <rules_profiles id="1" name="profile1" default_profile="true" provided="true" language="JAV" enabled="true"/> - <rules_profiles id="2" name="profile2" default_profile="false" provided="false" language="JAV" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" name="profile1" default_profile="true" provided="true" language="JAV" enabled="true"/> + <rules_profiles id="2" version="1" used_profile="true" name="profile2" default_profile="false" provided="false" language="JAV" enabled="true"/> <!-- ok --> <alerts id="1" profile_id="1" metric_id="1" operator=">" value_error="30" value_warning="[null]"/> diff --git a/sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRuleParameters.xml b/sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRuleParameters.xml index df722428cb4..e85839686b3 100644 --- a/sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRuleParameters.xml +++ b/sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRuleParameters.xml @@ -12,7 +12,7 @@ <rules_parameters id="3" rule_id="1" name="param3" description="[null]" param_type="[null]"/> - <rules_profiles id="1" name="profile name" language="java" default_profile="false" provided="false" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" name="profile name" language="java" default_profile="false" provided="false" enabled="true"/> <active_rules id="1" rule_id="1" profile_id="1" failure_level="4" /> <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="one" /> <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" value="two" /> diff --git a/sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRules.xml b/sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRules.xml index ae76f8c4ba6..0b3b68a9880 100644 --- a/sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRules.xml +++ b/sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRules.xml @@ -8,7 +8,7 @@ <rules_parameters id="1" rule_id="1" name="deprecated-prop" description="[null]" param_type="[null]"/> - <rules_profiles id="1" name="sonar way" language="java" default_profile="false" provided="true" enabled="true"/> + <rules_profiles id="1" version="1" used_profile="true" name="sonar way" language="java" default_profile="false" provided="true" enabled="true"/> <active_rules id="1" rule_id="1" profile_id="1" failure_level="4" /> <active_rules id="2" rule_id="2" profile_id="1" failure_level="0" /> diff --git a/sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl b/sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl index 2391427880f..e8d80293808 100644 --- a/sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl +++ b/sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl @@ -25,6 +25,20 @@ create table ACTIVE_RULES ( primary key (id) ); +create table ACTIVE_RULE_CHANGES ( + ID INTEGER not null, + USER_LOGIN VARCHAR(40) not null, + PROFILE_ID INTEGER not null, + PROFILE_VERSION INTEGER not null, + RULE_ID INTEGER not null, + CHANGE_DATE TIMESTAMP not null, + ENABLED SMALLINT, + OLD_SEVERITY INTEGER, + NEW_SEVERITY INTEGER, + primary key (id) +); +CREATE INDEX ACTIVE_RULE_CHANGES_PID ON ACTIVE_RULE_CHANGES (PROFILE_ID); + create table ACTIVE_RULE_PARAMETERS ( ID INTEGER not null, ACTIVE_RULE_ID INTEGER not null, @@ -33,6 +47,16 @@ create table ACTIVE_RULE_PARAMETERS ( primary key (id) ); +create table ACTIVE_RULE_PARAM_CHANGES ( + ID INTEGER not null, + ACTIVE_RULE_CHANGE_ID INTEGER not null, + RULES_PARAMETER_ID INTEGER not null, + OLD_VALUE VARCHAR(4000), + NEW_VALUE VARCHAR(4000), + primary key (id) +); +CREATE INDEX ACTIVE_RULE_PARAM_CHANGES_CID ON ACTIVE_RULE_PARAM_CHANGES (ACTIVE_RULE_CHANGE_ID); + create table ALERTS ( ID INTEGER not null, PROFILE_ID INTEGER, @@ -362,6 +386,8 @@ create table RULES_PROFILES ( LANGUAGE VARCHAR(16), PARENT_NAME VARCHAR(100), ENABLED SMALLINT, + VERSION INTEGER not null, + USED_PROFILE SMALLINT not null, primary key (id) ); |