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