]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6408 Restore PostJob execution in preview mode 212/head
authorJulien HENRY <julien.henry@sonarsource.com>
Mon, 13 Apr 2015 07:16:32 +0000 (09:16 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Tue, 14 Apr 2015 08:14:30 +0000 (10:14 +0200)
40 files changed:
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/extensions/XooPostJob.java [new file with mode: 0644]
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/extensions/XooPostJobTest.java [new file with mode: 0644]
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java
sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseLessPhaseExecutor.java
sonar-batch/src/main/java/org/sonar/batch/postjob/DefaultPostJobContext.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/postjob/PostJobOptimizer.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/postjob/PostJobWrapper.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/postjob/package-info.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/sensor/AnalyzerOptimizer.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java
sonar-batch/src/main/java/org/sonar/batch/sensor/SensorOptimizer.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/sensor/SensorWrapper.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
sonar-batch/src/test/java/org/sonar/batch/deprecated/decorator/DecoratorsSelectorTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/preview/PreviewAndReportsMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/postjob/DefaultPostJobContextTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/postjob/PostJobOptimizerTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/sensor/AnalyzerOptimizerTest.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java
sonar-batch/src/test/java/org/sonar/batch/sensor/SensorOptimizerTest.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJob.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJobContext.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJobDescriptor.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/internal/DefaultPostJobDescriptor.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/issue/Issue.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/issue/package-info.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/package-info.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Severity.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/Issue.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/NewIssue.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java

index 8aa011ef8736b1b01bda2f3ef94776477bbf8075..a94fe8c055c57434b23f1900a04a12f62a2ea0ef 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.xoo;
 
 import org.sonar.api.SonarPlugin;
+import org.sonar.xoo.extensions.XooPostJob;
 import org.sonar.xoo.extensions.XooProjectBuilder;
 import org.sonar.xoo.lang.*;
 import org.sonar.xoo.rule.*;
@@ -70,6 +71,7 @@ public class XooPlugin extends SonarPlugin {
       CreateIssueByInternalKeySensor.class,
 
       // Other
-      XooProjectBuilder.class);
+      XooProjectBuilder.class,
+      XooPostJob.class);
   }
 }
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/extensions/XooPostJob.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/extensions/XooPostJob.java
new file mode 100644 (file)
index 0000000..80b27f2
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.xoo.extensions;
+
+import com.google.common.collect.Iterables;
+import org.sonar.api.batch.postjob.PostJob;
+import org.sonar.api.batch.postjob.PostJobContext;
+import org.sonar.api.batch.postjob.PostJobDescriptor;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+public class XooPostJob implements PostJob {
+
+  private static final Logger LOG = Loggers.get(XooPostJob.class);
+
+  @Override
+  public void describe(PostJobDescriptor descriptor) {
+    descriptor.name("Xoo Post Job")
+      .requireProperty("sonar.xoo.enablePostJob");
+
+  }
+
+  @Override
+  public void execute(PostJobContext context) {
+    LOG.info("Resolved issues: " + Iterables.size(context.resolvedIssues()));
+    LOG.info("Open issues: " + Iterables.size(context.issues()));
+  }
+
+}
index 4aa4ea7e33f55cd627da7f1bbd4020559dbc9890..fc0a564c69cd36010b4377ee4433b258099d9e2e 100644 (file)
@@ -23,10 +23,10 @@ import org.sonar.api.batch.fs.FilePredicates;
 import org.sonar.api.batch.fs.FileSystem;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputFile.Type;
+import org.sonar.api.batch.rule.Severity;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.xoo.Xoo;
 
diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/extensions/XooPostJobTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/extensions/XooPostJobTest.java
new file mode 100644 (file)
index 0000000..4af975c
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.xoo.extensions;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.batch.postjob.PostJobContext;
+import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor;
+import org.sonar.api.batch.postjob.issue.Issue;
+import org.sonar.api.utils.log.LogTester;
+
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class XooPostJobTest {
+
+  @Rule
+  public LogTester logTester = new LogTester();
+
+  @Test
+  public void increaseCoverage() {
+    new XooPostJob().describe(new DefaultPostJobDescriptor());
+    PostJobContext context = mock(PostJobContext.class);
+    when(context.issues()).thenReturn(Arrays.<Issue>asList());
+    when(context.resolvedIssues()).thenReturn(Arrays.<Issue>asList());
+    new XooPostJob().execute(context);
+    assertThat(logTester.logs()).contains("Resolved issues: 0", "Open issues: 0");
+  }
+}
index ab8ea247d35f201ff9592b20ebdbbc9ab77d3cb2..a3cbbf5eb847408009849995b4b691f3e03a81f9 100644 (file)
@@ -19,8 +19,6 @@
  */
 package org.sonar.xoo.rule;
 
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
@@ -29,10 +27,11 @@ import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 import org.sonar.api.batch.fs.internal.DefaultFileSystem;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.rule.Severity;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
 import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
 import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
 import org.sonar.api.config.Settings;
 import org.sonar.xoo.Xoo;
index 95f333fe93e332e7cc1d504041b3398fa2f475cc..0f1eea698ea32035b523362c50ee0410e7e6949e 100644 (file)
@@ -28,15 +28,19 @@ import org.sonar.api.batch.CheckProject;
 import org.sonar.api.batch.DependedUpon;
 import org.sonar.api.batch.DependsUpon;
 import org.sonar.api.batch.Phase;
+import org.sonar.api.batch.postjob.PostJob;
+import org.sonar.api.batch.postjob.PostJobContext;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
 import org.sonar.api.utils.AnnotationUtils;
 import org.sonar.api.utils.dag.DirectAcyclicGraph;
-import org.sonar.batch.scan.SensorWrapper;
-import org.sonar.batch.sensor.AnalyzerOptimizer;
+import org.sonar.batch.postjob.PostJobOptimizer;
+import org.sonar.batch.postjob.PostJobWrapper;
 import org.sonar.batch.sensor.DefaultSensorContext;
+import org.sonar.batch.sensor.SensorOptimizer;
+import org.sonar.batch.sensor.SensorWrapper;
 
 import javax.annotation.Nullable;
 
