]> source.dussan.org Git - sonarqube.git/blob
254547e3063f1c803a8058d804ef884a3074a1f3
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2017 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.server.computation.task.projectanalysis.api.posttask;
21
22 import com.google.common.base.Optional;
23 import java.util.Collection;
24 import java.util.Date;
25 import java.util.Map;
26 import java.util.Set;
27 import javax.annotation.CheckForNull;
28 import javax.annotation.Nullable;
29 import org.sonar.api.ce.posttask.Branch;
30 import org.sonar.api.ce.posttask.CeTask;
31 import org.sonar.api.ce.posttask.PostProjectAnalysisTask;
32 import org.sonar.api.ce.posttask.Project;
33 import org.sonar.api.ce.posttask.QualityGate;
34 import org.sonar.api.ce.posttask.ScannerContext;
35 import org.sonar.api.utils.System2;
36 import org.sonar.api.utils.log.Logger;
37 import org.sonar.api.utils.log.Loggers;
38 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
39 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader;
40 import org.sonar.server.computation.task.projectanalysis.qualitygate.Condition;
41 import org.sonar.server.computation.task.projectanalysis.qualitygate.ConditionStatus;
42 import org.sonar.server.computation.task.projectanalysis.qualitygate.QualityGateHolder;
43 import org.sonar.server.computation.task.projectanalysis.qualitygate.QualityGateStatus;
44 import org.sonar.server.computation.task.projectanalysis.qualitygate.QualityGateStatusHolder;
45 import org.sonar.server.computation.task.step.ComputationStepExecutor;
46
47 import static com.google.common.collect.FluentIterable.from;
48 import static java.lang.String.format;
49 import static java.util.Objects.requireNonNull;
50 import static org.sonar.api.ce.posttask.CeTask.Status.FAILED;
51 import static org.sonar.api.ce.posttask.CeTask.Status.SUCCESS;
52
53 /**
54  * Responsible for calling {@link PostProjectAnalysisTask} implementations (if any).
55  */
56 public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor.Listener {
57   private static final PostProjectAnalysisTask[] NO_POST_PROJECT_ANALYSIS_TASKS = new PostProjectAnalysisTask[0];
58
59   private static final Logger LOG = Loggers.get(PostProjectAnalysisTasksExecutor.class);
60
61   private final org.sonar.ce.queue.CeTask ceTask;
62   private final AnalysisMetadataHolder analysisMetadataHolder;
63   private final QualityGateHolder qualityGateHolder;
64   private final QualityGateStatusHolder qualityGateStatusHolder;
65   private final PostProjectAnalysisTask[] postProjectAnalysisTasks;
66   private final BatchReportReader reportReader;
67   private final System2 system2;
68
69   /**
70    * Constructor used by Pico when there is no {@link PostProjectAnalysisTask} in the container.
71    */
72   public PostProjectAnalysisTasksExecutor(org.sonar.ce.queue.CeTask ceTask,
73     AnalysisMetadataHolder analysisMetadataHolder,
74     QualityGateHolder qualityGateHolder, QualityGateStatusHolder qualityGateStatusHolder,
75     BatchReportReader reportReader, System2 system2) {
76     this(ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader, system2, null);
77   }
78
79   public PostProjectAnalysisTasksExecutor(org.sonar.ce.queue.CeTask ceTask,
80     AnalysisMetadataHolder analysisMetadataHolder,
81     QualityGateHolder qualityGateHolder, QualityGateStatusHolder qualityGateStatusHolder,
82     BatchReportReader reportReader, System2 system2,
83     @Nullable PostProjectAnalysisTask[] postProjectAnalysisTasks) {
84     this.analysisMetadataHolder = analysisMetadataHolder;
85     this.qualityGateHolder = qualityGateHolder;
86     this.qualityGateStatusHolder = qualityGateStatusHolder;
87     this.ceTask = ceTask;
88     this.reportReader = reportReader;
89     this.postProjectAnalysisTasks = postProjectAnalysisTasks == null ? NO_POST_PROJECT_ANALYSIS_TASKS : postProjectAnalysisTasks;
90     this.system2 = system2;
91   }
92
93   @Override
94   public void finished(boolean allStepsExecuted) {
95     if (postProjectAnalysisTasks.length == 0) {
96       return;
97     }
98
99     ProjectAnalysis projectAnalysis = createProjectAnalysis(allStepsExecuted ? SUCCESS : FAILED);
100     for (PostProjectAnalysisTask postProjectAnalysisTask : postProjectAnalysisTasks) {
101       executeTask(projectAnalysis, postProjectAnalysisTask);
102     }
103   }
104
105   private static void executeTask(ProjectAnalysis projectAnalysis, PostProjectAnalysisTask postProjectAnalysisTask) {
106     try {
107       postProjectAnalysisTask.finished(projectAnalysis);
108     } catch (Exception e) {
109       LOG.error("Execution of task " + postProjectAnalysisTask.getClass() + " failed", e);
110     }
111   }
112
113   private ProjectAnalysis createProjectAnalysis(CeTask.Status status) {
114     Long analysisDate = getAnalysisDate();
115
116     return new ProjectAnalysis(
117       new CeTaskImpl(this.ceTask.getUuid(), status),
118       createProject(this.ceTask),
119       analysisDate,
120       analysisDate == null ? system2.now() : analysisDate,
121       ScannerContextImpl.from(reportReader.readContextProperties()),
122       status == SUCCESS ? createQualityGate() : null,
123       createBranch());
124   }
125
126   private static Project createProject(org.sonar.ce.queue.CeTask ceTask) {
127     return new ProjectImpl(
128       ceTask.getComponentUuid(),
129       ceTask.getComponentKey(),
130       ceTask.getComponentName());
131   }
132
133   @CheckForNull
134   private Long getAnalysisDate() {
135     if (this.analysisMetadataHolder.hasAnalysisDateBeenSet()) {
136       return this.analysisMetadataHolder.getAnalysisDate();
137     }
138     return null;
139   }
140
141   @CheckForNull
142   private QualityGateImpl createQualityGate() {
143     Optional<org.sonar.server.computation.task.projectanalysis.qualitygate.QualityGate> qualityGateOptional = this.qualityGateHolder.getQualityGate();
144     if (qualityGateOptional.isPresent()) {
145       org.sonar.server.computation.task.projectanalysis.qualitygate.QualityGate qualityGate = qualityGateOptional.get();
146
147       return new QualityGateImpl(
148         String.valueOf(qualityGate.getId()),
149         qualityGate.getName(),
150         convert(qualityGateStatusHolder.getStatus()),
151         convert(qualityGate.getConditions(), qualityGateStatusHolder.getStatusPerConditions()));
152     }
153     return null;
154   }
155
156   @CheckForNull
157   private BranchImpl createBranch() {
158     java.util.Optional<org.sonar.server.computation.task.projectanalysis.analysis.Branch> analysisBranchOpt = analysisMetadataHolder.getBranch();
159     if (analysisBranchOpt.isPresent() && !analysisBranchOpt.get().isLegacyFeature()) {
160       org.sonar.server.computation.task.projectanalysis.analysis.Branch branch = analysisBranchOpt.get();
161       return new BranchImpl(branch.isMain(), branch.getName().orElse(null), Branch.Type.valueOf(branch.getType().name()));
162     }
163     return null;
164   }
165
166   private static QualityGate.Status convert(QualityGateStatus status) {
167     switch (status) {
168       case OK:
169         return QualityGate.Status.OK;
170       case WARN:
171         return QualityGate.Status.WARN;
172       case ERROR:
173         return QualityGate.Status.ERROR;
174       default:
175         throw new IllegalArgumentException(format(
176           "Unsupported value '%s' of QualityGateStatus can not be converted to QualityGate.Status",
177           status));
178     }
179   }
180
181   private static Collection<QualityGate.Condition> convert(Set<Condition> conditions, Map<Condition, ConditionStatus> statusPerConditions) {
182     return from(conditions)
183       .transform(new ConditionToCondition(statusPerConditions))
184       .toList();
185   }
186
187   private static class ProjectAnalysis implements PostProjectAnalysisTask.ProjectAnalysis {
188     private final CeTask ceTask;
189     private final Project project;
190     @Nullable
191     private final Long analysisDate;
192     private final long date;
193     private final ScannerContext scannerContext;
194     @Nullable
195     private final QualityGate qualityGate;
196     @Nullable
197     private final Branch branch;
198
199     private ProjectAnalysis(CeTask ceTask, Project project,
200       @Nullable Long analysisDate, long date,
201       ScannerContext scannerContext, @Nullable QualityGate qualityGate, @Nullable Branch branch) {
202       this.ceTask = requireNonNull(ceTask, "ceTask can not be null");
203       this.project = requireNonNull(project, "project can not be null");
204       this.analysisDate = analysisDate;
205       this.date = date;
206       this.scannerContext = requireNonNull(scannerContext, "scannerContext can not be null");
207       this.qualityGate = qualityGate;
208       this.branch = branch;
209     }
210
211     @Override
212     public CeTask getCeTask() {
213       return ceTask;
214     }
215
216     @Override
217     public Project getProject() {
218       return project;
219     }
220
221     @Override
222     public java.util.Optional<Branch> getBranch() {
223       return java.util.Optional.ofNullable(branch);
224     }
225
226     @Override
227     @CheckForNull
228     public QualityGate getQualityGate() {
229       return qualityGate;
230     }
231
232     @Override
233     public Date getDate() {
234       return new Date(date);
235     }
236
237     @Override
238     public java.util.Optional<Date> getAnalysisDate() {
239       if (analysisDate == null) {
240         return java.util.Optional.empty();
241       }
242       return java.util.Optional.of(new Date(analysisDate));
243     }
244
245     @Override
246     public ScannerContext getScannerContext() {
247       return scannerContext;
248     }
249
250     @Override
251     public String toString() {
252       return "ProjectAnalysis{" +
253         "ceTask=" + ceTask +
254         ", project=" + project +
255         ", analysisDate=" + analysisDate +
256         ", date=" + date +
257         ", scannerContext=" + scannerContext +
258         ", qualityGate=" + qualityGate +
259         '}';
260     }
261   }
262
263 }