]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2380 The "violations" web service API must not return
authorFabrice Bellingard <bellingard@gmail.com>
Thu, 21 Apr 2011 14:56:21 +0000 (16:56 +0200)
committerFabrice Bellingard <bellingard@gmail.com>
Thu, 21 Apr 2011 16:40:48 +0000 (18:40 +0200)
"false-positive" violation

Also modified the batch side ViolationQuery class that I created so
that they have the same API.

sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
sonar-plugin-api/src/main/java/org/sonar/api/violations/ViolationQuery.java
sonar-server/src/main/webapp/WEB-INF/app/models/rule_failure.rb
sonar-ws-client/src/main/java/org/sonar/wsclient/services/Violation.java
sonar-ws-client/src/main/java/org/sonar/wsclient/services/ViolationQuery.java
sonar-ws-client/src/main/java/org/sonar/wsclient/unmarshallers/ViolationUnmarshaller.java
sonar-ws-client/src/test/java/org/sonar/wsclient/unmarshallers/ViolationUnmarshallerTest.java
sonar-ws-client/src/test/resources/violations/violation-without-optional-fields.json
sonar-ws-client/src/test/resources/violations/violations.json

index 5b4dd14c5fdf68cb03f1ca5b0e712680a4c5cfde..1accc7b4ea6491f226e8cdd6284b4dc20434fd54 100644 (file)
  */
 package org.sonar.batch.index;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
@@ -30,9 +36,17 @@ import org.sonar.api.batch.Event;
 import org.sonar.api.batch.SonarIndex;
 import org.sonar.api.database.model.ResourceModel;
 import org.sonar.api.design.Dependency;
-import org.sonar.api.measures.*;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MeasuresFilter;
+import org.sonar.api.measures.MeasuresFilters;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.MetricFinder;
 import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.*;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.ProjectLink;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.ResourceUtils;
+import org.sonar.api.resources.Scopes;
 import org.sonar.api.rules.ActiveRule;
 import org.sonar.api.rules.Violation;
 import org.sonar.api.utils.SonarException;
@@ -42,7 +56,9 @@ import org.sonar.batch.ProjectTree;
 import org.sonar.batch.ResourceFilters;
 import org.sonar.batch.ViolationFilters;
 
