001 /*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * SonarQube is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
019 */
020 package org.sonar.batch.phases;
021
022 import com.google.common.collect.Lists;
023 import org.slf4j.Logger;
024 import org.slf4j.LoggerFactory;
025 import org.sonar.api.batch.SensorContext;
026 import org.sonar.api.resources.Project;
027 import org.sonar.batch.events.BatchStepEvent;
028 import org.sonar.batch.events.EventBus;
029 import org.sonar.batch.index.DefaultIndex;
030 import org.sonar.batch.index.PersistenceManager;
031 import org.sonar.batch.index.ScanPersister;
032 import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
033 import org.sonar.batch.rule.QProfileVerifier;
034 import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
035 import org.sonar.batch.scan.filesystem.FileSystemLogger;
036 import org.sonar.batch.scan.maven.MavenPluginsConfigurator;
037 import org.sonar.batch.scan.report.JsonReport;
038
039 import java.util.Collection;
040
041 public final class PhaseExecutor {
042
043 public static final Logger LOGGER = LoggerFactory.getLogger(PhaseExecutor.class);
044
045 private final EventBus eventBus;
046 private final Phases phases;
047 private final DecoratorsExecutor decoratorsExecutor;
048 private final MavenPluginsConfigurator mavenPluginsConfigurator;
049 private final PostJobsExecutor postJobsExecutor;
050 private final InitializersExecutor initializersExecutor;
051 private final SensorsExecutor sensorsExecutor;
052 private final UpdateStatusJob updateStatusJob;
053 private final PersistenceManager persistenceManager;
054 private final SensorContext sensorContext;
055 private final DefaultIndex index;
056 private final ProjectInitializer pi;
057 private final ScanPersister[] persisters;
058 private final FileSystemLogger fsLogger;
059 private final JsonReport jsonReport;
060 private final DefaultModuleFileSystem fs;
061 private final QProfileVerifier profileVerifier;
062 private final IssueExclusionsLoader issueExclusionsLoader;
063
064 public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor,
065 MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
066 PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
067 PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
068 EventBus eventBus, UpdateStatusJob updateStatusJob, ProjectInitializer pi,
069 ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
070 IssueExclusionsLoader issueExclusionsLoader) {
071 this.phases = phases;
072 this.decoratorsExecutor = decoratorsExecutor;
073 this.mavenPluginsConfigurator = mavenPluginsConfigurator;
074 this.postJobsExecutor = postJobsExecutor;
075 this.initializersExecutor = initializersExecutor;
076 this.sensorsExecutor = sensorsExecutor;
077 this.persistenceManager = persistenceManager;
078 this.sensorContext = sensorContext;
079 this.index = index;
080 this.eventBus = eventBus;
081 this.updateStatusJob = updateStatusJob;
082 this.pi = pi;
083 this.persisters = persisters;
084 this.fsLogger = fsLogger;
085 this.jsonReport = jsonReport;
086 this.fs = fs;
087 this.profileVerifier = profileVerifier;
088 this.issueExclusionsLoader = issueExclusionsLoader;
089 }
090
091 public static Collection<Class> getPhaseClasses() {
092 return Lists.<Class>newArrayList(DecoratorsExecutor.class, MavenPluginsConfigurator.class,
093 PostJobsExecutor.class, SensorsExecutor.class,
094 InitializersExecutor.class, ProjectInitializer.class, UpdateStatusJob.class);
095 }
096
097 /**
098 * Executed on each module
099 */
100 public void execute(Project module) {
101 pi.execute(module);
102
103 eventBus.fireEvent(new ProjectAnalysisEvent(module, true));
104
105 executeMavenPhase(module);
106
107 executeInitializersPhase();
108
109 if (phases.isEnabled(Phases.Phase.SENSOR)) {
110 // Index and lock the filesystem
111 fs.index();
112
113 // Log detected languages and their profiles after FS is indexed and languages detected
114 profileVerifier.execute();
115
116 // Initialize issue exclusions
117 issueExclusionsLoader.execute();
118
119 sensorsExecutor.execute(sensorContext);
120 }
121
122 if (phases.isEnabled(Phases.Phase.DECORATOR)) {
123 decoratorsExecutor.execute();
124 }
125
126 if (module.isRoot()) {
127 jsonReport.execute();
128
129 executePersisters();
130 updateStatusJob();
131 if (phases.isEnabled(Phases.Phase.POSTJOB)) {
132 postJobsExecutor.execute(sensorContext);
133 }
134 }
135 cleanMemory();
136 eventBus.fireEvent(new ProjectAnalysisEvent(module, false));
137 }
138
139 private void executePersisters() {
140 LOGGER.info("Store results in database");
141 eventBus.fireEvent(new PersistersPhaseEvent(Lists.newArrayList(persisters), true));
142 for (ScanPersister persister : persisters) {
143 LOGGER.debug("Execute {}", persister.getClass().getName());
144 eventBus.fireEvent(new PersisterExecutionEvent(persister, true));
145 persister.persist();
146 eventBus.fireEvent(new PersisterExecutionEvent(persister, false));
147 }
148
149 eventBus.fireEvent(new PersistersPhaseEvent(Lists.newArrayList(persisters), false));
150 }
151
152 private void updateStatusJob() {
153 if (updateStatusJob != null) {
154 String stepName = "Update status job";
155 eventBus.fireEvent(new BatchStepEvent(stepName, true));
156 this.updateStatusJob.execute();
157 eventBus.fireEvent(new BatchStepEvent(stepName, false));
158 }
159 }
160
161 private void executeInitializersPhase() {
162 if (phases.isEnabled(Phases.Phase.INIT)) {
163 initializersExecutor.execute();
164 fsLogger.log();
165 }
166 }
167
168 private void executeMavenPhase(Project module) {
169 if (phases.isEnabled(Phases.Phase.MAVEN)) {
170 eventBus.fireEvent(new MavenPhaseEvent(true));
171 mavenPluginsConfigurator.execute(module);
172 eventBus.fireEvent(new MavenPhaseEvent(false));
173 }
174 }
175
176 private void cleanMemory() {
177 String cleanMemory = "Clean memory";
178 eventBus.fireEvent(new BatchStepEvent(cleanMemory, true));
179 persistenceManager.clear();
180 index.clear();
181 eventBus.fireEvent(new BatchStepEvent(cleanMemory, false));
182 }
183 }