1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.invoker;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.Reader;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import org.apache.maven.plugin.MojoFailureException;
30 import org.apache.maven.plugin.logging.Log;
31 import org.apache.maven.plugins.invoker.model.BuildJob;
32 import org.codehaus.plexus.util.IOUtil;
33
34 import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
35
36
37
38
39
40
41 class InvokerSession {
42 private static final String SEPARATOR =
43 buffer().strong("-------------------------------------------------").build();
44
45 private List<BuildJob> buildJobs;
46
47 private List<BuildJob> failedJobs;
48
49 private List<BuildJob> errorJobs;
50
51 private List<BuildJob> successfulJobs;
52
53 private List<BuildJob> skippedJobs;
54
55
56
57
58 InvokerSession() {
59 buildJobs = new ArrayList<>();
60 }
61
62
63
64
65
66
67 InvokerSession(List<BuildJob> buildJobs) {
68 this.buildJobs = new ArrayList<>(buildJobs);
69 }
70
71
72
73
74
75
76 public void addJob(BuildJob buildJob) {
77 buildJobs.add(buildJob);
78
79 resetStats();
80 }
81
82
83
84
85
86
87 public void setJobs(List<? extends BuildJob> buildJobs) {
88 this.buildJobs = new ArrayList<>(buildJobs);
89
90 resetStats();
91 }
92
93
94
95
96
97
98 public List<BuildJob> getJobs() {
99 return buildJobs;
100 }
101
102
103
104
105
106
107 public List<BuildJob> getSuccessfulJobs() {
108 updateStats();
109
110 return successfulJobs;
111 }
112
113
114
115
116
117
118 public List<BuildJob> getFailedJobs() {
119 updateStats();
120
121 return failedJobs;
122 }
123
124
125
126
127
128
129 public List<BuildJob> getErrorJobs() {
130 updateStats();
131
132 return errorJobs;
133 }
134
135
136
137
138
139
140 public List<BuildJob> getSkippedJobs() {
141 updateStats();
142
143 return skippedJobs;
144 }
145
146 private void resetStats() {
147 successfulJobs = null;
148 failedJobs = null;
149 skippedJobs = null;
150 errorJobs = null;
151 }
152
153 private void updateStats() {
154 if (successfulJobs != null && skippedJobs != null && failedJobs != null && errorJobs != null) {
155 return;
156 }
157
158 successfulJobs = new ArrayList<>();
159 failedJobs = new ArrayList<>();
160 skippedJobs = new ArrayList<>();
161 errorJobs = new ArrayList<>();
162
163 for (BuildJob buildJob : buildJobs) {
164 if (BuildJob.Result.SUCCESS.equals(buildJob.getResult())) {
165 successfulJobs.add(buildJob);
166 } else if (BuildJob.Result.SKIPPED.equals(buildJob.getResult())) {
167 skippedJobs.add(buildJob);
168 } else if (BuildJob.Result.ERROR.equals(buildJob.getResult())) {
169 errorJobs.add(buildJob);
170 } else if (buildJob.getResult() != null) {
171 failedJobs.add(buildJob);
172 }
173 }
174 }
175
176
177
178
179
180
181
182 public void logSummary(Log logger, boolean ignoreFailures) {
183 updateStats();
184
185 logger.info(SEPARATOR);
186 logger.info("Build Summary:");
187 logger.info(" Passed: " + successfulJobs.size()
188 + ", Failed: " + failedJobs.size()
189 + ", Errors: " + errorJobs.size()
190 + ", Skipped: " + skippedJobs.size());
191 logger.info(SEPARATOR);
192
193 logBuildJobList(logger, ignoreFailures, "The following builds failed:", failedJobs);
194 logBuildJobList(logger, ignoreFailures, "The following builds finished with error:", errorJobs);
195 logBuildJobList(logger, true, "The following builds were skipped:", skippedJobs);
196 }
197
198 public void logFailedBuildLog(Log logger, boolean ignoreFailures) throws MojoFailureException {
199 updateStats();
200
201 List<BuildJob> jobToLogs = new ArrayList<>(failedJobs);
202 jobToLogs.addAll(errorJobs);
203
204 for (BuildJob buildJob : jobToLogs) {
205 Path buildLogPath = buildJob.getBuildlog() != null ? new File(buildJob.getBuildlog()).toPath() : null;
206 if (buildLogPath != null && Files.exists(buildLogPath)) {
207 try {
208
209
210 StringBuilder buildLogMessage = new StringBuilder();
211 buildLogMessage.append(System.lineSeparator());
212 buildLogMessage.append(System.lineSeparator());
213 buildLogMessage
214 .append("*** begin build.log for: ")
215 .append(buildJob.getProject())
216 .append(" ***")
217 .append(System.lineSeparator());
218
219 if (buildJob.getExecutionCount() > 1) {
220
221 for (int executionCount = 1;
222 executionCount <= buildJob.getExecutionCount() - 1;
223 executionCount++) {
224
225 buildLogMessage
226 .append("*** build.log for execution: ")
227 .append(executionCount)
228 .append(" ***")
229 .append(System.lineSeparator());
230 Path path = buildLogPath
231 .getParent()
232 .resolve(buildLogPath.getFileName().toString() + "." + executionCount);
233 appendLogToMessage(path, buildLogMessage);
234 }
235
236 buildLogMessage
237 .append("*** build.log for execution: ")
238 .append(buildJob.getExecutionCount())
239 .append(" ***")
240 .append(System.lineSeparator());
241 }
242
243 appendLogToMessage(buildLogPath, buildLogMessage);
244
245 buildLogMessage
246 .append("*** end build.log for: ")
247 .append(buildJob.getProject())
248 .append(" ***")
249 .append(System.lineSeparator());
250
251 logWithLevel(logger, ignoreFailures, SEPARATOR);
252 logWithLevel(logger, ignoreFailures, buildLogMessage.toString());
253 logWithLevel(logger, ignoreFailures, SEPARATOR);
254 logWithLevel(logger, ignoreFailures, "");
255
256 } catch (IOException e) {
257 throw new MojoFailureException(e.getMessage(), e);
258 }
259 }
260 }
261 }
262
263 private void appendLogToMessage(Path logPath, StringBuilder buildLogMessage) throws IOException {
264 if (logPath != null && Files.exists(logPath)) {
265 try (Reader buildLogReader = Files.newBufferedReader(logPath)) {
266 buildLogMessage.append(IOUtil.toString(buildLogReader));
267 }
268 }
269 }
270
271
272
273
274
275
276
277
278 public void handleFailures(Log logger, boolean ignoreFailures) throws MojoFailureException {
279 updateStats();
280
281 if (!failedJobs.isEmpty()) {
282 String message = failedJobs.size() + " build" + (failedJobs.size() == 1 ? "" : "s") + " failed.";
283
284 if (ignoreFailures) {
285 logger.warn("Ignoring that " + message);
286 } else {
287 throw new MojoFailureException(message + " See console output above for details.");
288 }
289 }
290
291 if (!errorJobs.isEmpty()) {
292 String message = errorJobs.size() + " build" + (errorJobs.size() == 1 ? "" : "s") + " in error.";
293
294 if (ignoreFailures) {
295 logger.warn("Ignoring that " + message);
296 } else {
297 throw new MojoFailureException(message + " See console output above for details.");
298 }
299 }
300 }
301
302
303
304
305
306
307
308
309 private void logBuildJobList(Log logger, boolean warn, String header, List<BuildJob> buildJobs) {
310 if (buildJobs.isEmpty()) {
311 return;
312 }
313
314 logWithLevel(logger, warn, header);
315
316 for (BuildJob buildJob : buildJobs) {
317 logWithLevel(logger, warn, "* " + buildJob.getProject());
318 }
319
320 logger.info(SEPARATOR);
321 }
322
323
324
325
326
327
328
329
330 private void logWithLevel(Log logger, boolean warn, String message) {
331
332 if (warn) {
333 logger.warn(message);
334 } else {
335 logger.error(message);
336 }
337 }
338 }