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.List;
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.util.StringUtils;
41  
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  @Named
91  @Singleton
92  public class DefaultExceptionHandler implements ExceptionHandler {
93  
94      public ExceptionSummary handleException(Throwable exception) {
95          return handle("", exception);
96      }
97  
98      private ExceptionSummary handle(String message, Throwable exception) {
99          String reference = getReference(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 = System.lineSeparator()
138                 + "The project " + (result.getProjectId().isEmpty() ? "" : result.getProjectId() + " ")
139                 + "(" + result.getPomFile() + ") has "
140                 + children.size() + " error" + (children.size() == 1 ? "" : "s");
141 
142         return new ExceptionSummary(null, message, null, children);
143     }
144 
145     private ExceptionSummary handle(ModelProblem problem, String projectId) {
146         if (ModelProblem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
147             String message = problem.getMessage();
148 
149             String location = ModelProblemUtils.formatLocation(problem, projectId);
150 
151             if (!location.isEmpty()) {
152                 message += " @ " + location;
153             }
154 
155             return handle(message, problem.getException());
156         } else {
157             return null;
158         }
159     }
160 
161     private String getReference(Throwable exception) {
162         String reference = "";
163 
164         if (exception != null) {
165             if (exception instanceof MojoExecutionException) {
166                 reference = MojoExecutionException.class.getSimpleName();
167 
168                 Throwable cause = exception.getCause();
169                 if (cause instanceof IOException) {
170                     cause = cause.getCause();
171                     if (cause instanceof ConnectException) {
172                         reference = ConnectException.class.getSimpleName();
173                     }
174                 }
175             } else if (exception instanceof MojoFailureException) {
176                 reference = MojoFailureException.class.getSimpleName();
177             } else if (exception instanceof LinkageError) {
178                 reference = LinkageError.class.getSimpleName();
179             } else if (exception instanceof PluginExecutionException) {
180                 Throwable cause = exception.getCause();
181 
182                 if (cause instanceof PluginContainerException) {
183                     Throwable cause2 = cause.getCause();
184 
185                     if (cause2 instanceof NoClassDefFoundError) {
186                         String message = cause2.getMessage();
187                         if (message != null && message.contains("org/sonatype/aether/")) {
188                             reference = "AetherClassNotFound";
189                         }
190                     }
191                 }
192 
193                 if (StringUtils.isEmpty(reference)) {
194                     reference = getReference(cause);
195                 }
196 
197                 if (StringUtils.isEmpty(reference)) {
198                     reference = exception.getClass().getSimpleName();
199                 }
200             } else if (exception instanceof LifecycleExecutionException) {
201                 reference = getReference(exception.getCause());
202             } else if (isNoteworthyException(exception)) {
203                 reference = exception.getClass().getSimpleName();
204             }
205         }
206 
207         if (StringUtils.isNotEmpty(reference) && !reference.startsWith("http:")) {
208             reference = "http://cwiki.apache.org/confluence/display/MAVEN/" + reference;
209         }
210 
211         return reference;
212     }
213 
214     private boolean isNoteworthyException(Throwable exception) {
215         if (exception == null) {
216             return false;
217         } else if (exception instanceof Error) {
218             return true;
219         } else if (exception instanceof RuntimeException) {
220             return false;
221         } else {
222             return !exception.getClass().getName().startsWith("java");
223         }
224     }
225 
226     private String getMessage(String message, Throwable exception) {
227         String fullMessage = (message != null) ? message : "";
228 
229         for (Throwable t = exception; t != null; t = t.getCause()) {
230             String exceptionMessage = t.getMessage();
231 
232             if (t instanceof AbstractMojoExecutionException) {
233                 String longMessage = ((AbstractMojoExecutionException) t).getLongMessage();
234                 if (StringUtils.isNotEmpty(longMessage)) {
235                     if (StringUtils.isEmpty(exceptionMessage) || longMessage.contains(exceptionMessage)) {
236                         exceptionMessage = longMessage;
237                     } else if (!exceptionMessage.contains(longMessage)) {
238                         exceptionMessage = join(exceptionMessage, System.lineSeparator() + longMessage);
239                     }
240                 }
241             }
242 
243             if (StringUtils.isEmpty(exceptionMessage)) {
244                 exceptionMessage = t.getClass().getSimpleName();
245             }
246 
247             if (t instanceof UnknownHostException && !fullMessage.contains("host")) {
248                 fullMessage = join(fullMessage, "Unknown host " + exceptionMessage);
249             } else if (!fullMessage.contains(exceptionMessage)) {
250                 fullMessage = join(fullMessage, exceptionMessage);
251             }
252         }
253 
254         return fullMessage.trim();
255     }
256 
257     private String join(String message1, String message2) {
258         String message = "";
259 
260         if (StringUtils.isNotEmpty(message1)) {
261             message = message1.trim();
262         }
263 
264         if (StringUtils.isNotEmpty(message2)) {
265             if (StringUtils.isNotEmpty(message)) {
266                 if (message.endsWith(".") || message.endsWith("!") || message.endsWith(":")) {
267                     message += " ";
268                 } else {
269                     message += ": ";
270                 }
271             }
272 
273             message += message2;
274         }
275 
276         return message;
277     }
278 }