1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.exception;
20
21 import javax.inject.Named;
22 import javax.inject.Singleton;
23
24 import java.io.IOException;
25 import java.net.ConnectException;
26 import java.net.UnknownHostException;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.IdentityHashMap;
30 import java.util.List;
31 import java.util.Set;
32
33 import org.apache.maven.api.plugin.MojoException;
34 import org.apache.maven.lifecycle.LifecycleExecutionException;
35 import org.apache.maven.model.building.ModelProblem;
36 import org.apache.maven.model.building.ModelProblemUtils;
37 import org.apache.maven.plugin.AbstractMojoExecutionException;
38 import org.apache.maven.plugin.MojoExecutionException;
39 import org.apache.maven.plugin.PluginContainerException;
40 import org.apache.maven.plugin.PluginExecutionException;
41 import org.apache.maven.project.ProjectBuildingException;
42 import org.apache.maven.project.ProjectBuildingResult;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 @Named
93 @Singleton
94 public class DefaultExceptionHandler implements ExceptionHandler {
95 @Override
96 public ExceptionSummary handleException(Throwable exception) {
97 return handle("", exception);
98 }
99
100 private ExceptionSummary handle(String message, Throwable exception) {
101 String reference = getReference(Collections.newSetFromMap(new IdentityHashMap<>()), exception);
102
103 List<ExceptionSummary> children = null;
104
105 if (exception instanceof ProjectBuildingException) {
106 List<ProjectBuildingResult> results = ((ProjectBuildingException) exception).getResults();
107
108 children = new ArrayList<>();
109
110 for (ProjectBuildingResult result : results) {
111 ExceptionSummary child = handle(result);
112 if (child != null) {
113 children.add(child);
114 }
115 }
116
117 message = "The build could not read " + children.size() + " project" + (children.size() == 1 ? "" : "s");
118 } else {
119 message = getMessage(message, exception);
120 }
121
122 return new ExceptionSummary(exception, message, reference, children);
123 }
124
125 private ExceptionSummary handle(ProjectBuildingResult result) {
126 List<ExceptionSummary> children = new ArrayList<>();
127
128 for (ModelProblem problem : result.getProblems()) {
129 ExceptionSummary child = handle(problem, result.getProjectId());
130 if (child != null) {
131 children.add(child);
132 }
133 }
134
135 if (children.isEmpty()) {
136 return null;
137 }
138
139 String message = System.lineSeparator()
140 + "The project " + (result.getProjectId().isEmpty() ? "" : result.getProjectId() + " ")
141 + "(" + result.getPomFile() + ") has "
142 + children.size() + " error" + (children.size() == 1 ? "" : "s");
143
144 return new ExceptionSummary(null, message, null, children);
145 }
146
147 private ExceptionSummary handle(ModelProblem problem, String projectId) {
148 if (ModelProblem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
149 String message = problem.getMessage();
150
151 String location = ModelProblemUtils.formatLocation(problem, projectId);
152
153 if (!location.isEmpty()) {
154 message += " @ " + location;
155 }
156
157 return handle(message, problem.getException());
158 } else {
159 return null;
160 }
161 }
162
163 private String getReference(Set<Throwable> dejaVu, Throwable exception) {
164 String reference = "";
165 if (!dejaVu.add(exception)) {
166 return reference;
167 }
168
169 if (exception != null) {
170 if (exception instanceof MojoExecutionException) {
171 reference = MojoExecutionException.class.getSimpleName();
172
173 Throwable cause = exception.getCause();
174 if (cause instanceof IOException) {
175 cause = cause.getCause();
176 if (cause instanceof ConnectException) {
177 reference = ConnectException.class.getSimpleName();
178 }
179 }
180 } else if (exception instanceof LinkageError) {
181 reference = LinkageError.class.getSimpleName();
182 } else if (exception instanceof PluginExecutionException) {
183 Throwable cause = exception.getCause();
184
185 if (cause instanceof PluginContainerException) {
186 Throwable cause2 = cause.getCause();
187
188 if (cause2 instanceof NoClassDefFoundError) {
189 String message = cause2.getMessage();
190 if (message != null && message.contains("org/sonatype/aether/")) {
191 reference = "AetherClassNotFound";
192 }
193 }
194 }
195
196 if (reference == null || reference.isEmpty()) {
197 reference = getReference(dejaVu, cause);
198 }
199
200 if (reference == null || reference.isEmpty()) {
201 reference = exception.getClass().getSimpleName();
202 }
203 } else if (exception instanceof LifecycleExecutionException) {
204 reference = getReference(dejaVu, exception.getCause());
205 } else if (isNoteworthyException(exception)) {
206 reference = exception.getClass().getSimpleName();
207 }
208 }
209
210 if ((reference != null && !reference.isEmpty()) && !reference.startsWith("http:")) {
211 reference = "http://cwiki.apache.org/confluence/display/MAVEN/" + reference;
212 }
213
214 return reference;
215 }
216
217 private boolean isNoteworthyException(Throwable exception) {
218 if (exception == null) {
219 return false;
220 } else if (exception instanceof Error) {
221 return true;
222 } else if (exception instanceof RuntimeException) {
223 return false;
224 } else {
225 return !exception.getClass().getName().startsWith("java");
226 }
227 }
228
229 private String getMessage(String message, Throwable exception) {
230 String fullMessage = (message != null) ? message : "";
231
232
233 Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
234 for (Throwable t = exception; t != null && t != t.getCause(); t = t.getCause()) {
235 String exceptionMessage = t.getMessage();
236 String longMessage = null;
237
238 if (t instanceof AbstractMojoExecutionException) {
239 longMessage = ((AbstractMojoExecutionException) t).getLongMessage();
240 } else if (t instanceof MojoException) {
241 longMessage = ((MojoException) t).getLongMessage();
242 }
243
244 if (longMessage != null && !longMessage.isEmpty()) {
245 if ((exceptionMessage == null || exceptionMessage.isEmpty())
246 || longMessage.contains(exceptionMessage)) {
247 exceptionMessage = longMessage;
248 } else if (!exceptionMessage.contains(longMessage)) {
249 exceptionMessage = join(exceptionMessage, System.lineSeparator() + longMessage);
250 }
251 }
252
253 if (exceptionMessage == null || exceptionMessage.isEmpty()) {
254 exceptionMessage = t.getClass().getSimpleName();
255 }
256
257 if (t instanceof UnknownHostException && !fullMessage.contains("host")) {
258 fullMessage = join(fullMessage, "Unknown host " + exceptionMessage);
259 } else if (!fullMessage.contains(exceptionMessage)) {
260 fullMessage = join(fullMessage, exceptionMessage);
261 }
262
263 if (!dejaVu.add(t)) {
264 fullMessage = join(fullMessage, "[CIRCULAR REFERENCE]");
265 break;
266 }
267 }
268
269 return fullMessage.trim();
270 }
271
272 private String join(String message1, String message2) {
273 String message = "";
274
275 if (message1 != null && !message1.isEmpty()) {
276 message = message1.trim();
277 }
278
279 if (message2 != null && !message2.isEmpty()) {
280 if (message != null && !message.isEmpty()) {
281 if (message.endsWith(".") || message.endsWith("!") || message.endsWith(":")) {
282 message += " ";
283 } else {
284 message += ": ";
285 }
286 }
287
288 message += message2;
289 }
290
291 return message;
292 }
293 }