diff options
Diffstat (limited to 'guava/src/com/google/common/collect/Streams.java')
-rw-r--r-- | guava/src/com/google/common/collect/Streams.java | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/guava/src/com/google/common/collect/Streams.java b/guava/src/com/google/common/collect/Streams.java index 0b6e88ce2..8209cedb5 100644 --- a/guava/src/com/google/common/collect/Streams.java +++ b/guava/src/com/google/common/collect/Streams.java @@ -148,11 +148,40 @@ public final class Streams { return optional.isPresent() ? DoubleStream.of(optional.getAsDouble()) : DoubleStream.empty(); } + @SuppressWarnings("CatchingUnchecked") // sneaky checked exception private static void closeAll(BaseStream<?, ?>[] toClose) { + // If one of the streams throws an exception, continue closing the others, then throw the + // exception later. If more than one stream throws an exception, the later ones are added to the + // first as suppressed exceptions. We don't catch Error on the grounds that it should be allowed + // to propagate immediately. + Exception exception = null; for (BaseStream<?, ?> stream : toClose) { - // TODO(b/80534298): Catch exceptions, rethrowing later with extras as suppressed exceptions. - stream.close(); + try { + stream.close(); + } catch (Exception e) { // sneaky checked exception + if (exception == null) { + exception = e; + } else { + exception.addSuppressed(e); + } + } + } + if (exception != null) { + // Normally this is a RuntimeException that doesn't need sneakyThrow. + // But theoretically we could see sneaky checked exception + sneakyThrow(exception); + } + } + + /** Throws an undeclared checked exception. */ + private static void sneakyThrow(Throwable t) { + class SneakyThrower<T extends Throwable> { + @SuppressWarnings("unchecked") // not really safe, but that's the point + void throwIt(Throwable t) throws T { + throw (T) t; + } } + new SneakyThrower<Error>().throwIt(t); } /** |