From af6d4a423967e033cdf51e3762d0a4d14f659983 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Fri, 3 Apr 2015 15:51:28 +0200 Subject: Hasnext() should not call doNext() when iterator already closed --- .../org/sonar/server/util/CloseableIterator.java | 6 +++++ .../sonar/server/util/CloseableIteratorTest.java | 28 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'server') diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/CloseableIterator.java b/server/sonar-server/src/main/java/org/sonar/server/util/CloseableIterator.java index 44903d9a0da..c8244454baa 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/util/CloseableIterator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/util/CloseableIterator.java @@ -28,9 +28,14 @@ import java.util.NoSuchElementException; public abstract class CloseableIterator implements Iterator, AutoCloseable { private O nextObject = null; + boolean isClosed = false; @Override public final boolean hasNext() { + // Optimization to not call bufferNext() when already closed + if (isClosed) { + return false; + } boolean hasNext = nextObject != null || bufferNext() != null; if (!hasNext) { close(); @@ -88,6 +93,7 @@ public abstract class CloseableIterator implements Iterator, AutoCloseable public final void close() { try { doClose(); + isClosed = true; } catch (Exception e) { Throwables.propagate(e); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/util/CloseableIteratorTest.java b/server/sonar-server/src/test/java/org/sonar/server/util/CloseableIteratorTest.java index 96913c04d7f..672ff885e02 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/util/CloseableIteratorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/util/CloseableIteratorTest.java @@ -96,6 +96,21 @@ public class CloseableIteratorTest { assertThat(it.isRemoved).isTrue(); } + @Test + public void has_next_should_not_call_do_next_when_already_closed() throws Exception { + DoNextShouldNotBeCalledWhenClosedIterator it = new DoNextShouldNotBeCalledWhenClosedIterator(); + + it.next(); + it.next(); + assertThat(it.hasNext()).isFalse(); + // this call to hasNext close the stream + assertThat(it.hasNext()).isFalse(); + assertThat(it.isClosed).isTrue(); + + // calling hasNext should not fail + it.hasNext(); + } + static class SimpleCloseableIterator extends CloseableIterator { int count = 0; boolean isClosed = false; @@ -147,4 +162,17 @@ public class CloseableIteratorTest { isClosed = true; } } + + static class DoNextShouldNotBeCalledWhenClosedIterator extends SimpleCloseableIterator { + + @Override + protected Object doNext() { + if (!isClosed) { + return super.doNext(); + } else { + throw new IllegalStateException("doNext should not be called when already closed"); + } + } + } + } -- cgit v1.2.3