@@ -55,13 +59,18 @@ import java.util.List;
 public class BatchExtensionDictionnary {
 
   private final ComponentContainer componentContainer;
-  private final SensorContext context;
-  private final AnalyzerOptimizer analyzerOptimizer;
+  private final SensorContext sensorContext;
+  private final SensorOptimizer sensorOptimizer;
+  private final PostJobContext postJobContext;
+  private final PostJobOptimizer postJobOptimizer;
 
-  public BatchExtensionDictionnary(ComponentContainer componentContainer, DefaultSensorContext context, AnalyzerOptimizer analyzerOptimizer) {
+  public BatchExtensionDictionnary(ComponentContainer componentContainer, DefaultSensorContext sensorContext, SensorOptimizer sensorOptimizer, PostJobContext postJobContext,
+    PostJobOptimizer postJobOptimizer) {
     this.componentContainer = componentContainer;
-    this.context = context;
-    this.analyzerOptimizer = analyzerOptimizer;
+    this.sensorContext = sensorContext;
+    this.sensorOptimizer = sensorOptimizer;
+    this.postJobContext = postJobContext;
+    this.postJobOptimizer = postJobOptimizer;
   }
 
   public <T> Collection<T> select(Class<T> type, @Nullable Project project, boolean sort, @Nullable ExtensionMatcher matcher) {
@@ -90,7 +99,7 @@ public class BatchExtensionDictionnary {
     List<T> result = Lists.newArrayList();
     for (Object extension : getExtensions(type)) {
       if (org.sonar.api.batch.Sensor.class.equals(type) && extension instanceof Sensor) {
-        extension = new SensorWrapper((Sensor) extension, context, analyzerOptimizer);
+        extension = new SensorWrapper((Sensor) extension, sensorContext, sensorOptimizer);
       }
       if (shouldKeep(type, extension, project, matcher)) {
         result.add((T) extension);
@@ -99,7 +108,16 @@ public class BatchExtensionDictionnary {
     if (org.sonar.api.batch.Sensor.class.equals(type)) {
       // Retrieve new Sensors and wrap then in SensorWrapper
       for (Object extension : getExtensions(Sensor.class)) {
-        extension = new SensorWrapper((Sensor) extension, context, analyzerOptimizer);
+        extension = new SensorWrapper((Sensor) extension, sensorContext, sensorOptimizer);
+        if (shouldKeep(type, extension, project, matcher)) {
+          result.add((T) extension);
+        }
+      }
+    }
+    if (org.sonar.api.batch.PostJob.class.equals(type)) {
+      // Retrieve new PostJob and wrap then in PostJobWrapper
+      for (Object extension : getExtensions(PostJob.class)) {
+        extension = new PostJobWrapper((PostJob) extension, postJobContext, postJobOptimizer);
         if (shouldKeep(type, extension, project, matcher)) {
           result.add((T) extension);
         }
index 64f7e8d2446f31038ef97969a879d7527155ab2a..f17b42c18dbcba2f749882c00c63d15cb48c492f 100644 (file)
@@ -48,7 +48,7 @@ public class ModuleIssues {
   private final Project project;
   private final IssueFilters filters;
 
-  public ModuleIssues(ActiveRules activeRules, @Nullable Rules rules, IssueCache cache, @Nullable Project project, IssueFilters filters) {
+  public ModuleIssues(ActiveRules activeRules, @Nullable Rules rules, IssueCache cache, Project project, IssueFilters filters) {
     this.activeRules = activeRules;
     this.rules = rules;
     this.cache = cache;
@@ -56,17 +56,10 @@ public class ModuleIssues {
     this.filters = filters;
   }
 
-  public ModuleIssues(ActiveRules activeRules, IssueCache cache, @Nullable Project project, IssueFilters filters) {
+  public ModuleIssues(ActiveRules activeRules, IssueCache cache, Project project, IssueFilters filters) {
     this(activeRules, null, cache, project, filters);
   }
 
-  /** 
-   * Used by scan2
-   */
-  public ModuleIssues(ActiveRules activeRules, Rules rules, IssueCache cache, IssueFilters filters) {
-    this(activeRules, rules, cache, null, filters);
-  }
-
   public boolean initAndAddViolation(Violation violation) {
     DefaultIssue issue = newIssue(violation);
     return initAndAddIssue(issue);
index e116bb8056587915a7e801e1ad9f2b9c1d81b6ba..9a0d765ca662db33d4c8e2bbc40020b7798f936e 100644 (file)
@@ -37,6 +37,7 @@ public final class DatabaseLessPhaseExecutor implements PhaseExecutor {
   private final EventBus eventBus;
   private final Phases phases;
   private final InitializersExecutor initializersExecutor;
+  private final PostJobsExecutor postJobsExecutor;
   private final SensorsExecutor sensorsExecutor;
   private final SensorContext sensorContext;
   private final DefaultIndex index;
@@ -49,12 +50,13 @@ public final class DatabaseLessPhaseExecutor implements PhaseExecutor {
   private final LocalIssueTracking localIssueTracking;
   private final ReportPublisher reportPublisher;
 
-  public DatabaseLessPhaseExecutor(Phases phases, InitializersExecutor initializersExecutor, SensorsExecutor sensorsExecutor,
+  public DatabaseLessPhaseExecutor(Phases phases, InitializersExecutor initializersExecutor, PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
     SensorContext sensorContext, DefaultIndex index,
     EventBus eventBus, ProjectInitializer pi, FileSystemLogger fsLogger, IssuesReports jsonReport, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
     IssueExclusionsLoader issueExclusionsLoader, LocalIssueTracking localIssueTracking, ReportPublisher reportPublisher) {
     this.phases = phases;
     this.initializersExecutor = initializersExecutor;
+    this.postJobsExecutor = postJobsExecutor;
     this.sensorsExecutor = sensorsExecutor;
     this.sensorContext = sensorContext;
     this.index = index;
@@ -97,6 +99,9 @@ public final class DatabaseLessPhaseExecutor implements PhaseExecutor {
       localIssueTracking();
       issuesReport();
       publishReportJob();
+      if (phases.isEnabled(Phases.Phase.POSTJOB)) {
+        postJobsExecutor.execute(sensorContext);
+      }
     }
 
     cleanMemory();
diff --git a/sonar-batch/src/main/java/org/sonar/batch/postjob/DefaultPostJobContext.java b/sonar-batch/src/main/java/org/sonar/batch/postjob/DefaultPostJobContext.java
new file mode 100644 (file)
index 0000000..56840eb
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.postjob;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.api.batch.fs.InputPath;
+import org.sonar.api.batch.postjob.PostJobContext;
+import org.sonar.api.batch.postjob.issue.Issue;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.config.Settings;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.batch.index.BatchResource;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.issue.IssueCache;
+
+import javax.annotation.Nullable;
+
+public class DefaultPostJobContext implements PostJobContext {
+
+  private final Settings settings;
+  private final AnalysisMode analysisMode;
+  private final IssueCache cache;
+  private final ResourceCache resourceCache;
+
+  public DefaultPostJobContext(Settings settings, AnalysisMode analysisMode, IssueCache cache, ResourceCache resourceCache) {
+    this.settings = settings;
+    this.analysisMode = analysisMode;
+    this.cache = cache;
+    this.resourceCache = resourceCache;
+  }
+
+  @Override
+  public Settings settings() {
+    return settings;
+  }
+
+  @Override
+  public AnalysisMode analysisMode() {
+    return analysisMode;
+  }
+
+  @Override
+  public Iterable<Issue> issues() {
+    return Iterables.transform(Iterables.filter(cache.all(), new ResolvedPredicate(false)), new Function<DefaultIssue, Issue>() {
+      @Override
+      public Issue apply(DefaultIssue input) {
+        return new DefaultIssueWrapper(input);
+      }
+    });
+  }
+
+  @Override
+  public Iterable<Issue> resolvedIssues() {
+    return Iterables.transform(Iterables.filter(cache.all(), new ResolvedPredicate(true)), new Function<DefaultIssue, Issue>() {
+      @Override
+      public Issue apply(DefaultIssue input) {
+        return new DefaultIssueWrapper(input);
+      }
+    });
+  }
+
+  private class DefaultIssueWrapper implements Issue {
+
+    private final DefaultIssue wrapped;
+
+    public DefaultIssueWrapper(DefaultIssue wrapped) {
+      this.wrapped = wrapped;
+    }
+
+    @Override
+    public String key() {
+      return wrapped.key();
+    }
+
+    @Override
+    public RuleKey ruleKey() {
+      return wrapped.ruleKey();
+    }
+
+    @Override
+    public String componentKey() {
+      return wrapped.componentKey();
+    }
+
+    @Override
+    public InputPath inputPath() {
+      BatchResource component = resourceCache.get(wrapped.componentKey());
+      return component != null ? component.inputPath() : null;
+    }
+
+    @Override
+    public Integer line() {
+      return wrapped.line();
+    }
+
+    @Override
+    public Double effortToFix() {
+      return wrapped.effortToFix();
+    }
+
+    @Override
+    public String message() {
+      return wrapped.message();
+    }
+
+    @Override
+    public Severity severity() {
+      String severity = wrapped.severity();
+      return severity != null ? Severity.valueOf(severity) : null;
+    }
+
+    @Override
+    public boolean isNew() {
+      return wrapped.isNew();
+    }
+
+  }
+
+  private static class ResolvedPredicate implements Predicate<DefaultIssue> {
+    private final boolean resolved;
+
+    private ResolvedPredicate(boolean resolved) {
+      this.resolved = resolved;
+    }
+
+    @Override
+    public boolean apply(@Nullable DefaultIssue issue) {
+      if (issue != null) {
+        return resolved ? issue.resolution() != null : issue.resolution() == null;
+      }
+      return false;
+    }
+  }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/postjob/PostJobOptimizer.java b/sonar-batch/src/main/java/org/sonar/batch/postjob/PostJobOptimizer.java
new file mode 100644 (file)
index 0000000..fa4f3ea
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.postjob;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor;
+import org.sonar.api.config.Settings;
+
+public class PostJobOptimizer implements BatchComponent {
+
+  private static final Logger LOG = LoggerFactory.getLogger(PostJobOptimizer.class);
+
+  private final Settings settings;
+  private final AnalysisMode analysisMode;
+
+  public PostJobOptimizer(Settings settings, AnalysisMode analysisMode) {
+    this.settings = settings;
+    this.analysisMode = analysisMode;
+  }
+
+  /**
+   * Decide if the given PostJob should be executed.
+   */
+  public boolean shouldExecute(DefaultPostJobDescriptor descriptor) {
+    if (!settingsCondition(descriptor)) {
+      LOG.debug("'{}' skipped because one of the required properties is missing", descriptor.name());
+      return false;
+    }
+    if (descriptor.isDisabledInPreview() && analysisMode.isPreview()) {
+      LOG.debug("'{}' skipped in preview mode", descriptor.name());
+      return false;
+    }
+    return true;
+  }
+
+  private boolean settingsCondition(DefaultPostJobDescriptor descriptor) {
+    if (!descriptor.properties().isEmpty()) {
+      for (String propertyKey : descriptor.properties()) {
+        if (!settings.hasKey(propertyKey)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/postjob/PostJobWrapper.java b/sonar-batch/src/main/java/org/sonar/batch/postjob/PostJobWrapper.java
new file mode 100644 (file)
index 0000000..45182e6
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.postjob;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.CheckProject;
+import org.sonar.api.batch.postjob.PostJob;
+import org.sonar.api.batch.postjob.PostJobContext;
+import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor;
+import org.sonar.api.resources.Project;
+
+public class PostJobWrapper implements org.sonar.api.batch.PostJob, CheckProject {
+
+  private static final Logger LOG = LoggerFactory.getLogger(PostJobWrapper.class);
+
+  private PostJob wrappedPostJob;
+  private PostJobContext adaptor;
+  private DefaultPostJobDescriptor descriptor;
+  private PostJobOptimizer optimizer;
+
+  public PostJobWrapper(PostJob newPostJob, PostJobContext adaptor, PostJobOptimizer optimizer) {
+    this.wrappedPostJob = newPostJob;
+    this.optimizer = optimizer;
+    descriptor = new DefaultPostJobDescriptor();
+    newPostJob.describe(descriptor);
+    this.adaptor = adaptor;
+  }
+
+  public PostJob wrappedPostJob() {
+    return wrappedPostJob;
+  }
+
+  @Override
+  public boolean shouldExecuteOnProject(Project project) {
+    return optimizer.shouldExecute(descriptor);
+  }
+
+  @Override
+  public void executeOn(Project project, org.sonar.api.batch.SensorContext context) {
+    wrappedPostJob.execute(adaptor);
+  }
+
+  @Override
+  public String toString() {
+    return descriptor.name() + (LOG.isDebugEnabled() ? " (wrapped)" : "");
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/postjob/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/postjob/package-info.java
new file mode 100644 (file)
index 0000000..b4bab61
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.postjob;
index d9a67454ad0e2bcb43254ba4f8445eef6455c92e..a05aee3193cc752290a0a1ceecdb1721088d854e 100644 (file)
@@ -55,14 +55,16 @@ import org.sonar.batch.issue.tracking.IssueHandlers;
 import org.sonar.batch.issue.tracking.IssueTrackingDecorator;
 import org.sonar.batch.language.LanguageDistributionDecorator;
 import org.sonar.batch.phases.*;
+import org.sonar.batch.postjob.DefaultPostJobContext;
+import org.sonar.batch.postjob.PostJobOptimizer;
 import org.sonar.batch.qualitygate.GenerateQualityGateEvents;
 import org.sonar.batch.qualitygate.QualityGateVerifier;
 import org.sonar.batch.rule.*;
 import org.sonar.batch.scan.filesystem.*;
 import org.sonar.batch.scan.report.IssuesReports;
-import org.sonar.batch.sensor.AnalyzerOptimizer;
 import org.sonar.batch.sensor.DefaultSensorContext;
 import org.sonar.batch.sensor.DefaultSensorStorage;
+import org.sonar.batch.sensor.SensorOptimizer;
 import org.sonar.batch.sensor.coverage.CoverageExclusions;
 import org.sonar.batch.source.HighlightableBuilder;
 import org.sonar.batch.source.SymbolizableBuilder;
@@ -134,9 +136,11 @@ public class ModuleScanContainer extends ComponentContainer {
       ProjectFileSystemAdapter.class,
       QProfileVerifier.class,
 
-      AnalyzerOptimizer.class,
+      SensorOptimizer.class,
+      PostJobOptimizer.class,
 
       DefaultSensorContext.class,
+      DefaultPostJobContext.class,
       DefaultSensorStorage.class,
       DeprecatedSensorContext.class,
       BatchExtensionDictionnary.class,
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java
deleted file mode 100644 (file)
index 8884bef..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.batch.scan;
-
-import org.sonar.batch.sensor.AnalyzerOptimizer;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
-import org.sonar.api.resources.Project;
-
-public class SensorWrapper implements org.sonar.api.batch.Sensor {
-
-  private static final Logger LOG = LoggerFactory.getLogger(SensorWrapper.class);
-
-  private Sensor wrappedSensor;
-  private SensorContext adaptor;
-  private DefaultSensorDescriptor descriptor;
-  private AnalyzerOptimizer optimizer;
-
-  public SensorWrapper(Sensor newSensor, SensorContext adaptor, AnalyzerOptimizer optimizer) {
-    this.wrappedSensor = newSensor;
-    this.optimizer = optimizer;
-    descriptor = new DefaultSensorDescriptor();
-    newSensor.describe(descriptor);
-    this.adaptor = adaptor;
-  }
-
-  public Sensor wrappedSensor() {
-    return wrappedSensor;
-  }
-
-  @Override
-  public boolean shouldExecuteOnProject(Project project) {
-    return optimizer.shouldExecute(descriptor);
-  }
-
-  @Override
-  public void analyse(Project module, org.sonar.api.batch.SensorContext context) {
-    wrappedSensor.execute(adaptor);
-  }
-
-  @Override
-  public String toString() {
-    return descriptor.name() + (LOG.isDebugEnabled() ? " (wrapped)" : "");
-  }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/AnalyzerOptimizer.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/AnalyzerOptimizer.java
deleted file mode 100644 (file)
index f114e4a..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.batch.sensor;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.batch.AnalysisMode;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
-import org.sonar.api.config.Settings;
-
-public class AnalyzerOptimizer implements BatchComponent {
-
-  private static final Logger LOG = LoggerFactory.getLogger(AnalyzerOptimizer.class);
-
-  private final FileSystem fs;
-  private final ActiveRules activeRules;
-  private final Settings settings;
-  private final AnalysisMode analysisMode;
-
-  public AnalyzerOptimizer(FileSystem fs, ActiveRules activeRules, Settings settings, AnalysisMode analysisMode) {
-    this.fs = fs;
-    this.activeRules = activeRules;
-    this.settings = settings;
-    this.analysisMode = analysisMode;
-  }
-
-  /**
-   * Decide if the given Analyzer should be executed.
-   */
-  public boolean shouldExecute(DefaultSensorDescriptor descriptor) {
-    if (!fsCondition(descriptor)) {
-      LOG.debug("'{}' skipped because there is no related file in current project", descriptor.name());
-      return false;
-    }
-    if (!activeRulesCondition(descriptor)) {
-      LOG.debug("'{}' skipped because there is no related rule activated in the quality profile", descriptor.name());
-      return false;
-    }
-    if (!settingsCondition(descriptor)) {
-      LOG.debug("'{}' skipped because one of the required properties is missing", descriptor.name());
-      return false;
-    }
-    if (descriptor.isDisabledInPreview() && analysisMode.isPreview()) {
-      LOG.debug("'{}' skipped in preview mode", descriptor.name());
-      return false;
-    }
-    return true;
-  }
-
-  private boolean settingsCondition(DefaultSensorDescriptor descriptor) {
-    if (!descriptor.properties().isEmpty()) {
-      for (String propertyKey : descriptor.properties()) {
-        if (!settings.hasKey(propertyKey)) {
-          return false;
-        }
-      }
-    }
-    return true;
-  }
-
-  private boolean activeRulesCondition(DefaultSensorDescriptor descriptor) {
-    if (!descriptor.ruleRepositories().isEmpty()) {
-      for (String repoKey : descriptor.ruleRepositories()) {
-        if (!activeRules.findByRepository(repoKey).isEmpty()) {
-          return true;
-        }
-      }
-      return false;
-    }
-    return true;
-  }
-
-  private boolean fsCondition(DefaultSensorDescriptor descriptor) {
-    if (!descriptor.languages().isEmpty() || descriptor.type() != null) {
-      FilePredicate langPredicate = descriptor.languages().isEmpty() ? fs.predicates().all() : fs.predicates().hasLanguages(descriptor.languages());
-
-      FilePredicate typePredicate = descriptor.type() == null ? fs.predicates().all() : fs.predicates().hasType(descriptor.type());
-      return fs.hasFiles(fs.predicates().and(langPredicate, typePredicate));
-    }
-    return true;
-  }
-
-}
index 99cdf8bbb701c2d8450e2bd9a852b9234a102cb7..f73c35c06793aa1a4057bf4a51652ad0d3289683 100644 (file)
@@ -29,13 +29,13 @@ import org.sonar.api.batch.fs.TextRange;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.Severity;
 import org.sonar.api.batch.sensor.duplication.Duplication;
 import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
 import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
 import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
 import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
 import org.sonar.api.batch.sensor.measure.Measure;
 import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.config.Settings;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/SensorOptimizer.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/SensorOptimizer.java
new file mode 100644 (file)
index 0000000..dbc4eac
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.sensor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.config.Settings;
+
+public class SensorOptimizer implements BatchComponent {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SensorOptimizer.class);
+
+  private final FileSystem fs;
+  private final ActiveRules activeRules;
+  private final Settings settings;
+  private final AnalysisMode analysisMode;
+
+  public SensorOptimizer(FileSystem fs, ActiveRules activeRules, Settings settings, AnalysisMode analysisMode) {
+    this.fs = fs;
+    this.activeRules = activeRules;
+    this.settings = settings;
+    this.analysisMode = analysisMode;
+  }
+
+  /**
+   * Decide if the given Sensor should be executed.
+   */
+  public boolean shouldExecute(DefaultSensorDescriptor descriptor) {
+    if (!fsCondition(descriptor)) {
+      LOG.debug("'{}' skipped because there is no related file in current project", descriptor.name());
+      return false;
+    }
+    if (!activeRulesCondition(descriptor)) {
+      LOG.debug("'{}' skipped because there is no related rule activated in the quality profile", descriptor.name());
+      return false;
+    }
+    if (!settingsCondition(descriptor)) {
+      LOG.debug("'{}' skipped because one of the required properties is missing", descriptor.name());
+      return false;
+    }
+    if (descriptor.isDisabledInPreview() && analysisMode.isPreview()) {
+      LOG.debug("'{}' skipped in preview mode", descriptor.name());
+      return false;
+    }
+    return true;
+  }
+
+  private boolean settingsCondition(DefaultSensorDescriptor descriptor) {
+    if (!descriptor.properties().isEmpty()) {
+      for (String propertyKey : descriptor.properties()) {
+        if (!settings.hasKey(propertyKey)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  private boolean activeRulesCondition(DefaultSensorDescriptor descriptor) {
+    if (!descriptor.ruleRepositories().isEmpty()) {
+      for (String repoKey : descriptor.ruleRepositories()) {
+        if (!activeRules.findByRepository(repoKey).isEmpty()) {
+          return true;
+        }
+      }
+      return false;
+    }
+    return true;
+  }
+
+  private boolean fsCondition(DefaultSensorDescriptor descriptor) {
+    if (!descriptor.languages().isEmpty() || descriptor.type() != null) {
+      FilePredicate langPredicate = descriptor.languages().isEmpty() ? fs.predicates().all() : fs.predicates().hasLanguages(descriptor.languages());
+
+      FilePredicate typePredicate = descriptor.type() == null ? fs.predicates().all() : fs.predicates().hasType(descriptor.type());
+      return fs.hasFiles(fs.predicates().and(langPredicate, typePredicate));
+    }
+    return true;
+  }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/SensorWrapper.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/SensorWrapper.java
new file mode 100644 (file)
index 0000000..143160e
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.sensor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.sensor.Sensor;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.resources.Project;
+
+public class SensorWrapper implements org.sonar.api.batch.Sensor {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SensorWrapper.class);
+
+  private Sensor wrappedSensor;
+  private SensorContext adaptor;
+  private DefaultSensorDescriptor descriptor;
+  private SensorOptimizer optimizer;
+
+  public SensorWrapper(Sensor newSensor, SensorContext adaptor, SensorOptimizer optimizer) {
+    this.wrappedSensor = newSensor;
+    this.optimizer = optimizer;
+    descriptor = new DefaultSensorDescriptor();
+    newSensor.describe(descriptor);
+    this.adaptor = adaptor;
+  }
+
+  public Sensor wrappedSensor() {
+    return wrappedSensor;
+  }
+
+  @Override
+  public boolean shouldExecuteOnProject(Project project) {
+    return optimizer.shouldExecute(descriptor);
+  }
+
+  @Override
+  public void analyse(Project module, org.sonar.api.batch.SensorContext context) {
+    wrappedSensor.execute(adaptor);
+  }
+
+  @Override
+  public String toString() {
+    return descriptor.name() + (LOG.isDebugEnabled() ? " (wrapped)" : "");
+  }
+}
index 046f6664967da5c2a78d7dfa31c3d0d9b3e07890..14fde3895efe1bbf46e89a6127c421613be4c599 100644 (file)
@@ -22,19 +22,13 @@ package org.sonar.batch.bootstrap;
 import com.google.common.collect.Lists;
 import org.junit.Test;
 import org.sonar.api.BatchExtension;
-import org.sonar.api.batch.BuildBreaker;
-import org.sonar.api.batch.CheckProject;
-import org.sonar.api.batch.Decorator;
-import org.sonar.api.batch.DependedUpon;
-import org.sonar.api.batch.DependsUpon;
-import org.sonar.api.batch.Phase;
-import org.sonar.api.batch.PostJob;
-import org.sonar.api.batch.Sensor;
-import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.*;
+import org.sonar.api.batch.postjob.PostJobContext;
 import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
-import org.sonar.batch.sensor.AnalyzerOptimizer;
+import org.sonar.batch.postjob.PostJobOptimizer;
 import org.sonar.batch.sensor.DefaultSensorContext;
+import org.sonar.batch.sensor.SensorOptimizer;
 
 import java.util.Arrays;
 import java.util.Collection;
@@ -53,7 +47,8 @@ public class BatchExtensionDictionnaryTest {
     for (BatchExtension extension : extensions) {
       iocContainer.addSingleton(extension);
     }
-    return new BatchExtensionDictionnary(iocContainer, mock(DefaultSensorContext.class), mock(AnalyzerOptimizer.class));
+    return new BatchExtensionDictionnary(iocContainer, mock(DefaultSensorContext.class), mock(SensorOptimizer.class), mock(PostJobContext.class),
+      mock(PostJobOptimizer.class));
   }
 
   @Test
@@ -98,7 +93,8 @@ public class BatchExtensionDictionnaryTest {
     ComponentContainer child = parent.createChild();
     child.addSingleton(c);
 
-    BatchExtensionDictionnary dictionnary = new BatchExtensionDictionnary(child, mock(DefaultSensorContext.class), mock(AnalyzerOptimizer.class));
+    BatchExtensionDictionnary dictionnary = new BatchExtensionDictionnary(child, mock(DefaultSensorContext.class), mock(SensorOptimizer.class), mock(PostJobContext.class),
+      mock(PostJobOptimizer.class));
     assertThat(dictionnary.select(BatchExtension.class, null, true, null)).containsOnly(a, b, c);
   }
 
index f469d6b52e98e5ce1ed61763bb991ee36ec67715..fd9a9ed37272a31b6fc511ed5aa71748e9bba76e 100644 (file)
@@ -24,11 +24,7 @@ import org.junit.Test;
 import org.sonar.api.batch.Decorator;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependedUpon;
-import org.sonar.api.measures.Formula;
-import org.sonar.api.measures.FormulaContext;
-import org.sonar.api.measures.FormulaData;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.*;
 import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
@@ -81,7 +77,7 @@ public class DecoratorsSelectorTest {
     for (Object extension : extensions) {
       ioc.addSingleton(extension);
     }
-    return new BatchExtensionDictionnary(ioc, null, null);
+    return new BatchExtensionDictionnary(ioc, null, null, null, null);
   }
 
   class FakeFormula implements Formula {
index 22f8a339f1393083163f874dc4a6033720035e38..d97f6ba995d769343979799847823766c26ac38b 100644 (file)
@@ -25,7 +25,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
+import org.sonar.api.batch.rule.Severity;
 import org.sonar.batch.mediumtest.BatchMediumTester;
 import org.sonar.batch.mediumtest.TaskResult;
 import org.sonar.batch.protocol.input.ActiveRule;
index c8368f37246d738edb74cda3c128db4d448ce3a4..ab2157d056d0627623cab00a31cdac79ddbf0e26 100644 (file)
@@ -163,6 +163,18 @@ public class PreviewAndReportsMediumTest {
     assertThat(getReportLog()).contains("+13 issues", "+13 major");
   }
 
+  @Test
+  public void testPostJob() throws Exception {
+    File projectDir = new File(PreviewAndReportsMediumTest.class.getResource("/mediumtest/xoo/sample").toURI());
+
+    tester
+      .newScanTask(new File(projectDir, "sonar-project.properties"))
+      .property("sonar.xoo.enablePostJob", "true")
+      .start();
+
+    assertThat(logTester.logs()).contains("Resolved issues: 2", "Open issues: 15");
+  }
+
   private String getReportLog() {
     for (String log : logTester.logs()) {
       if (log.contains(ConsoleReport.HEADER)) {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/postjob/DefaultPostJobContextTest.java b/sonar-batch/src/test/java/org/sonar/batch/postjob/DefaultPostJobContextTest.java
new file mode 100644 (file)
index 0000000..9ca6dd4
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.postjob;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.postjob.issue.Issue;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.config.Settings;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.resources.File;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.issue.IssueCache;
+
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DefaultPostJobContextTest {
+
+  private IssueCache issueCache;
+  private ResourceCache resourceCache;
+  private AnalysisMode analysisMode;
+  private DefaultPostJobContext context;
+  private Settings settings;
+
+  @Before
+  public void prepare() {
+    issueCache = mock(IssueCache.class);
+    resourceCache = new ResourceCache();
+    analysisMode = mock(AnalysisMode.class);
+    settings = new Settings();
+    context = new DefaultPostJobContext(settings, analysisMode, issueCache, resourceCache);
+  }
+
+  @Test
+  public void test() {
+    assertThat(context.settings()).isSameAs(settings);
+    assertThat(context.analysisMode()).isSameAs(analysisMode);
+
+    DefaultIssue defaultIssue = new DefaultIssue();
+    defaultIssue.setComponentKey("foo:src/Foo.php");
+    defaultIssue.setEffortToFix(2.0);
+    defaultIssue.setNew(true);
+    defaultIssue.setKey("xyz");
+    defaultIssue.setLine(1);
+    defaultIssue.setMessage("msg");
+    defaultIssue.setSeverity("BLOCKER");
+    when(issueCache.all()).thenReturn(Arrays.asList(defaultIssue));
+
+    Issue issue = context.issues().iterator().next();
+    assertThat(issue.componentKey()).isEqualTo("foo:src/Foo.php");
+    assertThat(issue.effortToFix()).isEqualTo(2.0);
+    assertThat(issue.isNew()).isTrue();
+    assertThat(issue.key()).isEqualTo("xyz");
+    assertThat(issue.line()).isEqualTo(1);
+    assertThat(issue.message()).isEqualTo("msg");
+    assertThat(issue.severity()).isEqualTo(Severity.BLOCKER);
+    assertThat(issue.inputPath()).isNull();
+
+    InputFile inputPath = mock(InputFile.class);
+    resourceCache.add(File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php"), null).setInputPath(inputPath);
+    assertThat(issue.inputPath()).isEqualTo(inputPath);
+
+  }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/postjob/PostJobOptimizerTest.java b/sonar-batch/src/test/java/org/sonar/batch/postjob/PostJobOptimizerTest.java
new file mode 100644 (file)
index 0000000..acd9ea1
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.postjob;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor;
+import org.sonar.api.config.Settings;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class PostJobOptimizerTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  private PostJobOptimizer optimizer;
+  private Settings settings;
+  private AnalysisMode analysisMode;
+
+  @Before
+  public void prepare() throws Exception {
+    settings = new Settings();
+    analysisMode = mock(AnalysisMode.class);
+    optimizer = new PostJobOptimizer(settings, analysisMode);
+  }
+
+  @Test
+  public void should_run_analyzer_with_no_metadata() throws Exception {
+    DefaultPostJobDescriptor descriptor = new DefaultPostJobDescriptor();
+
+    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+  }
+
+  @Test
+  public void should_optimize_on_settings() throws Exception {
+    DefaultPostJobDescriptor descriptor = new DefaultPostJobDescriptor()
+      .requireProperty("sonar.foo.reportPath");
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+    settings.setProperty("sonar.foo.reportPath", "foo");
+    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+  }
+
+  @Test
+  public void should_disabled_in_preview() throws Exception {
+    DefaultPostJobDescriptor descriptor = new DefaultPostJobDescriptor()
+      .disabledInPreview();
+    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+
+    when(analysisMode.isPreview()).thenReturn(true);
+
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+  }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/sensor/AnalyzerOptimizerTest.java b/sonar-batch/src/test/java/org/sonar/batch/sensor/AnalyzerOptimizerTest.java
deleted file mode 100644 (file)
index 1850fe2..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.batch.sensor;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.AnalysisMode;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultFileSystem;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
-import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
-import org.sonar.api.config.Settings;
-import org.sonar.api.rule.RuleKey;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class AnalyzerOptimizerTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  private DefaultFileSystem fs;
-  private AnalyzerOptimizer optimizer;
-  private Settings settings;
-  private AnalysisMode analysisMode;
-
-  @Before
-  public void prepare() throws Exception {
-    fs = new DefaultFileSystem(temp.newFolder().toPath());
-    settings = new Settings();
-    analysisMode = mock(AnalysisMode.class);
-    optimizer = new AnalyzerOptimizer(fs, new ActiveRulesBuilder().build(), settings, analysisMode);
-  }
-
-  @Test
-  public void should_run_analyzer_with_no_metadata() throws Exception {
-    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor();
-
-    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
-  }
-
-  @Test
-  public void should_optimize_on_language() throws Exception {
-    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
-      .onlyOnLanguages("java", "php");
-    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
-
-    fs.add(new DefaultInputFile("foo", "src/Foo.java").setLanguage("java"));
-    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
-  }
-
-  @Test
-  public void should_optimize_on_type() throws Exception {
-    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
-      .onlyOnFileType(InputFile.Type.MAIN);
-    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
-
-    fs.add(new DefaultInputFile("foo", "tests/FooTest.java").setType(InputFile.Type.TEST));
-    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
-
-    fs.add(new DefaultInputFile("foo", "src/Foo.java").setType(InputFile.Type.MAIN));
-    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
-  }
-
-  @Test
-  public void should_optimize_on_both_type_and_language() throws Exception {
-    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
-      .onlyOnLanguages("java", "php")
-      .onlyOnFileType(InputFile.Type.MAIN);
-    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
-
-    fs.add(new DefaultInputFile("foo", "tests/FooTest.java").setLanguage("java").setType(InputFile.Type.TEST));
-    fs.add(new DefaultInputFile("foo", "src/Foo.cbl").setLanguage("cobol").setType(InputFile.Type.MAIN));
-    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
-
-    fs.add(new DefaultInputFile("foo", "src/Foo.java").setLanguage("java").setType(InputFile.Type.MAIN));
-    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
-  }
-
-  @Test
-  public void should_optimize_on_repository() throws Exception {
-    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
-      .createIssuesForRuleRepositories("squid");
-    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
-
-    ActiveRules activeRules = new ActiveRulesBuilder()
-      .create(RuleKey.of("repo1", "foo"))
-      .activate()
-      .build();
-    optimizer = new AnalyzerOptimizer(fs, activeRules, settings, analysisMode);
-
-    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
-
-    activeRules = new ActiveRulesBuilder()
-      .create(RuleKey.of("repo1", "foo"))
-      .activate()
-      .create(RuleKey.of("squid", "rule"))
-      .activate()
-      .build();
-    optimizer = new AnalyzerOptimizer(fs, activeRules, settings, analysisMode);
-    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
-  }
-
-  @Test
-  public void should_optimize_on_settings() throws Exception {
-    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
-      .requireProperty("sonar.foo.reportPath");
-    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
-
-    settings.setProperty("sonar.foo.reportPath", "foo");
-    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
-  }
-
-  @Test
-  public void should_disabled_in_preview() throws Exception {
-    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
-      .disabledInPreview();
-    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
-
-    when(analysisMode.isPreview()).thenReturn(true);
-
-    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
-  }
-}
index 3114e054718de061c659baf6e8efb3080eee35c6..2ebab61ace3e5b279bc5746d49716ac8548d3d4a 100644 (file)
@@ -33,9 +33,9 @@ import org.sonar.api.batch.fs.internal.DefaultInputDir;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.Severity;
 import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
 import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
 import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
 import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.config.Settings;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/sensor/SensorOptimizerTest.java b/sonar-batch/src/test/java/org/sonar/batch/sensor/SensorOptimizerTest.java
new file mode 100644 (file)
index 0000000..12d5e00
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.sensor;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.config.Settings;
+import org.sonar.api.rule.RuleKey;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SensorOptimizerTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  private DefaultFileSystem fs;
+  private SensorOptimizer optimizer;
+  private Settings settings;
+  private AnalysisMode analysisMode;
+
+  @Before
+  public void prepare() throws Exception {
+    fs = new DefaultFileSystem(temp.newFolder().toPath());
+    settings = new Settings();
+    analysisMode = mock(AnalysisMode.class);
+    optimizer = new SensorOptimizer(fs, new ActiveRulesBuilder().build(), settings, analysisMode);
+  }
+
+  @Test
+  public void should_run_analyzer_with_no_metadata() throws Exception {
+    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor();
+
+    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+  }
+
+  @Test
+  public void should_optimize_on_language() throws Exception {
+    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
+      .onlyOnLanguages("java", "php");
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+    fs.add(new DefaultInputFile("foo", "src/Foo.java").setLanguage("java"));
+    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+  }
+
+  @Test
+  public void should_optimize_on_type() throws Exception {
+    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
+      .onlyOnFileType(InputFile.Type.MAIN);
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+    fs.add(new DefaultInputFile("foo", "tests/FooTest.java").setType(InputFile.Type.TEST));
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+    fs.add(new DefaultInputFile("foo", "src/Foo.java").setType(InputFile.Type.MAIN));
+    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+  }
+
+  @Test
+  public void should_optimize_on_both_type_and_language() throws Exception {
+    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
+      .onlyOnLanguages("java", "php")
+      .onlyOnFileType(InputFile.Type.MAIN);
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+    fs.add(new DefaultInputFile("foo", "tests/FooTest.java").setLanguage("java").setType(InputFile.Type.TEST));
+    fs.add(new DefaultInputFile("foo", "src/Foo.cbl").setLanguage("cobol").setType(InputFile.Type.MAIN));
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+    fs.add(new DefaultInputFile("foo", "src/Foo.java").setLanguage("java").setType(InputFile.Type.MAIN));
+    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+  }
+
+  @Test
+  public void should_optimize_on_repository() throws Exception {
+    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
+      .createIssuesForRuleRepositories("squid");
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+    ActiveRules activeRules = new ActiveRulesBuilder()
+      .create(RuleKey.of("repo1", "foo"))
+      .activate()
+      .build();
+    optimizer = new SensorOptimizer(fs, activeRules, settings, analysisMode);
+
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+    activeRules = new ActiveRulesBuilder()
+      .create(RuleKey.of("repo1", "foo"))
+      .activate()
+      .create(RuleKey.of("squid", "rule"))
+      .activate()
+      .build();
+    optimizer = new SensorOptimizer(fs, activeRules, settings, analysisMode);
+    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+  }
+
+  @Test
+  public void should_optimize_on_settings() throws Exception {
+    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
+      .requireProperty("sonar.foo.reportPath");
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+    settings.setProperty("sonar.foo.reportPath", "foo");
+    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+  }
+
+  @Test
+  public void should_disabled_in_preview() throws Exception {
+    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor()
+      .disabledInPreview();
+    assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+
+    when(analysisMode.isPreview()).thenReturn(true);
+
+    assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+  }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJob.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJob.java
new file mode 100644 (file)
index 0000000..06ac3e3
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.postjob;
+
+import com.google.common.annotations.Beta;
+import org.sonar.api.BatchExtension;
+
+/**
+ * PostJobs are executed at the very end of batch analysis. A PostJob can't do any modification
+ * since everything is already computed (issues, measures,...). <br/>
+ * WANRING: Do not rely on the fact that analysis results are available on server side using WS since this is an
+ * asynchronous process to compute data on server side in 5.x series.
+ *
+ * @since 5.2
+ */
+@Beta
+public interface PostJob extends BatchExtension {
+
+  /**
+   * Populate {@link PostJobDescriptor} of this PostJob.
+   */
+  void describe(PostJobDescriptor descriptor);
+
+  /**
+   * The actual sensor code.
+   */
+  void execute(PostJobContext context);
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJobContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJobContext.java
new file mode 100644 (file)
index 0000000..8af643a
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.postjob;
+
+import com.google.common.annotations.Beta;
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.api.batch.postjob.issue.Issue;
+import org.sonar.api.config.Settings;
+
+/**
+ * See {@link PostJob#execute(PostJobContext)}
+ * @since 5.2
+ */
+@Beta
+public interface PostJobContext {
+
+  /**
+   * Get settings of the current project.
+   */
+  Settings settings();
+
+  /**
+   * Get analysis mode.
+   */
+  AnalysisMode analysisMode();
+
+  // ----------- ISSUES --------------
+
+  /**
+   * All the unresolved issues of the project, including the issues reported by end-users.
+   */
+  Iterable<Issue> issues();
+
+  /**
+   * All the issues of this project that have been marked as resolved during this scan
+   */
+  Iterable<Issue> resolvedIssues();
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJobDescriptor.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJobDescriptor.java
new file mode 100644 (file)
index 0000000..d82c57b
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.postjob;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Describe what a {@link PostJob} is doing. Information may be used by the platform
+ * to log interesting information or perform some optimization.
+ * See {@link PostJob#describe(PostJobDescriptor)}
+ * @since 5.2
+ */
+@Beta
+public interface PostJobDescriptor {
+
+  /**
+   * Displayable name of the {@link PostJob}. Will be displayed in logs.
+   */
+  PostJobDescriptor name(String postJobName);
+
+  /**
+   * Property this {@link PostJob} depends on. Used by the platform to skip execution of the {@link PostJob} when
+   * property is not set.
+   */
+  PostJobDescriptor requireProperty(String... propertyKey);
+
+  /**
+   * List properties this {@link PostJob} depends on. Used by the platform to skip execution of the {@link PostJob} when
+   * property is not set.
+   */
+  PostJobDescriptor requireProperties(String... propertyKeys);
+
+  /**
+   * Should this PostJob be disabled in preview mode. Default is to run all PostJobs in preview mode.
+   */
+  PostJobDescriptor disabledInPreview();
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/internal/DefaultPostJobDescriptor.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/internal/DefaultPostJobDescriptor.java
new file mode 100644 (file)
index 0000000..f3b5142
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.postjob.internal;
+
+import org.sonar.api.batch.postjob.PostJobDescriptor;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public class DefaultPostJobDescriptor implements PostJobDescriptor {
+
+  private String name;
+  private String[] properties = new String[0];
+  private boolean disabledInPreview = false;
+
+  public String name() {
+    return name;
+  }
+
+  public Collection<String> properties() {
+    return Arrays.asList(properties);
+  }
+
+  public boolean isDisabledInPreview() {
+    return disabledInPreview;
+  }
+
+  @Override
+  public DefaultPostJobDescriptor name(String name) {
+    this.name = name;
+    return this;
+  }
+
+  @Override
+  public DefaultPostJobDescriptor requireProperty(String... propertyKey) {
+    return requireProperties(propertyKey);
+  }
+
+  @Override
+  public DefaultPostJobDescriptor requireProperties(String... propertyKeys) {
+    this.properties = propertyKeys;
+    return this;
+  }
+
+  @Override
+  public DefaultPostJobDescriptor disabledInPreview() {
+    this.disabledInPreview = true;
+    return this;
+  }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/issue/Issue.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/issue/Issue.java
new file mode 100644 (file)
index 0000000..ccf79d8
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.postjob.issue;
+
+import com.google.common.annotations.Beta;
+import org.sonar.api.batch.fs.InputPath;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.rule.RuleKey;
+
+import javax.annotation.CheckForNull;
+
+/**
+ * Represents an issue state at the end of the batch analysis. Only available after local issue tracking in preview mode.
+ *
+ * @since 5.2
+ */
+@Beta
+public interface Issue {
+
+  /**
+   * Key of the issue.
+   */
+  String key();
+
+  /**
+   * The {@link RuleKey} of this issue.
+   */
+  RuleKey ruleKey();
+
+  /**
+   * Component key like foo:src/Foo.php
+   */
+  String componentKey();
+
+  /**
+   * The {@link InputPath} this issue belongs to. Returns null if issue is global to the project or if component was deleted (for resolved issues).
+   */
+  @CheckForNull
+  InputPath inputPath();
+
+  /**
+   * Line of the issue. Null for global issues and issues on directories. Can also be null
+   * for files (issue global to the file).
+   */
+  @CheckForNull
+  Integer line();
+
+  /**
+   * Effort to fix the issue. Used by technical debt model.
+   */
+  @CheckForNull
+  Double effortToFix();
+
+  /**
+   * Message of the issue.
+   */
+  @CheckForNull
+  String message();
+
+  /**
+   * Severity.
+   */
+  Severity severity();
+
+  /**
+   * If the issue a new one.
+   */
+  boolean isNew();
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/issue/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/issue/package-info.java
new file mode 100644 (file)
index 0000000..7b3046f
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.api.batch.postjob.issue;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/package-info.java
new file mode 100644 (file)
index 0000000..398dee3
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.api.batch.postjob;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Severity.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Severity.java
new file mode 100644 (file)
index 0000000..f31055f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @since 5.2
+ */
+@Beta
+public enum Severity {
+  INFO,
+  MINOR,
+  MAJOR,
+  CRITICAL,
+  BLOCKER
+}
index b52cb989e4c75b3f0a0e53720545ff5fa074132e..834325d779210145597ce5ae0856c8ce6fc6da10 100644 (file)
@@ -45,12 +45,12 @@ import java.io.Serializable;
 public interface SensorContext {
 
   /**
-   * Get settings of the current project.
+   * Get settings of the current module.
    */
   Settings settings();
 
   /**
-   * Get filesystem of the current project.
+   * Get filesystem of the current module.
    */
   FileSystem fileSystem();
 
index e235b33abb4d28ecffcd76b41a940845233d90bc..8a446731c3cb06b0b7814030a148e4d3d059fb32 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.api.batch.sensor.issue;
 
 import com.google.common.annotations.Beta;
 import org.sonar.api.batch.fs.InputPath;
+import org.sonar.api.batch.rule.Severity;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.rule.RuleKey;
 
@@ -34,14 +35,6 @@ import javax.annotation.CheckForNull;
 @Beta
 public interface Issue {
 
-  enum Severity {
-    INFO,
-    MINOR,
-    MAJOR,
-    CRITICAL,
-    BLOCKER
-  }
-
   /**
    * The {@link RuleKey} of this issue.
    */
index a98ca7eafd9b3a8a615df185d169429bb5c3f30a..8a088f533c74ecd355a55f5c1f59994e44a956fd 100644 (file)
@@ -22,8 +22,8 @@ package org.sonar.api.batch.sensor.issue;
 import com.google.common.annotations.Beta;
 import org.sonar.api.batch.fs.InputDir;
 import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.rule.Severity;
 import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
 import org.sonar.api.rule.RuleKey;
 
 import javax.annotation.Nullable;
index 280502d23b7209e2ef004f6a0ab59f959543c706..7eee7b189dd65d3eab4d4dc9e5e401aba6e965d5 100644 (file)
@@ -24,6 +24,7 @@ import com.google.common.base.Strings;
 import org.sonar.api.batch.fs.InputDir;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputPath;
+import org.sonar.api.batch.rule.Severity;
 import org.sonar.api.batch.sensor.internal.DefaultStorable;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
 import org.sonar.api.batch.sensor.issue.Issue;
index 098266cff6f25c43388163b52efc160be15fd7e9..41ebf8e7a5b3a25afeba897db1b599af6a5aa959 100644 (file)
@@ -24,8 +24,8 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.batch.fs.internal.DefaultInputDir;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.rule.Severity;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
 import org.sonar.api.rule.RuleKey;
 
 import static org.assertj.core.api.Assertions.assertThat;