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