From 45ac9c01785b4410fa82c498d89c56b9ae4a16ea Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Fri, 15 Mar 2013 12:38:52 +0100 Subject: [PATCH] SONAR-4069 ability to configure the phases to be executed --- .../org/sonar/batch/phases/PhaseExecutor.java | 133 ++++++++++++++++++ .../java/org/sonar/batch/phases/Phases.java | 102 ++------------ .../sonar/batch/scan/ModuleScanContainer.java | 8 +- .../java/org/sonar/batch/scan/ScanTask.java | 8 +- .../sonar/batch/phases/PhaseExecutorTest.java | 33 +++++ .../org/sonar/batch/phases/PhasesTest.java | 30 +++- .../org/sonar/batch/scan/ScanTaskTest.java | 14 ++ 7 files changed, 230 insertions(+), 98 deletions(-) create mode 100644 sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java create mode 100644 sonar-batch/src/test/java/org/sonar/batch/phases/PhaseExecutorTest.java diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java new file mode 100644 index 00000000000..49091a2fb25 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java @@ -0,0 +1,133 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.batch.phases; + +import com.google.common.collect.Lists; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.resources.Project; +import org.sonar.batch.events.EventBus; +import org.sonar.batch.index.DefaultIndex; +import org.sonar.batch.index.PersistenceManager; +import org.sonar.batch.scan.filesystem.FileSystemLogger; +import org.sonar.batch.scan.maven.MavenPhaseExecutor; +import org.sonar.batch.scan.maven.MavenPluginsConfigurator; +import org.sonar.core.component.ScanGraphStore; + +import java.util.Collection; + +public final class PhaseExecutor { + + public static Collection getPhaseClasses() { + return Lists.newArrayList(DecoratorsExecutor.class, MavenPhaseExecutor.class, MavenPluginsConfigurator.class, + PostJobsExecutor.class, SensorsExecutor.class, + InitializersExecutor.class, ProjectInitializer.class, UpdateStatusJob.class); + } + + private EventBus eventBus; + private Phases phases; + private DecoratorsExecutor decoratorsExecutor; + private MavenPhaseExecutor mavenPhaseExecutor; + private MavenPluginsConfigurator mavenPluginsConfigurator; + private PostJobsExecutor postJobsExecutor; + private InitializersExecutor initializersExecutor; + private SensorsExecutor sensorsExecutor; + private UpdateStatusJob updateStatusJob; + private PersistenceManager persistenceManager; + private SensorContext sensorContext; + private DefaultIndex index; + private ProjectInitializer pi; + private ScanGraphStore graphStorage; + private FileSystemLogger fsLogger; + + public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor, + MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor, + PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, + PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index, + EventBus eventBus, UpdateStatusJob updateStatusJob, ProjectInitializer pi, + ScanGraphStore graphStorage, FileSystemLogger fsLogger) { + this.phases = phases; + this.decoratorsExecutor = decoratorsExecutor; + this.mavenPhaseExecutor = mavenPhaseExecutor; + this.mavenPluginsConfigurator = mavenPluginsConfigurator; + this.postJobsExecutor = postJobsExecutor; + this.initializersExecutor = initializersExecutor; + this.sensorsExecutor = sensorsExecutor; + this.persistenceManager = persistenceManager; + this.sensorContext = sensorContext; + this.index = index; + this.eventBus = eventBus; + this.updateStatusJob = updateStatusJob; + this.pi = pi; + this.graphStorage = graphStorage; + this.fsLogger = fsLogger; + } + + public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor, + MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor, + PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, + PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index, + EventBus eventBus, ProjectInitializer pi, ScanGraphStore graphStorage, FileSystemLogger fsLogger) { + this(phases, decoratorsExecutor, mavenPhaseExecutor, mavenPluginsConfigurator, initializersExecutor, postJobsExecutor, + sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null, pi, graphStorage, fsLogger); + } + + /** + * Executed on each module + */ + public void execute(Project module) { + pi.execute(module); + eventBus.fireEvent(new ProjectAnalysisEvent(module, true)); + if (phases.isEnabled(Phases.Phase.MAVEN)) { + mavenPluginsConfigurator.execute(module); + mavenPhaseExecutor.execute(module); + } + if (phases.isEnabled(Phases.Phase.INIT)) { + initializersExecutor.execute(); + fsLogger.log(); + } + + persistenceManager.setDelayedMode(true); + if (phases.isEnabled(Phases.Phase.SENSOR)) { + sensorsExecutor.execute(sensorContext); + } + if (phases.isEnabled(Phases.Phase.DECORATOR)) { + decoratorsExecutor.execute(); + } + persistenceManager.dump(); + persistenceManager.setDelayedMode(false); + + if (module.isRoot()) { + graphStorage.save(); + if (updateStatusJob != null) { + updateStatusJob.execute(); + } + if (phases.isEnabled(Phases.Phase.POSTJOB)) { + postJobsExecutor.execute(sensorContext); + } + } + cleanMemory(); + eventBus.fireEvent(new ProjectAnalysisEvent(module, false)); + } + + private void cleanMemory() { + persistenceManager.clear(); + index.clear(); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java b/sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java index 2ad607cd0dc..2ccb0da0d05 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java +++ b/sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java @@ -19,103 +19,29 @@ */ package org.sonar.batch.phases; -import com.google.common.collect.Lists; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.resources.Project; -import org.sonar.batch.events.EventBus; -import org.sonar.batch.index.DefaultIndex; -import org.sonar.batch.index.PersistenceManager; -import org.sonar.batch.scan.filesystem.FileSystemLogger; -import org.sonar.batch.scan.maven.MavenPhaseExecutor; -import org.sonar.batch.scan.maven.MavenPluginsConfigurator; -import org.sonar.core.component.ScanGraphStore; +import com.google.common.collect.Sets; -import java.util.Collection; +import java.util.Arrays; +import java.util.Set; -public final class Phases { +public class Phases { - public static Collection getPhaseClasses() { - return Lists.newArrayList(DecoratorsExecutor.class, MavenPhaseExecutor.class, MavenPluginsConfigurator.class, - PostJobsExecutor.class, SensorsExecutor.class, - InitializersExecutor.class, ProjectInitializer.class, UpdateStatusJob.class); + public static enum Phase { + MAVEN, INIT, SENSOR, DECORATOR, POSTJOB } - private EventBus eventBus; - private DecoratorsExecutor decoratorsExecutor; - private MavenPhaseExecutor mavenPhaseExecutor; - private MavenPluginsConfigurator mavenPluginsConfigurator; - private PostJobsExecutor postJobsExecutor; - private InitializersExecutor initializersExecutor; - private SensorsExecutor sensorsExecutor; - private UpdateStatusJob updateStatusJob; - private PersistenceManager persistenceManager; - private SensorContext sensorContext; - private DefaultIndex index; - private ProjectInitializer pi; - private ScanGraphStore graphStorage; - private FileSystemLogger fsLogger; + private final Set enabled = Sets.newHashSet(); - public Phases(DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor, - MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor, - PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, - PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index, - EventBus eventBus, UpdateStatusJob updateStatusJob, ProjectInitializer pi, - ScanGraphStore graphStorage, FileSystemLogger fsLogger) { - this.decoratorsExecutor = decoratorsExecutor; - this.mavenPhaseExecutor = mavenPhaseExecutor; - this.mavenPluginsConfigurator = mavenPluginsConfigurator; - this.postJobsExecutor = postJobsExecutor; - this.initializersExecutor = initializersExecutor; - this.sensorsExecutor = sensorsExecutor; - this.persistenceManager = persistenceManager; - this.sensorContext = sensorContext; - this.index = index; - this.eventBus = eventBus; - this.updateStatusJob = updateStatusJob; - this.pi = pi; - this.graphStorage = graphStorage; - this.fsLogger = fsLogger; + public Phases enable(Phase... phases) { + enabled.addAll(Arrays.asList(phases)); + return this; } - public Phases(DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor, - MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor, - PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, - PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index, - EventBus eventBus, ProjectInitializer pi, ScanGraphStore graphStorage, FileSystemLogger fsLogger) { - this(decoratorsExecutor, mavenPhaseExecutor, mavenPluginsConfigurator, initializersExecutor, postJobsExecutor, - sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null, pi, graphStorage, fsLogger); + public boolean isEnabled(Phase phase) { + return enabled.contains(phase); } - /** - * Executed on each module - */ - public void execute(Project module) { - pi.execute(module); - eventBus.fireEvent(new ProjectAnalysisEvent(module, true)); - mavenPluginsConfigurator.execute(module); - mavenPhaseExecutor.execute(module); - initializersExecutor.execute(); - fsLogger.log(); - - persistenceManager.setDelayedMode(true); - sensorsExecutor.execute(sensorContext); - decoratorsExecutor.execute(); - persistenceManager.dump(); - persistenceManager.setDelayedMode(false); - - if (module.isRoot()) { - graphStorage.save(); - if (updateStatusJob != null) { - updateStatusJob.execute(); - } - postJobsExecutor.execute(sensorContext); - } - cleanMemory(); - eventBus.fireEvent(new ProjectAnalysisEvent(module, false)); - } - - private void cleanMemory() { - persistenceManager.clear(); - index.clear(); + public boolean isFullyEnabled() { + return enabled.containsAll(Arrays.asList(Phase.values())); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java index 0e001d1c3b7..8fdb47f9668 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java @@ -46,7 +46,7 @@ import org.sonar.batch.events.EventBus; import org.sonar.batch.index.DefaultIndex; import org.sonar.batch.index.ResourcePersister; import org.sonar.batch.local.DryRunExporter; -import org.sonar.batch.phases.Phases; +import org.sonar.batch.phases.PhaseExecutor; import org.sonar.batch.phases.PhasesTimeProfiler; import org.sonar.batch.scan.filesystem.DeprecatedFileSystemAdapter; import org.sonar.batch.scan.filesystem.ExclusionFilters; @@ -83,10 +83,10 @@ public class ModuleScanContainer extends ComponentContainer { add( EventBus.class, - Phases.class, + PhaseExecutor.class, PhasesTimeProfiler.class, UnsupportedProperties.class, - Phases.getPhaseClasses(), + PhaseExecutor.getPhaseClasses(), moduleDefinition.getContainerExtensions(), // TODO move outside project, but not possible yet because of dependency of project settings (cf plsql) @@ -140,7 +140,7 @@ public class ModuleScanContainer extends ComponentContainer { getComponentByType(ViolationFilters.class), getComponentByType(RulesProfile.class)); - getComponentByType(Phases.class).execute(module); + getComponentByType(PhaseExecutor.class).execute(module); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java index 01e6ad7b9b9..a6df4b096be 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java @@ -24,9 +24,9 @@ import org.sonar.api.platform.ComponentContainer; import org.sonar.api.task.Task; import org.sonar.api.task.TaskDefinition; import org.sonar.batch.bootstrap.TaskContainer; +import org.sonar.batch.phases.Phases; public class ScanTask implements Task { - public static final TaskDefinition DEFINITION = TaskDefinition.builder() .description("Scan project") .key(CoreProperties.SCAN_TASK) @@ -40,7 +40,11 @@ public class ScanTask implements Task { } public void execute() { - new ProjectScanContainer(taskContainer).execute(); + scan(new ProjectScanContainer(taskContainer)); } + void scan(ComponentContainer scanContainer) { + scanContainer.add(new Phases().enable(Phases.Phase.values())); + scanContainer.execute(); + } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/phases/PhaseExecutorTest.java b/sonar-batch/src/test/java/org/sonar/batch/phases/PhaseExecutorTest.java new file mode 100644 index 00000000000..47784cb25b1 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/phases/PhaseExecutorTest.java @@ -0,0 +1,33 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.batch.phases; + +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; + +public class PhaseExecutorTest { + + @Test + public void shouldDefinePhaseClasses() { + assertThat(PhaseExecutor.getPhaseClasses().size()).isGreaterThan(4); + } + +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/phases/PhasesTest.java b/sonar-batch/src/test/java/org/sonar/batch/phases/PhasesTest.java index 0e4d0157a7a..c7d4a558819 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/phases/PhasesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/phases/PhasesTest.java @@ -21,14 +21,36 @@ package org.sonar.batch.phases; import org.junit.Test; -import static org.hamcrest.number.OrderingComparisons.greaterThan; -import static org.junit.Assert.assertThat; +import static org.fest.assertions.Assertions.assertThat; public class PhasesTest { + @Test + public void no_phase_should_be_enabled_by_default() { + Phases phases = new Phases(); + assertThat(phases.isEnabled(Phases.Phase.DECORATOR)).isFalse(); + } @Test - public void shouldDefinePhaseClasses() { - assertThat(Phases.getPhaseClasses().size(), greaterThan(4)); + public void phase_should_be_enabled() { + Phases phases = new Phases(); + phases.enable(Phases.Phase.SENSOR, Phases.Phase.DECORATOR); + + assertThat(phases.isEnabled(Phases.Phase.DECORATOR)).isTrue(); + assertThat(phases.isEnabled(Phases.Phase.SENSOR)).isTrue(); + assertThat(phases.isEnabled(Phases.Phase.POSTJOB)).isFalse(); + assertThat(phases.isFullyEnabled()).isFalse(); } + @Test + public void all_phases_should_be_enabled() { + Phases phases = new Phases(); + phases.enable(Phases.Phase.values()); + + assertThat(phases.isEnabled(Phases.Phase.INIT)).isTrue(); + assertThat(phases.isEnabled(Phases.Phase.MAVEN)).isTrue(); + assertThat(phases.isEnabled(Phases.Phase.DECORATOR)).isTrue(); + assertThat(phases.isEnabled(Phases.Phase.SENSOR)).isTrue(); + assertThat(phases.isEnabled(Phases.Phase.POSTJOB)).isTrue(); + assertThat(phases.isFullyEnabled()).isTrue(); + } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ScanTaskTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ScanTaskTest.java index fcf4c52244a..7f5b71697f4 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/ScanTaskTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ScanTaskTest.java @@ -21,8 +21,12 @@ package org.sonar.batch.scan; import org.junit.Test; import org.sonar.api.CoreProperties; +import org.sonar.api.platform.ComponentContainer; +import org.sonar.batch.bootstrap.TaskContainer; +import org.sonar.batch.phases.Phases; import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; public class ScanTaskTest { @Test @@ -30,4 +34,14 @@ public class ScanTaskTest { assertThat(ScanTask.DEFINITION).isNotNull(); assertThat(ScanTask.DEFINITION.key()).isEqualTo(CoreProperties.SCAN_TASK); } + + @Test + public void should_enable_all_phases() { + ScanTask task = new ScanTask(mock(TaskContainer.class)); + ComponentContainer projectScanContainer = new ComponentContainer(); + task.scan(projectScanContainer); + + Phases phases = projectScanContainer.getComponentByType(Phases.class); + assertThat(phases.isFullyEnabled()).isTrue(); + } } -- 2.39.5