-import java.util.*;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 
 public class DefaultIndex extends SonarIndex {
 
@@ -297,12 +313,11 @@ public class DefaultIndex extends SonarIndex {
       return Collections.emptyList();
     }
     List<Violation> filteredViolations = Lists.newArrayList();
-    boolean ignoreSwitchedOff = violationQuery.ignoreSwitchedOff();
+    boolean isSwitchedOff = violationQuery.isSwitchedOff();
     for (Violation violation : bucket.getViolations()) {
-      if ( ignoreSwitchedOff && violation.isSwitchedOff()) {
-        continue;
+      if ( violation.isSwitchedOff() == isSwitchedOff) {
+        filteredViolations.add(violation);
       }
-      filteredViolations.add(violation);
     }
     return filteredViolations;
   }
index 48946226df4d7fdc657472b51e32a072180b1ecc..0a5bb5ccc7a6817cc1f47bfa7354a4d1f24ad578 100644 (file)
@@ -227,7 +227,7 @@ public class DefaultIndexTest {
     violation3.setSwitchedOff(true);
     index.addViolation(violation3);
 
-    assertThat(index.getViolations(ViolationQuery.create().forResource(file).ignoreSwitchedOff(false)).size(), is(3));
+    assertThat(index.getViolations(ViolationQuery.create().forResource(file).setSwitchedOff(true)).size(), is(2));
   }
 
   @Test(expected = IllegalArgumentException.class)
index 89133b1c6b8dccf92d0f6c084816b5174f47f84d..4c82198ffdd2d2298fef69728c7af5676aae0dee 100644 (file)
@@ -138,7 +138,7 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe
    * @return the list of violations
    */
   public final List<Violation> getViolations(Resource resource) {
-    return getViolations(ViolationQuery.create().forResource(resource).ignoreSwitchedOff(true));
+    return getViolations(ViolationQuery.create().forResource(resource));
   }
 
   /**
index 10be756b640de592c99deae9fa6d82d9600fa6f7..28b9082693c7c04fbb0a97546d132af160ec1302 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.api.resources.Resource;
  */
 public final class ViolationQuery {
 
-  private boolean ignoreSwitchedOff;
+  private boolean isSwitchedOff;
   private Resource resource;
 
   /**
@@ -50,21 +50,21 @@ public final class ViolationQuery {
    * Specifies if the query should returned switched-off violations or not.
    * 
    * @param ignore
-   *          if true, the query will return only active violations.
+   *          if true, the query will return only switched-off violations. if false, it will return only active violations.
    * @return the current violation query
    */
-  public ViolationQuery ignoreSwitchedOff(boolean ignore) {
-    this.ignoreSwitchedOff = ignore;
+  public ViolationQuery setSwitchedOff(boolean ignore) {
+    this.isSwitchedOff = ignore;
     return this;
   }
 
   /**
-   * Tells if the query should returned switched-off violations or not.
+   * Tells if the query should returned switched-off violations or active violations.
    * 
    * @return
    */
-  public boolean ignoreSwitchedOff() {
-    return ignoreSwitchedOff;
+  public boolean isSwitchedOff() {
+    return isSwitchedOff;
   }
 
   /**
index bb62d4e80f20b112c28e77a624e867d3b9b725c5..cef150fef10114980cbd5c9abf52d1fe73c79d2e 100644 (file)
@@ -38,6 +38,7 @@ class RuleFailure < ActiveRecord::Base
     json['message'] = message
     json['line'] = line if line
     json['priority'] = Sonar::RulePriority.to_s(failure_level).upcase
+    json['switchedOff'] = switched_off ? true : false
     if created_at
       json['createdAt'] = format_datetime(created_at)
     end
@@ -60,6 +61,7 @@ class RuleFailure < ActiveRecord::Base
       xml.message(message)
       xml.line(line) if line
       xml.priority(Sonar::RulePriority.to_s(failure_level))
+      xml.switchedOff(switched_off ? true : false)
       if created_at
         xml.createdAt(format_datetime(created_at))
       end
index f993b14321fb3bc38f6f283e25fb767e717a24b0..e29c37396ba19ae08c2f5f80f9394ba66b713a8b 100644 (file)
@@ -33,6 +33,7 @@ public class Violation extends Model {
   private String resourceScope = null;
   private String resourceQualifier = null;
   private Date createdAt = null;
+  private boolean switchedOff;
 
   public String getMessage() {
     return message;
@@ -152,6 +153,22 @@ public class Violation extends Model {
    * @since 2.5
    */
   public boolean isCreatedAfter(Date date) {
-    return createdAt!=null && date!=null && createdAt.after(date);
+    return createdAt != null && date != null && createdAt.after(date);
   }
+
+  /**
+   * @since 2.8
+   */
+  public Violation setSwitchedOff(boolean switchedOff) {
+    this.switchedOff = switchedOff;
+    return this;
+  }
+
+  /**
+   * @since 2.8
+   */
+  public boolean isSwitchedOff() {
+    return switchedOff;
+  }
+
 }
index 0fc6d244d572bb705a4fd6ca1a614d05f3da8d82..06a75f94c9e288a41769c6c13a814f6056cf5de7 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.wsclient.services;
 
 public class ViolationQuery extends Query<Violation> {
+
   public static final String BASE_URL = "/api/violations";
 
   private String resourceKeyOrId;
@@ -30,6 +31,7 @@ public class ViolationQuery extends Query<Violation> {
   private String[] categories;
   private String[] severities;
   private Integer limit;
+  private boolean isSwitchedOff;
 
   public ViolationQuery(String resourceKeyOrId) {
     this.resourceKeyOrId = resourceKeyOrId;
@@ -127,6 +129,21 @@ public class ViolationQuery extends Query<Violation> {
     return this;
   }
 
+  /**
+   * @since 2.8
+   */
+  public ViolationQuery setSwitchedOff(boolean ignore) {
+    this.isSwitchedOff = ignore;
+    return this;
+  }
+
+  /**
+   * @since 2.8
+   */
+  public boolean isSwitchedOff() {
+    return isSwitchedOff;
+  }
+
   @Override
   public String getUrl() {
     StringBuilder url = new StringBuilder(BASE_URL);
@@ -141,6 +158,8 @@ public class ViolationQuery extends Query<Violation> {
     appendUrlParameter(url, "rules", ruleKeys);
     appendUrlParameter(url, "categories", categories);
     appendUrlParameter(url, "priorities", severities);
+    appendUrlParameter(url, "switched_off", isSwitchedOff);
+
     return url.toString();
   }
 
index 0df77ae74fcf5ea2fea40b04b25175807efba3ec..df62e5c0e16dbda439ea3e6483a0a2d2c78d4a80 100644 (file)
@@ -33,6 +33,7 @@ public class ViolationUnmarshaller extends AbstractUnmarshaller<Violation> {
     violation.setLine(utils.getInteger(json, "line"));
     violation.setSeverity(utils.getString(json, "priority"));
     violation.setCreatedAt(utils.getDateTime(json, "createdAt"));
+    violation.setSwitchedOff(utils.getBoolean(json, "switchedOff"));
 
     Object rule = utils.getField(json, "rule");
     if (rule != null) {
index 614ed46b79f0438af0c9df890e699cd1427e969a..3f3da0e81fc88b540664a57c3a41d3996e3af432 100644 (file)
  */
 package org.sonar.wsclient.unmarshallers;
 
-import org.junit.Test;
-import org.sonar.wsclient.services.Violation;
-
-import java.util.List;
-
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.core.IsNot.not;
 import static org.junit.Assert.assertThat;
 
+import java.util.List;
+
+import org.junit.Test;
+import org.sonar.wsclient.services.Violation;
+
 public class ViolationUnmarshallerTest extends UnmarshallerTestCase {
 
   @Test
@@ -52,6 +52,7 @@ public class ViolationUnmarshallerTest extends UnmarshallerTestCase {
     assertThat(violation.getResourceName(), is("TraceableResourceLimitingPool"));
     assertThat(violation.getResourceQualifier(), is("CLA"));
     assertThat(violation.getResourceScope(), is("FIL"));
+    assertThat(violation.isSwitchedOff(), is(true));
   }
 
   @Test
index acfffe3e152ad09845592ca10b11105db540918f..7c8aa24b70ad601c0b10121e835a7cd25619b136 100644 (file)
@@ -1,3 +1,3 @@
 [
-  {"message":"throw java.lang.Exception","priority":"MAJOR","rule":{"key":"pmd:SignatureDeclareThrowsException","name":"Signature Declare Throws Exception","category":"Maintainability"},"resource":{"key":"org.apache.excalibur.components:excalibur-pool-instrumented:org.apache.avalon.excalibur.pool.TraceableResourceLimitingPool","name":"TraceableResourceLimitingPool","scope":"FIL","qualifier":"CLA","language":"java"}},
+  {"message":"throw java.lang.Exception","priority":"MAJOR","switchedOff":true,"rule":{"key":"pmd:SignatureDeclareThrowsException","name":"Signature Declare Throws Exception","category":"Maintainability"},"resource":{"key":"org.apache.excalibur.components:excalibur-pool-instrumented:org.apache.avalon.excalibur.pool.TraceableResourceLimitingPool","name":"TraceableResourceLimitingPool","scope":"FIL","qualifier":"CLA","language":"java"}},
 ]
\ No newline at end of file
index 92c98b332f088fb2328ff226516ff393c4bf252f..1dbad54bb6ec9846db22eb0a9c2d0ee88d0c18a3 100644 (file)
@@ -1,4 +1,4 @@
 [
-  {"message":"throw java.lang.Exception","line":97,"createdAt":"2010-12-01T13:55:22+0300","priority":"MAJOR","rule":{"key":"pmd:SignatureDeclareThrowsException","name":"Signature Declare Throws Exception","category":"Maintainability"},"resource":{"key":"org.apache.excalibur.components:excalibur-pool-instrumented:org.apache.avalon.excalibur.pool.TraceableResourceLimitingPool","name":"TraceableResourceLimitingPool","scope":"FIL","qualifier":"CLA","language":"java"}},
-  {"message":"The user-supplied array 'threads' is stored directly.","line":242,"createdAt":"2010-12-01T13:55:22+0300","priority":"MAJOR","rule":{"key":"pmd:ArrayIsStoredDirectly","name":"Security - Array is stored directly","category":"Reliability"},"resource":{"key":"org.apache.excalibur.components:excalibur-pool-instrumented:org.apache.avalon.excalibur.pool.TraceableResourceLimitingPool","name":"TraceableResourceLimitingPool","scope":"FIL","qualifier":"CLA","language":"java"}}
+  {"message":"throw java.lang.Exception","line":97,"createdAt":"2010-12-01T13:55:22+0300","priority":"MAJOR","switchedOff":true,"rule":{"key":"pmd:SignatureDeclareThrowsException","name":"Signature Declare Throws Exception","category":"Maintainability"},"resource":{"key":"org.apache.excalibur.components:excalibur-pool-instrumented:org.apache.avalon.excalibur.pool.TraceableResourceLimitingPool","name":"TraceableResourceLimitingPool","scope":"FIL","qualifier":"CLA","language":"java"}},
+  {"message":"The user-supplied array 'threads' is stored directly.","line":242,"createdAt":"2010-12-01T13:55:22+0300","priority":"MAJOR","switchedOff":false,"rule":{"key":"pmd:ArrayIsStoredDirectly","name":"Security - Array is stored directly","category":"Reliability"},"resource":{"key":"org.apache.excalibur.components:excalibur-pool-instrumented:org.apache.avalon.excalibur.pool.TraceableResourceLimitingPool","name":"TraceableResourceLimitingPool","scope":"FIL","qualifier":"CLA","language":"java"}}
 ]
\ No newline at end of file