From: Simon Brandhof Date: Mon, 15 Dec 2014 12:56:08 +0000 (+0100) Subject: Automatic close of ResultSetIterator when reaching last element X-Git-Tag: latest-silver-master-#65~513 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=8400d76a67b7ecfad53b58e3c0e32c37228613b8;p=sonarqube.git Automatic close of ResultSetIterator when reaching last element --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/ResultSetIterator.java b/server/sonar-server/src/main/java/org/sonar/server/db/ResultSetIterator.java index c3ab79b7d86..77392ec0957 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/db/ResultSetIterator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/db/ResultSetIterator.java @@ -31,7 +31,14 @@ import java.util.Iterator; import java.util.NoSuchElementException; /** - * {@link java.util.Iterator} applied to {@link java.sql.ResultSet} + * Forward-only {@link java.util.Iterator} over a {@link java.sql.ResultSet}. Rows are + * lazily loaded. The underlying ResultSet must be closed by calling the method + * {@link #close()} + *

+ * As a safeguard, the ResultSet is automatically closed after the last element has + * been retrieved via {@link #next()} or {@link #hasNext()} is called (which will return false). + * This automagic behavior is not enough to remove explicit calls to {@link #close()} + * from caller methods. Errors raised before end of traversal must still be handled. */ public abstract class ResultSetIterator implements Iterator, Closeable { @@ -40,6 +47,7 @@ public abstract class ResultSetIterator implements Iterator, Closeable { private volatile boolean didNext = false; private volatile boolean hasNext = false; + private volatile boolean closed = false; public ResultSetIterator(PreparedStatement stmt) throws SQLException { this.stmt = stmt; @@ -53,10 +61,15 @@ public abstract class ResultSetIterator implements Iterator, Closeable { @Override public boolean hasNext() { + if (closed) { + return false; + } if (!didNext) { hasNext = doNextQuietly(); if (hasNext) { didNext = true; + } else { + close(); } } return hasNext; @@ -66,6 +79,7 @@ public abstract class ResultSetIterator implements Iterator, Closeable { @CheckForNull public E next() { if (!hasNext()) { + close(); throw new NoSuchElementException(); } try { @@ -74,6 +88,9 @@ public abstract class ResultSetIterator implements Iterator, Closeable { throw new IllegalStateException("Fail to read result set row", e); } finally { hasNext = doNextQuietly(); + if (!hasNext) { + close(); + } } } @@ -84,6 +101,7 @@ public abstract class ResultSetIterator implements Iterator, Closeable { @Override public void close() { + closed = true; DbUtils.closeQuietly(rs); DbUtils.closeQuietly(stmt); }