private static String collapseText( Throwable t, boolean includeAllCausalMessages, Set<Throwable> visited) { if (t == null) return null; if (visited.contains(t)) { // IllegalStateException sometimes refers to itself; guard against stack overflows if (Strings.isNonBlank(t.getMessage())) return t.getMessage(); else return "(" + t.getClass().getName() + ", recursive cause)"; } Throwable t2 = collapse(t, true, includeAllCausalMessages, visited); visited = MutableSet.copyOf(visited); visited.add(t); visited.add(t2); if (t2 instanceof PropagatedRuntimeException) { if (((PropagatedRuntimeException) t2).isCauseEmbeddedInMessage()) // normally return t2.getMessage(); else if (t2.getCause() != null) return collapseText(t2.getCause(), includeAllCausalMessages, ImmutableSet.copyOf(visited)); return "" + t2.getClass(); } String result = t2.toString(); if (!includeAllCausalMessages) { return result; } Throwable cause = t2.getCause(); if (cause != null) { String causeResult = collapseText(new PropagatedRuntimeException(cause)); if (result.indexOf(causeResult) >= 0) return result; return result + "; caused by " + causeResult; } return result; }
private static Throwable collapse( Throwable source, boolean collapseCausalChain, boolean includeAllCausalMessages, Set<Throwable> visited) { visited = MutableSet.copyOf(visited); String message = ""; Throwable collapsed = source; int collapseCount = 0; boolean messageIsFinal = false; // remove boring stack traces at the head while (isBoring(collapsed) && !messageIsFinal) { collapseCount++; Throwable cause = collapsed.getCause(); if (cause == null) { // everything in the tree is boring... return source; } if (visited.add(collapsed)) { // there is a recursive loop break; } String collapsedS = collapsed.getMessage(); if (collapsed instanceof PropagatedRuntimeException && ((PropagatedRuntimeException) collapsed).isCauseEmbeddedInMessage()) { message = collapsed.getMessage(); messageIsFinal = true; } else if (Strings.isNonBlank(collapsedS)) { collapsedS = Strings.removeAllFromEnd( collapsedS, cause.toString(), stripBoringPrefixes(cause.toString()), cause.getMessage()); collapsedS = stripBoringPrefixes(collapsedS); if (Strings.isNonBlank(collapsedS)) message = appendSeparator(message, collapsedS); } collapsed = cause; } // if no messages so far (ie we will be the toString) then remove boring prefixes from the // message Throwable messagesCause = collapsed; while (messagesCause != null && isPrefixBoring(messagesCause) && Strings.isBlank(message)) { collapseCount++; if (Strings.isNonBlank(messagesCause.getMessage())) { message = messagesCause.getMessage(); messagesCause = messagesCause.getCause(); break; } visited.add(messagesCause); messagesCause = messagesCause.getCause(); } if (collapseCount == 0 && !includeAllCausalMessages) return source; if (collapseCount == 0 && messagesCause != null) { message = messagesCause.toString(); messagesCause = messagesCause.getCause(); } if (messagesCause != null && !messageIsFinal) { String extraMessage = collapseText(messagesCause, includeAllCausalMessages, ImmutableSet.copyOf(visited)); message = appendSeparator(message, extraMessage); } if (message == null) message = ""; return new PropagatedRuntimeException(message, collapseCausalChain ? collapsed : source, true); }
private void assertEqualsIgnoringOrder( Iterable<? extends Object> col1, Iterable<? extends Object> col2) { assertEquals(Iterables.size(col1), Iterables.size(col2), "col2=" + col1 + "; col2=" + col2); assertEquals( MutableSet.copyOf(col1), MutableSet.copyOf(col2), "col1=" + col1 + "; col2=" + col2); }