extensions.add(DirectoriesDecorator.class);
extensions.add(FilesDecorator.class);
extensions.add(CloseReviewsDecorator.class);
+ extensions.add(ReferenceAnalysis.class);
// time machine
extensions.add(TendencyDecorator.class);
extensions.add(VariationDecorator.class);
+ extensions.add(ViolationTrackingDecorator.class);
extensions.add(ViolationPersisterDecorator.class);
extensions.add(NewViolationsDecorator.class);
extensions.add(TimeMachineConfigurationPersister.class);
--- /dev/null
+/*
+ * 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.timemachine;
+
+import org.sonar.api.BatchExtension;
+import org.sonar.api.database.DatabaseSession;
+import org.sonar.api.database.model.ResourceModel;
+import org.sonar.api.database.model.RuleFailureModel;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.resources.Resource;
+
+import javax.persistence.Query;
+import java.util.Collections;
+import java.util.List;
+
+public class ReferenceAnalysis implements BatchExtension {
+
+ private DatabaseSession session;
+
+ public ReferenceAnalysis(DatabaseSession session) {
+ this.session = session;
+ }
+
+ public List<RuleFailureModel> getViolations(Resource resource) {
+ Snapshot snapshot = getSnapshot(resource);
+ if (snapshot != null) {
+ return session.getResults(RuleFailureModel.class, "snapshotId", snapshot.getId());
+ }
+ return Collections.emptyList();
+ }
+
+ Snapshot getSnapshot(Resource resource) {
+ Query query = session.createQuery("from " + Snapshot.class.getSimpleName() + " s where s.last=true and s.resourceId=(select r.id from "
+ + ResourceModel.class.getSimpleName() + " r where r.key=:key)");
+ query.setParameter("key", resource.getEffectiveKey());
+ return session.getSingleResult(query, null);
+ }
+}
--- /dev/null
+/*
+ * 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.timemachine;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.List;
+
+public final class SourceChecksum {
+
+ private static final String SPACE_CHARS = "\t\n\r ";
+
+ private SourceChecksum() {
+ // only static methods
+ }
+
+ public static List<String> lineChecksumsOfFile(String file) {
+ List<String> result = Lists.newArrayList();
+ if (file != null) {
+ String[] lines = file.split("\r?\n|\r", -1);
+ for (String line : lines) {
+ result.add(lineChecksum(line));
+ }
+ }
+ return result;
+ }
+
+ public static String lineChecksum(String line) {
+ String reducedLine = StringUtils.replaceChars(line, SPACE_CHARS, "");
+ return DigestUtils.md5Hex(reducedLine);
+ }
+
+}
*/
package org.sonar.plugins.core.timemachine;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.lang.ObjectUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.Decorator;
-import org.sonar.api.batch.DecoratorBarriers;
-import org.sonar.api.batch.DecoratorContext;
-import org.sonar.api.batch.DependedUpon;
-import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.batch.*;
+import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.RuleFailureModel;
-import org.sonar.api.database.model.SnapshotSource;
+import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.Violation;
-import org.sonar.batch.components.PastViolationsLoader;
-import org.sonar.batch.index.ViolationPersister;
-
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
+import org.sonar.batch.index.ResourcePersister;
import org.sonar.core.NotDryRun;
+import java.util.List;
+
@NotDryRun
-@DependsUpon({ DecoratorBarriers.END_OF_VIOLATIONS_GENERATION, DecoratorBarriers.START_VIOLATION_TRACKING })
@DependedUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING)
public class ViolationPersisterDecorator implements Decorator {
- /**
- * Those chars would be ignored during generation of checksums.
- */
- private static final String SPACE_CHARS = "\t\n\r ";
-
- private PastViolationsLoader pastViolationsLoader;
- private ViolationPersister violationPersister;
+ private ViolationTrackingDecorator tracker;
+ private ResourcePersister persister;
+ private RuleFinder ruleFinder;
+ private DatabaseSession session;
- List<String> checksums;
-
- public ViolationPersisterDecorator(PastViolationsLoader pastViolationsLoader, ViolationPersister violationPersister) {
- this.pastViolationsLoader = pastViolationsLoader;
- this.violationPersister = violationPersister;
+ public ViolationPersisterDecorator(ViolationTrackingDecorator tracker, ResourcePersister persister, RuleFinder ruleFinder, DatabaseSession session) {
+ this.tracker = tracker;
+ this.persister = persister;
+ this.ruleFinder = ruleFinder;
+ this.session = session;
}
public boolean shouldExecuteOnProject(Project project) {
return true;
}
- public void decorate(Resource resource, DecoratorContext context) {
- if (context.getViolations().isEmpty()) {
- return;
- }
- // Load new violations
- List<Violation> newViolations = context.getViolations();
-
- // Load past violations
- List<RuleFailureModel> pastViolations = pastViolationsLoader.getPastViolations(resource);
-
- // Load current source code and calculate checksums for each line
- checksums = getChecksums(pastViolationsLoader.getSource(resource));
-
- // Map new violations with old ones
- Map<Violation, RuleFailureModel> violationMap = mapViolations(newViolations, pastViolations);
-
- for (Violation newViolation : newViolations) {
- String checksum = getChecksumForLine(checksums, newViolation.getLineId());
- violationPersister.saveViolation(context.getProject(), newViolation, violationMap.get(newViolation), checksum);
- }
- violationPersister.commit();
- // Clear cache
- checksums.clear();
- }
-
- Map<Violation, RuleFailureModel> mapViolations(List<Violation> newViolations, List<RuleFailureModel> pastViolations) {
- Map<Violation, RuleFailureModel> violationMap = new IdentityHashMap<Violation, RuleFailureModel>();
-
- Multimap<Integer, RuleFailureModel> pastViolationsByRule = LinkedHashMultimap.create();
- for (RuleFailureModel pastViolation : pastViolations) {
- pastViolationsByRule.put(pastViolation.getRuleId(), pastViolation);
- }
-
- // Try first to match violations on same rule with same line and with same checkum (but not necessarily with same message)
- for (Violation newViolation : newViolations) {
- mapViolation(newViolation,
- findPastViolationWithSameLineAndChecksum(newViolation, pastViolationsByRule.get(newViolation.getRule().getId())),
- pastViolationsByRule, violationMap);
- }
-
- // If each new violation matches an old one we can stop the matching mechanism
- if (violationMap.size() != newViolations.size()) {
-
- // Try then to match violations on same rule with same message and with same checkum
- for (Violation newViolation : newViolations) {
- if (isNotAlreadyMapped(newViolation, violationMap)) {
- mapViolation(newViolation,
- findPastViolationWithSameChecksumAndMessage(newViolation, pastViolationsByRule.get(newViolation.getRule().getId())),
- pastViolationsByRule, violationMap);
- }
- }
-
- // Try then to match violations on same rule with same line and with same message
- for (Violation newViolation : newViolations) {
- if (isNotAlreadyMapped(newViolation, violationMap)) {
- mapViolation(newViolation,
- findPastViolationWithSameLineAndMessage(newViolation, pastViolationsByRule.get(newViolation.getRule().getId())),
- pastViolationsByRule, violationMap);
- }
- }
- }
-
- return violationMap;
- }
-
- private boolean isNotAlreadyMapped(Violation newViolation, Map<Violation, RuleFailureModel> violationMap) {
- return violationMap.get(newViolation) == null;
- }
-
- private RuleFailureModel findPastViolationWithSameLineAndMessage(Violation newViolation, Collection<RuleFailureModel> pastViolations) {
- for (RuleFailureModel pastViolation : pastViolations) {
- if (isSameLine(newViolation, pastViolation) && isSameMessage(newViolation, pastViolation)) {
- return pastViolation;
- }
- }
- return null;
- }
-
- private RuleFailureModel findPastViolationWithSameChecksumAndMessage(Violation newViolation, Collection<RuleFailureModel> pastViolations) {
- for (RuleFailureModel pastViolation : pastViolations) {
- if (isSameChecksum(newViolation, pastViolation) && isSameMessage(newViolation, pastViolation)) {
- return pastViolation;
- }
- }
- return null;
+ @DependsUpon
+ public Class dependsOnTracker() {
+ return ViolationTrackingDecorator.class;
}
- private RuleFailureModel findPastViolationWithSameLineAndChecksum(Violation newViolation, Collection<RuleFailureModel> pastViolations) {
- for (RuleFailureModel pastViolation : pastViolations) {
- if (isSameLine(newViolation, pastViolation) && isSameChecksum(newViolation, pastViolation)) {
- return pastViolation;
- }
- }
- return null;
- }
-
- private boolean isSameChecksum(Violation newViolation, RuleFailureModel pastViolation) {
- return pastViolation.getChecksum() != null
- && StringUtils.equals(pastViolation.getChecksum(), getChecksumForLine(checksums, newViolation.getLineId()));
+ public void decorate(Resource resource, DecoratorContext context) {
+ saveViolations(context.getProject(), context.getViolations());
}
- private boolean isSameLine(Violation newViolation, RuleFailureModel pastViolation) {
- if (pastViolation.getLine() == null && newViolation.getLineId() == null) {
- return true;
+ void saveViolations(Project project, List<Violation> violations) {
+ for (Violation violation : violations) {
+ RuleFailureModel referenceViolation = tracker.getReferenceViolation(violation);
+ save(project, violation, referenceViolation);
}
- return ObjectUtils.equals(pastViolation.getLine(), newViolation.getLineId());
+ session.commit();
}
- private boolean isSameMessage(Violation newViolation, RuleFailureModel pastViolation) {
- return StringUtils.equals(RuleFailureModel.abbreviateMessage(newViolation.getMessage()), pastViolation.getMessage());
- }
+ public void save(Project project, Violation violation, RuleFailureModel referenceViolation) {
+ Snapshot snapshot = persister.saveResource(project, violation.getResource());
- private void mapViolation(Violation newViolation, RuleFailureModel pastViolation,
- Multimap<Integer, RuleFailureModel> pastViolationsByRule, Map<Violation, RuleFailureModel> violationMap) {
- if (pastViolation != null) {
- pastViolationsByRule.remove(newViolation.getRule().getId(), pastViolation);
- violationMap.put(newViolation, pastViolation);
+ RuleFailureModel model = createModel(violation);
+ if (referenceViolation != null) {
+ model.setPermanentId(referenceViolation.getPermanentId());
}
- }
-
- /**
- * @return checksums, never null
- */
- private List<String> getChecksums(SnapshotSource source) {
- return source == null || source.getData() == null ? Collections.<String> emptyList() : getChecksums(source.getData());
- }
+ model.setSnapshotId(snapshot.getId());
+ session.saveWithoutFlush(model);
- /**
- * @param data
- * can't be null
- */
- static List<String> getChecksums(String data) {
- String[] lines = data.split("\r?\n|\r", -1);
- List<String> result = Lists.newArrayList();
- for (String line : lines) {
- result.add(getChecksum(line));
+ if (model.getPermanentId() == null) {
+ model.setPermanentId(model.getId());
+ session.saveWithoutFlush(model);
}
- return result;
+ violation.setMessage(model.getMessage());// the message can be changed in the class RuleFailure (truncate + trim)
}
- static String getChecksum(String line) {
- String reducedLine = StringUtils.replaceChars(line, SPACE_CHARS, "");
- return DigestUtils.md5Hex(reducedLine);
- }
- /**
- * @return checksum or null if checksum not exists for line
- */
- private String getChecksumForLine(List<String> checksums, Integer line) {
- if (line == null || line < 1 || line > checksums.size()) {
- return null;
- }
- return checksums.get(line - 1);
+ private RuleFailureModel createModel(Violation violation) {
+ RuleFailureModel model = new RuleFailureModel();
+ Rule rule = ruleFinder.findByKey(violation.getRule().getRepositoryKey(), violation.getRule().getKey());
+ model.setRuleId(rule.getId());
+ model.setPriority(violation.getSeverity());
+ model.setLine(violation.getLineId());
+ model.setMessage(violation.getMessage());
+ model.setCost(violation.getCost());
+ model.setChecksum(violation.getChecksum());
+ model.setCreatedAt(violation.getCreatedAt());
+ model.setSwitchedOff(violation.isSwitchedOff());
+ return model;
}
-
- @Override
- public String toString() {
- return getClass().getSimpleName();
- }
-
}
--- /dev/null
+/*
+ * 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.timemachine;
+
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.batch.*;
+import org.sonar.api.database.model.RuleFailureModel;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rules.Violation;
+
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+
+@DependsUpon({DecoratorBarriers.END_OF_VIOLATIONS_GENERATION, DecoratorBarriers.START_VIOLATION_TRACKING})
+@DependedUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING)
+public class ViolationTrackingDecorator implements Decorator {
+ private ReferenceAnalysis referenceAnalysis;
+ private Map<Violation, RuleFailureModel> referenceViolationsMap = Maps.newIdentityHashMap();
+ private SonarIndex index;
+ private Project project;
+
+ public ViolationTrackingDecorator(Project project, ReferenceAnalysis referenceAnalysis, SonarIndex index) {
+ this.referenceAnalysis = referenceAnalysis;
+ this.index = index;
+ this.project = project;
+ }
+
+ public boolean shouldExecuteOnProject(Project project) {
+ return true;
+ }
+
+ public void decorate(Resource resource, DecoratorContext context) {
+ referenceViolationsMap.clear();
+
+ if (!context.getViolations().isEmpty()) {
+ // Load new violations
+ List<Violation> newViolations = prepareNewViolations(context);
+
+ // Load reference violations
+ List<RuleFailureModel> referenceViolations = referenceAnalysis.getViolations(resource);
+
+ // Map new violations with old ones
+ mapViolations(newViolations, referenceViolations);
+ }
+ }
+
+ private List<Violation> prepareNewViolations(DecoratorContext context) {
+ List<Violation> result = Lists.newArrayList();
+ List<String> checksums = SourceChecksum.lineChecksumsOfFile(index.getSource(context.getResource()));
+ for (Violation violation : context.getViolations()) {
+ violation.setChecksum(getChecksumForLine(checksums, violation.getLineId()));
+ result.add(violation);
+ }
+ return result;
+ }
+
+ RuleFailureModel getReferenceViolation(Violation violation) {
+ return referenceViolationsMap.get(violation);
+ }
+
+ Map<Violation, RuleFailureModel> mapViolations(List<Violation> newViolations, List<RuleFailureModel> pastViolations) {
+ Multimap<Integer, RuleFailureModel> pastViolationsByRule = LinkedHashMultimap.create();
+ for (RuleFailureModel pastViolation : pastViolations) {
+ pastViolationsByRule.put(pastViolation.getRuleId(), pastViolation);
+ }
+
+ // Try first to match violations on same rule with same line and with same checkum (but not necessarily with same message)
+ for (Violation newViolation : newViolations) {
+ mapViolation(newViolation,
+ findPastViolationWithSameLineAndChecksum(newViolation, pastViolationsByRule.get(newViolation.getRule().getId())),
+ pastViolationsByRule, referenceViolationsMap);
+ }
+
+ // If each new violation matches an old one we can stop the matching mechanism
+ if (referenceViolationsMap.size() != newViolations.size()) {
+ // Try then to match violations on same rule with same message and with same checkum
+ for (Violation newViolation : newViolations) {
+ if (isNotAlreadyMapped(newViolation, referenceViolationsMap)) {
+ mapViolation(newViolation,
+ findPastViolationWithSameChecksumAndMessage(newViolation, pastViolationsByRule.get(newViolation.getRule().getId())),
+ pastViolationsByRule, referenceViolationsMap);
+ }
+ }
+
+ // Try then to match violations on same rule with same line and with same message
+ for (Violation newViolation : newViolations) {
+ if (isNotAlreadyMapped(newViolation, referenceViolationsMap)) {
+ mapViolation(newViolation,
+ findPastViolationWithSameLineAndMessage(newViolation, pastViolationsByRule.get(newViolation.getRule().getId())),
+ pastViolationsByRule, referenceViolationsMap);
+ }
+ }
+ }
+ return referenceViolationsMap;
+ }
+
+ private boolean isNotAlreadyMapped(Violation newViolation, Map<Violation, RuleFailureModel> violationMap) {
+ return !violationMap.containsKey(newViolation);
+ }
+
+ private RuleFailureModel findPastViolationWithSameLineAndMessage(Violation newViolation, Collection<RuleFailureModel> pastViolations) {
+ for (RuleFailureModel pastViolation : pastViolations) {
+ if (isSameLine(newViolation, pastViolation) && isSameMessage(newViolation, pastViolation)) {
+ return pastViolation;
+ }
+ }
+ return null;
+ }
+
+ private RuleFailureModel findPastViolationWithSameChecksumAndMessage(Violation newViolation, Collection<RuleFailureModel> pastViolations) {
+ for (RuleFailureModel pastViolation : pastViolations) {
+ if (isSameChecksum(newViolation, pastViolation) && isSameMessage(newViolation, pastViolation)) {
+ return pastViolation;
+ }
+ }
+ return null;
+ }
+
+ private RuleFailureModel findPastViolationWithSameLineAndChecksum(Violation newViolation, Collection<RuleFailureModel> pastViolations) {
+ for (RuleFailureModel pastViolation : pastViolations) {
+ if (isSameLine(newViolation, pastViolation) && isSameChecksum(newViolation, pastViolation)) {
+ return pastViolation;
+ }
+ }
+ return null;
+ }
+
+ private boolean isSameChecksum(Violation newViolation, RuleFailureModel pastViolation) {
+ return pastViolation.getChecksum() != null
+ && StringUtils.equals(pastViolation.getChecksum(), newViolation.getChecksum());
+ }
+
+ private boolean isSameLine(Violation newViolation, RuleFailureModel pastViolation) {
+ if (pastViolation.getLine() == null && newViolation.getLineId() == null) {
+ return true;
+ }
+ return ObjectUtils.equals(pastViolation.getLine(), newViolation.getLineId());
+ }
+
+ private boolean isSameMessage(Violation newViolation, RuleFailureModel pastViolation) {
+ return StringUtils.equals(RuleFailureModel.abbreviateMessage(newViolation.getMessage()), pastViolation.getMessage());
+ }
+
+ private void mapViolation(Violation newViolation, RuleFailureModel pastViolation,
+ Multimap<Integer, RuleFailureModel> pastViolationsByRule, Map<Violation, RuleFailureModel> violationMap) {
+ if (pastViolation != null) {
+ newViolation.setCreatedAt(pastViolation.getCreatedAt());
+ newViolation.setSwitchedOff(pastViolation.isSwitchedOff());
+ pastViolationsByRule.remove(newViolation.getRule().getId(), pastViolation);
+ violationMap.put(newViolation, pastViolation);
+ } else {
+ newViolation.setCreatedAt(project.getAnalysisDate());
+ }
+ }
+
+ /**
+ * @return checksum or null if checksum not exists for line
+ */
+ private String getChecksumForLine(List<String> checksums, Integer line) {
+ if (line == null || line < 1 || line > checksums.size()) {
+ return null;
+ }
+ return checksums.get(line - 1);
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName();
+ }
+
+}
--- /dev/null
+/*
+ * 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.timemachine;
+
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertThat;
+
+public class SourceChecksumTest {
+ /**
+ * See http://jira.codehaus.org/browse/SONAR-2358
+ */
+ @Test
+ public void shouldGenerateCorrectChecksums() {
+ List<String> encoding = SourceChecksum.lineChecksumsOfFile("Привет Мир");
+ assertThat(encoding.size(), is(1));
+ assertThat(encoding.get(0), is("5ba3a45e1299ede07f56e5531351be52"));
+ }
+
+ @Test
+ public void shouldSplitLinesAndIgnoreSpaces() {
+ List<String> crlf = SourceChecksum.lineChecksumsOfFile("Hello\r\nWorld");
+ List<String> lf = SourceChecksum.lineChecksumsOfFile("Hello\nWorld");
+ List<String> cr = SourceChecksum.lineChecksumsOfFile("Hello\rWorld");
+ assertThat(crlf.size(), is(2));
+ assertThat(crlf.get(0), not(equalTo(crlf.get(1))));
+ assertThat(lf, equalTo(crlf));
+ assertThat(cr, equalTo(crlf));
+
+ assertThat(SourceChecksum.lineChecksum("\tvoid method() {\n"),
+ equalTo(SourceChecksum.lineChecksum(" void method() {")));
+ }
+}
*/
package org.sonar.plugins.core.timemachine;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.hamcrest.Matchers.nullValue;
-import static org.junit.Assert.assertThat;
-
-import java.util.List;
-import java.util.Map;
-
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.database.model.RuleFailureModel;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.resources.JavaFile;
+import org.sonar.api.resources.Project;
import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RulePriority;
import org.sonar.api.rules.Violation;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.batch.index.ResourcePersister;
+import org.sonar.core.components.DefaultRuleFinder;
+import org.sonar.jpa.test.AbstractDbUnitTestCase;
+
+import java.util.Arrays;
-import com.google.common.collect.Lists;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
-public class ViolationPersisterDecoratorTest {
+public class ViolationPersisterDecoratorTest extends AbstractDbUnitTestCase {
private ViolationPersisterDecorator decorator;
+ private Rule rule1 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck", "Check Header");
+ private Rule rule2 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck", "Equals Avoid Null");
+ private JavaFile javaFile = new JavaFile("org.foo.Bar");
+ Project project = new Project("project");
+ private ViolationTrackingDecorator tracker;
@Before
- public void setUp() {
- decorator = new ViolationPersisterDecorator(null, null);
- }
-
- /**
- * See http://jira.codehaus.org/browse/SONAR-2358
- */
- @Test
- public void shouldGenerateCorrectChecksums() {
- List<String> encoding = ViolationPersisterDecorator.getChecksums("Привет Мир");
- assertThat(encoding.size(), is(1));
- assertThat(encoding.get(0), is("5ba3a45e1299ede07f56e5531351be52"));
- }
-
- @Test
- public void shouldSplitLinesAndIgnoreSpaces() {
- List<String> crlf = ViolationPersisterDecorator.getChecksums("Hello\r\nWorld");
- List<String> lf = ViolationPersisterDecorator.getChecksums("Hello\nWorld");
- List<String> cr = ViolationPersisterDecorator.getChecksums("Hello\rWorld");
- assertThat(crlf.size(), is(2));
- assertThat(crlf.get(0), not(equalTo(crlf.get(1))));
- assertThat(lf, equalTo(crlf));
- assertThat(cr, equalTo(crlf));
-
- assertThat(ViolationPersisterDecorator.getChecksum("\tvoid method() {\n"),
- equalTo(ViolationPersisterDecorator.getChecksum(" void method() {")));
- }
-
- @Test
- public void checksumShouldHaveGreaterPriorityThanLine() {
- RuleFailureModel pastViolation1 = newPastViolation("message", 1, 50, "checksum1");
- RuleFailureModel pastViolation2 = newPastViolation("message", 3, 50, "checksum2");
-
- Violation newViolation1 = newViolation("message", 3, 50, "checksum1");
- Violation newViolation2 = newViolation("message", 5, 50, "checksum2");
-
- Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation1, newViolation2),
- Lists.newArrayList(pastViolation1, pastViolation2));
- assertThat(mapping.get(newViolation1), equalTo(pastViolation1));
- assertThat(mapping.get(newViolation2), equalTo(pastViolation2));
- }
-
- @Test
- public void sameRuleAndLineAndChecksumButDifferentMessages() {
- Violation newViolation = newViolation("new message", 1, 50, "checksum1");
- RuleFailureModel pastViolation = newPastViolation("old message", 1, 50, "checksum1");
-
- Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(pastViolation));
- assertThat(mapping.get(newViolation), equalTo(pastViolation));
+ public void before() {
+ setupData("shared");
+ Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", 1000);
+ ResourcePersister resourcePersister = mock(ResourcePersister.class);
+ when(resourcePersister.saveResource((Project) anyObject(), eq(javaFile))).thenReturn(snapshot);
+ when(resourcePersister.getSnapshot(javaFile)).thenReturn(snapshot);
+ tracker = mock(ViolationTrackingDecorator.class);
+ decorator = new ViolationPersisterDecorator(tracker, resourcePersister, new DefaultRuleFinder(getSessionFactory()), getSession());
}
@Test
- public void sameRuleAndLineMessage() {
- Violation newViolation = newViolation("message", 1, 50, "checksum1");
- RuleFailureModel pastViolation = newPastViolation("message", 1, 50, "checksum2");
-
- Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(pastViolation));
- assertThat(mapping.get(newViolation), equalTo(pastViolation));
+ public void shouldSaveViolations() {
+ Violation violation1a = Violation.create(rule1, javaFile)
+ .setSeverity(RulePriority.CRITICAL).setLineId(20).setCost(55.6).setMessage("the message")
+ .setChecksum("checksum").setCreatedAt(DateUtils.parseDate("2010-12-25"));
+ Violation violation1b = Violation.create(rule1, javaFile)
+ .setSeverity(RulePriority.CRITICAL).setLineId(50).setCost(80.0);
+ Violation violation2 = Violation.create(rule2, javaFile)
+ .setSeverity(RulePriority.MINOR).setSwitchedOff(true);
+
+ decorator.saveViolations(project, Arrays.asList(violation1a, violation1b, violation2));
+
+ checkTables("shouldSaveViolations", "rule_failures");
}
@Test
- public void pastMeasureHasNoChecksum() {
- Violation newViolation = newViolation("message", 1, 50, null);
- RuleFailureModel pastViolation = newPastViolation("message", 1, 51, null);
+ public void shouldCopyPermanentIdFromReferenceViolation() {
+ RuleFailureModel referenceViolation = getSession().getSingleResult(RuleFailureModel.class, "id", 1);
+ Violation violation = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message");
+ when(tracker.getReferenceViolation(violation)).thenReturn(referenceViolation);
- Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(pastViolation));
- assertThat(mapping.get(newViolation), is(nullValue()));
- }
-
- @Test
- public void sameRuleAndMessageAndChecksumButDifferentLine() {
- Violation newViolation = newViolation("message", 1, 50, "checksum1");
- RuleFailureModel pastViolation = newPastViolation("message", 2, 50, "checksum1");
+ decorator.saveViolations(project, Arrays.asList(violation));
- Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(pastViolation));
- assertThat(mapping.get(newViolation), equalTo(pastViolation));
+ checkTables("shouldCopyPermanentIdFromReferenceViolation", "rule_failures");
}
-
- @Test
- public void shouldCreateNewViolationWhenSameRuleSameMessageButDifferentLineAndChecksum() {
- Violation newViolation = newViolation("message", 1, 50, "checksum1");
- RuleFailureModel pastViolation = newPastViolation("message", 2, 50, "checksum2");
-
- Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(pastViolation));
- assertThat(mapping.get(newViolation), is(nullValue()));
- }
-
- @Test
- public void shouldNotTrackViolationIfDifferentRule() {
- Violation newViolation = newViolation("message", 1, 50, "checksum1");
- RuleFailureModel pastViolation = newPastViolation("message", 1, 51, "checksum1");
-
- Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(pastViolation));
- assertThat(mapping.get(newViolation), is(nullValue()));
- }
-
- @Test
- public void shouldCompareViolationsWithDatabaseFormat() {
- // violation messages are trimmed and can be abbreviated when persisted in database.
- // Comparing violation messages must use the same format.
- Violation newViolation = newViolation("message", 1, 50, "checksum1");
- RuleFailureModel pastViolation = newPastViolation(" message ", 1, 50, "checksum2");
-
- Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(pastViolation));
- assertThat(mapping.get(newViolation), equalTo(pastViolation));
- }
-
- private Violation newViolation(String message, int lineId, int ruleId) {
- Rule rule = Rule.create().setKey("rule");
- rule.setId(ruleId);
- return Violation.create(rule, null).setLineId(lineId).setMessage(message);
- }
-
- private Violation newViolation(String message, int lineId, int ruleId, String lineChecksum) {
- Violation violation = newViolation(message, lineId, ruleId);
- if (decorator.checksums == null) {
- decorator.checksums = Lists.newArrayListWithExpectedSize(100);
- }
- for (int i = decorator.checksums.size() - 1; i < lineId; i++) {
- decorator.checksums.add("");
- }
- if (lineChecksum != null) {
- decorator.checksums.set(lineId - 1, ViolationPersisterDecorator.getChecksum(lineChecksum));
- }
- return violation;
- }
-
- private RuleFailureModel newPastViolation(String message, int lineId, int ruleId) {
- RuleFailureModel pastViolation = new RuleFailureModel();
- pastViolation.setId(lineId + ruleId);
- pastViolation.setLine(lineId);
- pastViolation.setMessage(message);
- pastViolation.setRuleId(ruleId);
- return pastViolation;
- }
-
- private RuleFailureModel newPastViolation(String message, int lineId, int ruleId, String lineChecksum) {
- RuleFailureModel pastViolation = newPastViolation(message, lineId, ruleId);
- if (lineChecksum != null) {
- pastViolation.setChecksum(ViolationPersisterDecorator.getChecksum(lineChecksum));
- }
- return pastViolation;
- }
-
}
--- /dev/null
+/*
+ * 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.timemachine;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.database.model.RuleFailureModel;
+import org.sonar.api.resources.Project;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.utils.DateUtils;
+
+import java.text.ParseException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ViolationTrackingDecoratorTest {
+
+ private ViolationTrackingDecorator decorator;
+ private Date analysisDate = DateUtils.parseDate("2010-12-25");
+
+ @Before
+ public void setUp() throws ParseException {
+ Project project = mock(Project.class);
+ when(project.getAnalysisDate()).thenReturn(analysisDate);
+ decorator = new ViolationTrackingDecorator(project, null, null);
+ }
+
+ @Test
+ public void checksumShouldHaveGreaterPriorityThanLine() {
+ RuleFailureModel referenceViolation1 = newReferenceViolation("message", 1, 50, "checksum1");
+ RuleFailureModel referenceViolation2 = newReferenceViolation("message", 3, 50, "checksum2");
+
+ Violation newViolation1 = newViolation("message", 3, 50, "checksum1");
+ Violation newViolation2 = newViolation("message", 5, 50, "checksum2");
+
+ Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation1, newViolation2),
+ Lists.newArrayList(referenceViolation1, referenceViolation2));
+ assertThat(mapping.get(newViolation1), equalTo(referenceViolation1));
+ assertThat(mapping.get(newViolation2), equalTo(referenceViolation2));
+ }
+
+ @Test
+ public void sameRuleAndLineAndChecksumButDifferentMessages() {
+ Violation newViolation = newViolation("new message", 1, 50, "checksum1");
+ RuleFailureModel referenceViolation = newReferenceViolation("old message", 1, 50, "checksum1");
+
+ Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(referenceViolation));
+ assertThat(mapping.get(newViolation), equalTo(referenceViolation));
+ }
+
+ @Test
+ public void sameRuleAndLineMessage() {
+ Violation newViolation = newViolation("message", 1, 50, "checksum1");
+ RuleFailureModel refernceViolation = newReferenceViolation("message", 1, 50, "checksum2");
+
+ Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(refernceViolation));
+ assertThat(mapping.get(newViolation), equalTo(refernceViolation));
+ }
+
+ @Test
+ public void shouldIgnoreReferenceMeasureWithoutChecksum() {
+ Violation newViolation = newViolation("message", 1, 50, null);
+ RuleFailureModel referenceViolation = newReferenceViolation("message", 1, 51, null);
+
+ Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(referenceViolation));
+ assertThat(mapping.get(newViolation), is(nullValue()));
+ }
+
+ @Test
+ public void sameRuleAndMessageAndChecksumButDifferentLine() {
+ Violation newViolation = newViolation("message", 1, 50, "checksum1");
+ RuleFailureModel referenceViolation = newReferenceViolation("message", 2, 50, "checksum1");
+
+ Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(referenceViolation));
+ assertThat(mapping.get(newViolation), equalTo(referenceViolation));
+ }
+
+ @Test
+ public void shouldCreateNewViolationWhenSameRuleSameMessageButDifferentLineAndChecksum() {
+ Violation newViolation = newViolation("message", 1, 50, "checksum1");
+ RuleFailureModel referenceViolation = newReferenceViolation("message", 2, 50, "checksum2");
+
+ Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(referenceViolation));
+ assertThat(mapping.get(newViolation), is(nullValue()));
+ }
+
+ @Test
+ public void shouldNotTrackViolationIfDifferentRule() {
+ Violation newViolation = newViolation("message", 1, 50, "checksum1");
+ RuleFailureModel referenceViolation = newReferenceViolation("message", 1, 51, "checksum1");
+
+ Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(referenceViolation));
+ assertThat(mapping.get(newViolation), is(nullValue()));
+ }
+
+ @Test
+ public void shouldCompareViolationsWithDatabaseFormat() {
+ // violation messages are trimmed and can be abbreviated when persisted in database.
+ // Comparing violation messages must use the same format.
+ Violation newViolation = newViolation("message", 1, 50, "checksum1");
+ RuleFailureModel referenceViolation = newReferenceViolation(" message ", 1, 50, "checksum2");
+
+ Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.newArrayList(referenceViolation));
+ assertThat(mapping.get(newViolation), equalTo(referenceViolation));
+ }
+
+ @Test
+ public void shouldSetDateOfNewViolations() {
+ Violation newViolation = newViolation("message", 1, 50, "checksum");
+ assertThat(newViolation.getCreatedAt(), nullValue());
+
+ Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Collections.<RuleFailureModel>emptyList());
+ assertThat(mapping.size(), is(0));
+ assertThat(newViolation.getCreatedAt(), is(analysisDate));
+ }
+
+ @Test
+ public void shouldCopyViolationDate() {
+ Violation newViolation = newViolation("message", 1, 50, "checksum");
+ RuleFailureModel referenceViolation = newReferenceViolation("", 1, 50, "checksum");
+ Date referenceDate = DateUtils.parseDate("2009-05-18");
+ referenceViolation.setCreatedAt(referenceDate);
+ assertThat(newViolation.getCreatedAt(), nullValue());
+
+ Map<Violation, RuleFailureModel> mapping = decorator.mapViolations(Lists.newArrayList(newViolation), Lists.<RuleFailureModel>newArrayList(referenceViolation));
+ assertThat(mapping.size(), is(1));
+ assertThat(newViolation.getCreatedAt(), is(referenceDate));
+ }
+
+ private Violation newViolation(String message, int lineId, int ruleId) {
+ Rule rule = Rule.create().setKey("rule");
+ rule.setId(ruleId);
+ return Violation.create(rule, null).setLineId(lineId).setMessage(message);
+ }
+
+ private Violation newViolation(String message, int lineId, int ruleId, String lineChecksum) {
+ return newViolation(message, lineId, ruleId).setChecksum(lineChecksum);
+ }
+
+ private RuleFailureModel newReferenceViolation(String message, int lineId, int ruleId, String lineChecksum) {
+ RuleFailureModel referenceViolation = new RuleFailureModel();
+ referenceViolation.setId(lineId + ruleId);
+ referenceViolation.setLine(lineId);
+ referenceViolation.setMessage(message);
+ referenceViolation.setRuleId(ruleId);
+ referenceViolation.setChecksum(lineChecksum);
+ return referenceViolation;
+ }
+
+}
--- /dev/null
+<dataset>
+
+ <rules_categories id="1" name="Efficiency" description="[null]"/>
+ <rules_categories id="6" name="Usability" description="[null]"/>
+
+ <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+ plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+ cardinality="SINGLE" parent_id="[null]"/>
+
+ <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+ plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+ cardinality="SINGLE" parent_id="[null]"/>
+
+ <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+ name="Bar" long_name="org.foo.Bar" description="[null]"
+ enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
+
+ <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+ scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
+ status="U" islast="false" depth="3" />
+
+ <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+ <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules_categories id="1" name="Efficiency" description="[null]"/>
+ <rules_categories id="6" name="Usability" description="[null]"/>
+
+ <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+ plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+ cardinality="SINGLE" parent_id="[null]"/>
+
+ <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+ plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+ cardinality="SINGLE" parent_id="[null]"/>
+
+ <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+ name="Bar" long_name="org.foo.Bar" description="[null]"
+ enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
+
+ <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+ scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
+ status="U" islast="false" depth="3" />
+
+ <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+ <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+
+ <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="[null]" checksum="[null]"/>
+</dataset>
--- /dev/null
+<dataset>
+ <rules_categories id="1" name="Efficiency" description="[null]"/>
+ <rules_categories id="6" name="Usability" description="[null]"/>
+
+ <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+ plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+ cardinality="SINGLE" parent_id="[null]"/>
+
+ <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+ plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+ cardinality="SINGLE" parent_id="[null]"/>
+
+ <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+ name="Bar" long_name="org.foo.Bar" description="[null]"
+ enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
+
+ <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+ scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
+ status="U" islast="false" depth="3" />
+
+ <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+ <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+ <rule_failures switched_off="false" permanent_id="3" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="55.6" created_at="2010-12-25 00:00:00.00" checksum="checksum"/>
+ <rule_failures switched_off="false" permanent_id="4" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="[null]" LINE="50" COST="80" created_at="[null]" checksum="[null]"/>
+ <rule_failures switched_off="true" permanent_id="5" ID="5" SNAPSHOT_ID="1000" RULE_ID="31" FAILURE_LEVEL="1" MESSAGE="[null]" LINE="[null]" COST="[null]" created_at="[null]" checksum="[null]"/>
+</dataset>
\ No newline at end of file
addComponent(MemoryOptimizer.class);
addComponent(DefaultResourcePersister.class);
addComponent(SourcePersister.class);
- addComponent(ViolationPersister.class);
}
addComponent(Plugins.class);
import org.sonar.api.rules.DefaultRulesManager;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.*;
-import org.sonar.batch.components.PastViolationsLoader;
import org.sonar.batch.components.TimeMachineConfiguration;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.index.DefaultIndex;
// the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
addComponent(getComponent(DefaultResourcePersister.class).getSnapshot(project));
addComponent(TimeMachineConfiguration.class);
- addComponent(PastViolationsLoader.class);
}
addComponent(org.sonar.api.database.daos.MeasuresDao.class);
addComponent(ProfilesDao.class);
+++ /dev/null
-/*
- * 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.batch.components;
-
-import org.sonar.api.BatchExtension;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.RuleFailureModel;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.database.model.SnapshotSource;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.utils.SonarException;
-import org.sonar.batch.index.ResourcePersister;
-import org.sonar.core.NotDryRun;
-
-import java.util.Collections;
-import java.util.List;
-
-@NotDryRun
-public class PastViolationsLoader implements BatchExtension {
-
- private DatabaseSession session;
- private ResourcePersister resourcePersister;
-
- public PastViolationsLoader(DatabaseSession session, ResourcePersister resourcePersister) {
- this.session = session;
- this.resourcePersister = resourcePersister;
- }
-
- public List<RuleFailureModel> getPastViolations(Resource resource) {
- if (resource == null) {
- return Collections.emptyList();
- }
-
- Snapshot snapshot = resourcePersister.getSnapshot(resource);
- if (snapshot == null) {
- throw new SonarException("This resource has no snapshot ???" + resource);
- }
- Snapshot previousLastSnapshot = resourcePersister.getLastSnapshot(snapshot, true);
- if (previousLastSnapshot == null) {
- return Collections.emptyList();
- }
- return session.getResults(RuleFailureModel.class,
- "snapshotId", previousLastSnapshot.getId());
- }
-
- public SnapshotSource getSource(Resource resource) {
- Snapshot snapshot = resourcePersister.getSnapshot(resource);
- return session.getSingleResult(SnapshotSource.class,
- "snapshotId", snapshot.getId());
- }
-
-}
}
}
+ public String getSource(Resource resource) {
+ return persistence.getSource(resource);
+ }
+
/**
* Does nothing if the resource is already registered.
*/
sourcePersister.saveSource(file, source);
}
+ public String getSource(Resource resource) {
+ return sourcePersister.getSource(resource);
+ }
+
public void saveMeasure(Resource resource, Measure measure) {
if (ResourceUtils.isPersistable(resource)) {
measurePersister.saveMeasure(resource, measure);
void setSource(Resource file, String source);
+ String getSource(Resource resource);
+
void saveMeasure(Resource resource, Measure measure);
Measure reloadMeasure(Measure measure);
*/
package org.sonar.batch.index;
+import com.google.common.collect.Maps;
import org.sonar.api.batch.Event;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.design.Dependency;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
public final class ReadOnlyPersistenceManager implements PersistenceManager {
+ private Map<Resource, String> sources = Maps.newHashMap();
+
public void clear() {
+ sources.clear();
}
public void setDelayedMode(boolean b) {
}
public void setSource(Resource file, String source) {
+ sources.put(file, source);
+ }
+
+ public String getSource(Resource resource) {
+ return sources.get(resource);
}
public void saveMeasure(Resource resource, Measure measure) {
addToCache(snapshot);
}
+ public String getSource(Resource resource) {
+ SnapshotSource source = null;
+ Snapshot snapshot = resourcePersister.getSnapshot(resource);
+ if (snapshot!=null && snapshot.getId()!=null) {
+ source = session.getSingleResult(SnapshotSource.class, "snapshotId", snapshot.getId());
+ }
+ return source!=null ? source.getData() : null;
+ }
+
private boolean isCached(Snapshot snapshot) {
return savedSnapshotIds.contains(snapshot.getId());
}
+++ /dev/null
-/*
- * 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.batch.index;
-
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.RuleFailureModel;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.resources.Project;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.rules.Violation;
-
-public final class ViolationPersister {
-
- private DatabaseSession session;
- private ResourcePersister resourcePersister;
- private RuleFinder ruleFinder;
-
- public ViolationPersister(DatabaseSession session, ResourcePersister resourcePersister, RuleFinder ruleFinder) {
- this.session = session;
- this.resourcePersister = resourcePersister;
- this.ruleFinder = ruleFinder;
- }
-
- void saveViolation(Project project, Violation violation) {
- saveViolation(project, violation, null, null);
- }
-
- public void saveViolation(Project project, Violation violation, RuleFailureModel pastViolation, String checksum) {
- Snapshot snapshot = resourcePersister.saveResource(project, violation.getResource());
-
- RuleFailureModel model = createModel(violation);
- if (pastViolation!=null) {
- model.setCreatedAt(pastViolation.getCreatedAt());
- model.setPermanentId(pastViolation.getPermanentId());
- model.setSwitchedOff(pastViolation.isSwitchedOff());
- } else {
- // avoid plugins setting date
- model.setCreatedAt(snapshot.getCreatedAt());
- }
- model.setSnapshotId(snapshot.getId());
- model.setChecksum(checksum);
- session.saveWithoutFlush(model);
-
- if (model.getPermanentId()==null) {
- model.setPermanentId(model.getId());
- session.saveWithoutFlush(model);
- }
-
- // the following fields can have been changed
- violation.setMessage(model.getMessage());// the message can be changed in the class RuleFailure (truncate + trim)
- violation.setCreatedAt(model.getCreatedAt());
- violation.setSwitchedOff(model.isSwitchedOff());
- }
-
- public void commit() {
- session.commit();
- }
-
- private RuleFailureModel createModel(Violation violation) {
- RuleFailureModel model = new RuleFailureModel();
- Rule rule = ruleFinder.findByKey(violation.getRule().getRepositoryKey(), violation.getRule().getKey());
- model.setRuleId(rule.getId());
- model.setPriority(violation.getSeverity());
- model.setLine(violation.getLineId());
- model.setMessage(violation.getMessage());
- model.setCost(violation.getCost());
- return model;
- }
-
-}
+++ /dev/null
-/*
- * 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.batch.components;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.database.model.RuleFailureModel;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.resources.JavaFile;
-import org.sonar.api.resources.Resource;
-import org.sonar.batch.index.ResourcePersister;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
-
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
-public class PastViolationsLoaderTest extends AbstractDbUnitTestCase {
-
- private ResourcePersister resourcePersister;
- private PastViolationsLoader loader;
-
- @Before
- public void setUp() {
- setupData("shared");
- resourcePersister = mock(ResourcePersister.class);
- loader = new PastViolationsLoader(getSession(), resourcePersister);
- }
-
- @Test
- public void shouldGetPastResourceViolations() {
- Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", 1000);
- doReturn(snapshot).when(resourcePersister)
- .getSnapshot(any(Resource.class));
- doReturn(snapshot).when(resourcePersister)
- .getLastSnapshot(any(Snapshot.class), anyBoolean());
-
- List<RuleFailureModel> violations = loader.getPastViolations(new JavaFile("file"));
-
- assertThat(violations.size(), is(2));
- }
-
- @Test
- public void shouldReturnEmptyList() {
- List<RuleFailureModel> violations = loader.getPastViolations(null);
-
- assertThat(violations, notNullValue());
- assertThat(violations.size(), is(0));
- }
-
-}
+++ /dev/null
-/*
- * 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.batch.index;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.database.model.RuleFailureModel;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.resources.JavaFile;
-import org.sonar.api.resources.Project;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RulePriority;
-import org.sonar.api.rules.Violation;
-import org.sonar.core.components.DefaultRuleFinder;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
-
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class ViolationPersisterTest extends AbstractDbUnitTestCase {
-
- private ViolationPersister violationPersister;
- private Rule rule1 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck", "Check Header");
- private Rule rule2 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck", "Equals Avoid Null");
- private JavaFile javaFile = new JavaFile("org.foo.Bar");
- Project project = new Project("project");
-
- @Before
- public void before() {
- setupData("shared");
- Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", 1000);
- ResourcePersister resourcePersister = mock(ResourcePersister.class);
- when(resourcePersister.saveResource((Project) anyObject(), eq(javaFile))).thenReturn(snapshot);
- when(resourcePersister.getSnapshot(javaFile)).thenReturn(snapshot);
- violationPersister = new ViolationPersister(getSession(), resourcePersister, new DefaultRuleFinder(getSessionFactory()));
- }
-
- @Test
- public void shouldSaveViolations() {
- Violation violation1a = Violation.create(rule1, javaFile)
- .setSeverity(RulePriority.CRITICAL).setLineId(20).setCost(55.6)
- .setMessage("the message");
- Violation violation1b = Violation.create(rule1, javaFile)
- .setSeverity(RulePriority.CRITICAL).setLineId(50).setCost(80.0);
- Violation violation2 = Violation.create(rule2, javaFile)
- .setSeverity(RulePriority.MINOR);
-
- violationPersister.saveViolation(project, violation1a);
- violationPersister.saveViolation(project, violation1b);
- violationPersister.saveViolation(project, violation2);
-
- checkTables("shouldInsertViolations", "rule_failures");
- }
-
- @Test
- public void shouldCopyPermanentIdFromPastViolation() {
- RuleFailureModel pastViolation = getSession().getSingleResult(RuleFailureModel.class, "id", 1);
-
- Violation violation = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message");
- violationPersister.saveViolation(project, violation, pastViolation, "line_checksum");
-
- checkTables("shouldCopyPermanentIdFromPastViolation", "rule_failures");
- }
-
- @Test
- public void shouldCopySwitchedOffFromPastViolation() {
- RuleFailureModel pastViolation1 = getSession().getSingleResult(RuleFailureModel.class, "id", 1);
- Violation violation1 = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message");
- violationPersister.saveViolation(project, violation1, pastViolation1, "line_checksum");
-
- RuleFailureModel pastViolation2 = getSession().getSingleResult(RuleFailureModel.class, "id", 2);
- Violation violation2 = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message");
- violationPersister.saveViolation(project, violation2, pastViolation2, "line_checksum");
-
- checkTables("shouldCopySwitchedOffFromPastViolation", "rule_failures");
- }
-}
+++ /dev/null
-<dataset>
-
- <rules_categories id="1" name="Efficiency" description="[null]"/>
- <rules_categories id="6" name="Usability" description="[null]"/>
-
- <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
-
- <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
- status="U" islast="false" depth="3" />
-
- <rule_failures switched_off="[null]" permanent_id="[null]" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" />
- <rule_failures switched_off="[null]" permanent_id="[null]" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" />
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules_categories id="1" name="Efficiency" description="[null]"/>
- <rules_categories id="6" name="Usability" description="[null]"/>
-
- <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
-
- <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
- status="U" islast="false" depth="3" />
-
- <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules_categories id="1" name="Efficiency" description="[null]"/>
- <rules_categories id="6" name="Usability" description="[null]"/>
-
- <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
-
- <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
- status="U" islast="false" depth="3" />
-
- <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
-
- <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules_categories id="1" name="Efficiency" description="[null]"/>
- <rules_categories id="6" name="Usability" description="[null]"/>
-
- <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
-
- <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
- status="U" islast="false" depth="3" />
-
- <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
-
- <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>
- <rule_failures switched_off="true" permanent_id="2" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>
-</dataset>
+++ /dev/null
-<dataset>
- <rules_categories id="1" name="Efficiency" description="[null]"/>
- <rules_categories id="6" name="Usability" description="[null]"/>
-
- <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
- cardinality="SINGLE" parent_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
-
- <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
- status="U" islast="false" depth="3" />
-
- <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="false" permanent_id="3" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="55.6" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="false" permanent_id="4" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="[null]" LINE="50" COST="80" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
- <rule_failures switched_off="false" permanent_id="5" ID="5" SNAPSHOT_ID="1000" RULE_ID="31" FAILURE_LEVEL="1" MESSAGE="[null]" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
-</dataset>
\ No newline at end of file
*/
public abstract void setSource(Resource reference, String source) throws DuplicatedSourceException;
+ /**
+ * @since 2.9
+ */
+ public abstract String getSource(Resource resource);
+
public abstract Project getProject();
public final Collection<Resource> getResources() {
* as a parameter.
*
* @since 2.7
- * @param the
- * resource on which violations are searched
* @return the list of violations
*/
public final List<Violation> getViolations(Resource resource) {
/**
* Warning: the resource is automatically indexed for backward-compatibility, but it should be explictly
* indexed before. Next versions will deactivate this automatic indexation.
- *
- * @throws SonarException if the metric is unknown.
*/
public abstract Measure addMeasure(Resource resource, Measure measure);
private Double cost;
private Date createdAt;
private boolean switchedOff=false;
+ private String checksum;
/**
* Creates of a violation from a rule. Will need to define the resource later on
* Tells whether this violation is ON or OFF.
*
* @since 2.8
- * @return true if the violation has been switched off
*/
public boolean isSwitchedOff() {
return switchedOff;
}
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Violation)) {
- return false;
- }
- if (this == obj) {
- return true;
- }
- Violation other = (Violation) obj;
- return new EqualsBuilder().append(rule, other.getRule()).append(resource, other.getResource()).isEquals();
+ /**
+ * Checksum is available in decorators executed after the barrier {@link org.sonar.api.batch.DecoratorBarriers#END_OF_VIOLATION_TRACKING}
+ */
+ public String getChecksum() {
+ return checksum;
}
- @Override
- public int hashCode() {
- return new HashCodeBuilder(17, 37).append(getRule()).append(getResource()).toHashCode();
+ /**
+ * For internal use only. Checksum is automatically set by Sonar. Plugins must not call this method.
+ */
+ public Violation setChecksum(String s) {
+ this.checksum = s;
+ return this;
}
@Override