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 java.io.IOException;
22 import java.net.ConnectException;
23 import java.net.UnknownHostException;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.IdentityHashMap;
27 import java.util.List;
28 import java.util.Set;
29
30 import org.apache.maven.lifecycle.LifecycleExecutionException;
31 import org.apache.maven.model.building.ModelProblem;
32 import org.apache.maven.model.building.ModelProblemUtils;
33 import org.apache.maven.plugin.AbstractMojoExecutionException;
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.plugin.MojoFailureException;
36 import org.apache.maven.plugin.PluginContainerException;
37 import org.apache.maven.plugin.PluginExecutionException;
38 import org.apache.maven.project.ProjectBuildingException;
39 import org.apache.maven.project.ProjectBuildingResult;
40 import org.codehaus.plexus.component.annotations.Component;
41 import org.codehaus.plexus.util.StringUtils;
42
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 @Component(role = ExceptionHandler.class)
92 public class DefaultExceptionHandler implements ExceptionHandler {
93 @Override
94 public ExceptionSummary handleException(Throwable exception) {
95 return handle("", exception);
96 }
97
98 private ExceptionSummary handle(String message, Throwable exception) {
99 String reference = getReference(Collections.newSetFromMap(new IdentityHashMap<>()), exception);
100
101 List<ExceptionSummary> children = null;
102
103 if (exception instanceof ProjectBuildingException) {
104 List<ProjectBuildingResult> results = ((ProjectBuildingException) exception).getResults();
105
106 children = new ArrayList<>();
107
108 for (ProjectBuildingResult result : results) {
109 ExceptionSummary child = handle(result);
110 if (child != null) {
111 children.add(child);
112 }
113 }
114
115 message = "The build could not read " + children.size() + " project" + (children.size() == 1 ? "" : "s");
116 } else {
117 message = getMessage(message, exception);
118 }
119
120 return new ExceptionSummary(exception, message, reference, children);
121 }
122
123 private ExceptionSummary handle(ProjectBuildingResult result) {
124 List<ExceptionSummary> children = new ArrayList<>();
125
126 for (ModelProblem problem : result.getProblems()) {
127 ExceptionSummary child = handle(problem, result.getProjectId());
128 if (child != null) {
129 children.add(child);
130 }
131 }
132
133 if (children.isEmpty()) {
134 return null;
135 }
136
137 String message = "\nThe project " + result.getProjectId() + " (" + result.getPomFile() + ") has "
138 + children.size() + " error" + (children.size() == 1 ? "" : "s");
139
140 return new ExceptionSummary(null, message, null, children);
141 }
142
143 private ExceptionSummary handle(ModelProblem problem, String projectId) {
144 if (ModelProblem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
145 String message = problem.getMessage();
146
147 String location = ModelProblemUtils.formatLocation(problem, projectId);
148
149 if (StringUtils.isNotEmpty(location)) {
150 message += " @ " + location;
151 }
152
153 return handle(message, problem.getException());
154 } else {
155 return null;
156 }
157 }
158
159 private String getReference(Set<Throwable> dejaVu, Throwable exception) {
160 String reference = "";
161 if (!dejaVu.add(exception)) {
162 return reference;
163 }
164
165 if (exception != null) {
166 if (exception instanceof MojoExecutionException) {
167 reference = MojoExecutionException.class.getSimpleName();
168
169 Throwable cause = exception.getCause();
170 if (cause instanceof IOException) {
171 cause = cause.getCause();
172 if (cause instanceof ConnectException) {
173 reference = ConnectException.class.getSimpleName();
174 }
175 }
176 } else if (exception instanceof MojoFailureException) {
177 reference = MojoFailureException.class.getSimpleName();
178 } else if (exception instanceof LinkageError) {
179 reference = LinkageError.class.getSimpleName();
180 } else if (exception instanceof PluginExecutionException) {
181 Throwable cause = exception.getCause();
182
183 if (cause instanceof PluginContainerException) {
184 Throwable cause2 = cause.getCause();
185
186 if (cause2 instanceof NoClassDefFoundError) {
187 String message = cause2.getMessage();
188 if (message != null && message.contains("org/sonatype/aether/")) {
189 reference = "AetherClassNotFound";
190 }
191 }
192 }
193
194 if (StringUtils.isEmpty(reference)) {
195 reference = getReference(dejaVu, cause);
196 }
197
198 if (StringUtils.isEmpty(reference)) {
199 reference = exception.getClass().getSimpleName();
200 }
201 } else if (exception instanceof LifecycleExecutionException) {
202 reference = getReference(dejaVu, exception.getCause());
203 } else if (isNoteworthyException(exception)) {
204 reference = exception.getClass().getSimpleName();
205 }
206 }
207
208 if (StringUtils.isNotEmpty(reference) && !reference.startsWith("http:")) {
209 reference = "http://cwiki.apache.org/confluence/display/MAVEN/" + reference;
210 }
211
212 return reference;
213 }
214
215 private boolean isNoteworthyException(Throwable exception) {
216 if (exception == null) {
217 return false;
218 } else if (exception instanceof Error) {
219 return true;
220 } else if (exception instanceof RuntimeException) {
221 return false;
222 } else if (exception.getClass().getName().startsWith("java")) {
223 return false;
224 }
225 return true;
226 }
227
228 private String getMessage(String message, Throwable exception) {
229 String fullMessage = (message != null) ? message : "";
230
231
232 Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
233 for (Throwable t = exception; t != null && t != t.getCause(); t = t.getCause()) {
234 String exceptionMessage = t.getMessage();
235
236 if (t instanceof AbstractMojoExecutionException) {
237 String longMessage = ((AbstractMojoExecutionException) t).getLongMessage();
238 if (StringUtils.isNotEmpty(longMessage)) {
239 if (StringUtils.isEmpty(exceptionMessage) || longMessage.contains(exceptionMessage)) {
240 exceptionMessage = longMessage;
241 } else if (!exceptionMessage.contains(longMessage)) {
242 exceptionMessage = join(exceptionMessage, '\n' + longMessage);
243 }
244 }
245 }
246
247 if (StringUtils.isEmpty(exceptionMessage)) {
248 exceptionMessage = t.getClass().getSimpleName();
249 }
250
251 if (t instanceof UnknownHostException && !fullMessage.contains("host")) {
252 fullMessage = join(fullMessage, "Unknown host " + exceptionMessage);
253 } else if (!fullMessage.contains(exceptionMessage)) {
254 fullMessage = join(fullMessage, exceptionMessage);
255 }
256
257 if (!dejaVu.add(t)) {
258 fullMessage = join(fullMessage, "[CIRCULAR REFERENCE]");
259 break;
260 }
261 }
262
263 return fullMessage.trim();
264 }
265
266 private String join(String message1, String message2) {
267 String message = "";
268
269 if (StringUtils.isNotEmpty(message1)) {
270 message = message1.trim();
271 }
272
273 if (StringUtils.isNotEmpty(message2)) {
274 if (StringUtils.isNotEmpty(message)) {
275 if (message.endsWith(".") || message.endsWith("!") || message.endsWith(":")) {
276 message += " ";
277 } else {
278 message += ": ";
279 }
280 }
281
282 message += message2;
283 }
284
285 return message;
286 }
287 }