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