View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.exception;
20  
21  import java.io.IOException;
22  import java.net.ConnectException;
23  import java.util.concurrent.atomic.AtomicReference;
24  
25  import org.apache.maven.model.Plugin;
26  import org.apache.maven.plugin.MojoExecution;
27  import org.apache.maven.plugin.MojoExecutionException;
28  import org.apache.maven.plugin.PluginContainerException;
29  import org.apache.maven.plugin.PluginExecutionException;
30  import org.apache.maven.plugin.descriptor.MojoDescriptor;
31  import org.apache.maven.plugin.descriptor.PluginDescriptor;
32  import org.junit.jupiter.api.Test;
33  
34  import static org.junit.jupiter.api.Assertions.assertEquals;
35  
36  /**
37   */
38  class DefaultExceptionHandlerTest {
39      /**
40       * Running Maven under JDK7 may cause connection issues because IPv6 is used by default.
41       * <p>
42       * e.g running mvn site:run will cause Jetty to fail.
43       * </p>
44       * <p>
45       * The resolution is to add -Djava.net.preferIPv4Stack=true to the command line as documented in
46       * http://cwiki.apache.org/confluence/display/MAVEN/ConnectException
47       * </p>
48       */
49      @Test
50      void testJdk7ipv6() {
51          ConnectException connEx = new ConnectException("Connection refused: connect");
52          IOException ioEx = new IOException("Unable to establish loopback connection", connEx);
53          MojoExecutionException mojoEx =
54                  new MojoExecutionException("Error executing Jetty: Unable to establish loopback connection", ioEx);
55  
56          ExceptionHandler exceptionHandler = new DefaultExceptionHandler();
57          ExceptionSummary exceptionSummary = exceptionHandler.handleException(mojoEx);
58  
59          String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/ConnectException";
60          assertEquals(expectedReference, exceptionSummary.getReference());
61      }
62  
63      @Test
64      void testHandleExceptionAetherClassNotFound() {
65          Throwable cause2 = new NoClassDefFoundError("org/sonatype/aether/RepositorySystem");
66          Plugin plugin = new Plugin();
67          Exception cause = new PluginContainerException(plugin, null, null, cause2);
68          PluginDescriptor pluginDescriptor = new PluginDescriptor();
69          MojoDescriptor mojoDescriptor = new MojoDescriptor();
70          mojoDescriptor.setPluginDescriptor(pluginDescriptor);
71          MojoExecution mojoExecution = new MojoExecution(mojoDescriptor);
72          Throwable exception = new PluginExecutionException(mojoExecution, null, cause);
73  
74          DefaultExceptionHandler handler = new DefaultExceptionHandler();
75          ExceptionSummary summary = handler.handleException(exception);
76  
77          String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/AetherClassNotFound";
78          assertEquals(expectedReference, summary.getReference());
79      }
80  
81      @Test
82      void testHandleExceptionNoClassDefFoundErrorNull() {
83          Throwable cause2 = new NoClassDefFoundError();
84          Plugin plugin = new Plugin();
85          Exception cause = new PluginContainerException(plugin, null, null, cause2);
86          PluginDescriptor pluginDescriptor = new PluginDescriptor();
87          MojoDescriptor mojoDescriptor = new MojoDescriptor();
88          mojoDescriptor.setPluginDescriptor(pluginDescriptor);
89          MojoExecution mojoExecution = new MojoExecution(mojoDescriptor);
90          Throwable exception = new PluginExecutionException(mojoExecution, null, cause);
91  
92          DefaultExceptionHandler handler = new DefaultExceptionHandler();
93          ExceptionSummary summary = handler.handleException(exception);
94  
95          String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException";
96          assertEquals(expectedReference, summary.getReference());
97      }
98  
99      @Test
100     void testHandleExceptionLoopInCause() {
101         // Some broken exception that does return "this" as getCause
102         AtomicReference<Throwable> causeRef = new AtomicReference<>(null);
103         Exception cause2 = new RuntimeException("loop") {
104             @Override
105             public synchronized Throwable getCause() {
106                 return causeRef.get();
107             }
108         };
109         causeRef.set(cause2);
110 
111         Plugin plugin = new Plugin();
112         Exception cause = new PluginContainerException(plugin, null, null, cause2);
113         cause2.initCause(cause);
114         PluginDescriptor pluginDescriptor = new PluginDescriptor();
115         MojoDescriptor mojoDescriptor = new MojoDescriptor();
116         mojoDescriptor.setPluginDescriptor(pluginDescriptor);
117         MojoExecution mojoExecution = new MojoExecution(mojoDescriptor);
118         Throwable exception = new PluginExecutionException(mojoExecution, null, cause);
119 
120         DefaultExceptionHandler handler = new DefaultExceptionHandler();
121         ExceptionSummary summary = handler.handleException(exception);
122 
123         String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException";
124         assertEquals(expectedReference, summary.getReference());
125     }
126 
127     @Test
128     void testHandleExceptionSelfReferencing() {
129         RuntimeException boom3 = new RuntimeException("BOOM3");
130         RuntimeException boom2 = new RuntimeException("BOOM2", boom3);
131         RuntimeException boom1 = new RuntimeException("BOOM1", boom2);
132         boom3.initCause(boom1);
133 
134         DefaultExceptionHandler handler = new DefaultExceptionHandler();
135         ExceptionSummary summary = handler.handleException(boom1);
136 
137         assertEquals("BOOM1: BOOM2: BOOM3: [CIRCULAR REFERENCE]", summary.getMessage());
138         assertEquals("", summary.getReference());
139         assertEquals(0, summary.getChildren().size());
140         assertEquals(boom1, summary.getException());
141     }
142 }