mirror of https://github.com/apache/maven.git
[MNG-8066] Default exception handler does not handle recursion (#1558)
If there is a recursion in throwable causes, Maven will hang forever, instead to return. --- https://issues.apache.org/jira/browse/MNG-8066
This commit is contained in:
parent
df00ea5c10
commit
865072025d
|
@ -22,7 +22,10 @@ import java.io.IOException;
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.maven.lifecycle.LifecycleExecutionException;
|
import org.apache.maven.lifecycle.LifecycleExecutionException;
|
||||||
import org.apache.maven.model.building.ModelProblem;
|
import org.apache.maven.model.building.ModelProblem;
|
||||||
|
@ -87,13 +90,13 @@ Plugins:
|
||||||
*/
|
*/
|
||||||
@Component(role = ExceptionHandler.class)
|
@Component(role = ExceptionHandler.class)
|
||||||
public class DefaultExceptionHandler implements ExceptionHandler {
|
public class DefaultExceptionHandler implements ExceptionHandler {
|
||||||
|
@Override
|
||||||
public ExceptionSummary handleException(Throwable exception) {
|
public ExceptionSummary handleException(Throwable exception) {
|
||||||
return handle("", exception);
|
return handle("", exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExceptionSummary handle(String message, Throwable exception) {
|
private ExceptionSummary handle(String message, Throwable exception) {
|
||||||
String reference = getReference(exception);
|
String reference = getReference(Collections.newSetFromMap(new IdentityHashMap<>()), exception);
|
||||||
|
|
||||||
List<ExceptionSummary> children = null;
|
List<ExceptionSummary> children = null;
|
||||||
|
|
||||||
|
@ -153,8 +156,11 @@ public class DefaultExceptionHandler implements ExceptionHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getReference(Throwable exception) {
|
private String getReference(Set<Throwable> dejaVu, Throwable exception) {
|
||||||
String reference = "";
|
String reference = "";
|
||||||
|
if (!dejaVu.add(exception)) {
|
||||||
|
return reference;
|
||||||
|
}
|
||||||
|
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
if (exception instanceof MojoExecutionException) {
|
if (exception instanceof MojoExecutionException) {
|
||||||
|
@ -186,14 +192,14 @@ public class DefaultExceptionHandler implements ExceptionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isEmpty(reference)) {
|
if (StringUtils.isEmpty(reference)) {
|
||||||
reference = getReference(cause);
|
reference = getReference(dejaVu, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isEmpty(reference)) {
|
if (StringUtils.isEmpty(reference)) {
|
||||||
reference = exception.getClass().getSimpleName();
|
reference = exception.getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
} else if (exception instanceof LifecycleExecutionException) {
|
} else if (exception instanceof LifecycleExecutionException) {
|
||||||
reference = getReference(exception.getCause());
|
reference = getReference(dejaVu, exception.getCause());
|
||||||
} else if (isNoteworthyException(exception)) {
|
} else if (isNoteworthyException(exception)) {
|
||||||
reference = exception.getClass().getSimpleName();
|
reference = exception.getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
|
@ -222,7 +228,8 @@ public class DefaultExceptionHandler implements ExceptionHandler {
|
||||||
private String getMessage(String message, Throwable exception) {
|
private String getMessage(String message, Throwable exception) {
|
||||||
String fullMessage = (message != null) ? message : "";
|
String fullMessage = (message != null) ? message : "";
|
||||||
|
|
||||||
// To break out of possible endless loop when getCause returns "this"
|
// To break out of possible endless loop when getCause returns "this", or dejaVu for n-level recursion (n>1)
|
||||||
|
Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
|
||||||
for (Throwable t = exception; t != null && t != t.getCause(); t = t.getCause()) {
|
for (Throwable t = exception; t != null && t != t.getCause(); t = t.getCause()) {
|
||||||
String exceptionMessage = t.getMessage();
|
String exceptionMessage = t.getMessage();
|
||||||
|
|
||||||
|
@ -246,6 +253,11 @@ public class DefaultExceptionHandler implements ExceptionHandler {
|
||||||
} else if (!fullMessage.contains(exceptionMessage)) {
|
} else if (!fullMessage.contains(exceptionMessage)) {
|
||||||
fullMessage = join(fullMessage, exceptionMessage);
|
fullMessage = join(fullMessage, exceptionMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!dejaVu.add(t)) {
|
||||||
|
fullMessage = join(fullMessage, "[CIRCULAR REFERENCE]");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fullMessage.trim();
|
return fullMessage.trim();
|
||||||
|
|
|
@ -124,4 +124,20 @@ public class DefaultExceptionHandlerTest {
|
||||||
String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException";
|
String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException";
|
||||||
assertEquals(expectedReference, summary.getReference());
|
assertEquals(expectedReference, summary.getReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHandleExceptionSelfReferencing() {
|
||||||
|
RuntimeException boom3 = new RuntimeException("BOOM3");
|
||||||
|
RuntimeException boom2 = new RuntimeException("BOOM2", boom3);
|
||||||
|
RuntimeException boom1 = new RuntimeException("BOOM1", boom2);
|
||||||
|
boom3.initCause(boom1);
|
||||||
|
|
||||||
|
DefaultExceptionHandler handler = new DefaultExceptionHandler();
|
||||||
|
ExceptionSummary summary = handler.handleException(boom1);
|
||||||
|
|
||||||
|
assertEquals("BOOM1: BOOM2: BOOM3: [CIRCULAR REFERENCE]", summary.getMessage());
|
||||||
|
assertEquals("", summary.getReference());
|
||||||
|
assertEquals(0, summary.getChildren().size());
|
||||||
|
assertEquals(boom1, summary.getException());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue