jdk/src/share/classes/java/nio/file/DirectoryStream.java
changeset 6537 7aa4e7bb5dae
parent 5506 202f599c92aa
child 7668 d4a77089c587
--- a/jdk/src/share/classes/java/nio/file/DirectoryStream.java	Thu Sep 09 11:50:40 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/DirectoryStream.java	Fri Sep 10 16:36:48 2010 +0100
@@ -31,60 +31,84 @@
 
 /**
  * An object to iterate over the entries in a directory. A directory stream
- * allows for convenient use of the for-each construct:
+ * allows for the convenient use of the for-each construct to iterate over a
+ * directory.
+ *
+ * <p> <b> While {@code DirectoryStream} extends {@code Iterable}, it is not a
+ * general-purpose {@code Iterable} as it supports only a single {@code
+ * Iterator}; invoking the {@link #iterator iterator} method to obtain a second
+ * or subsequent iterator throws {@code IllegalStateException}. </b>
+ *
+ * <p> An important property of the directory stream's {@code Iterator} is that
+ * its {@link Iterator#hasNext() hasNext} method is guaranteed to read-ahead by
+ * at least one element. If {@code hasNext} method returns {@code true}, and is
+ * followed by a call to the {@code next} method, it is guaranteed that the
+ * {@code next} method will not throw an exception due to an I/O error, or
+ * because the stream has been {@link #close closed}. The {@code Iterator} does
+ * not support the {@link Iterator#remove remove} operation.
+ *
+ * <p> A {@code DirectoryStream} is opened upon creation and is closed by
+ * invoking the {@code close} method. Closing a directory stream releases any
+ * resources associated with the stream. Failure to close the stream may result
+ * in a resource leak. The try-with-resources statement provides a useful
+ * construct to ensure that the stream is closed:
  * <pre>
  *   Path dir = ...
- *   DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream();
- *   try {
+ *   try (DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream()) {
  *       for (Path entry: stream) {
- *         ..
+ *           ...
  *       }
- *   } finally {
- *       stream.close();
  *   }
  * </pre>
  *
- * <p><b> A {@code DirectoryStream} is not a general-purpose {@code Iterable}.
- * While this interface extends {@code Iterable}, the {@code iterator} method
- * may only be invoked once to obtain the iterator; a second, or subsequent,
- * call to the {@code iterator} method throws {@code IllegalStateException}. </b>
- *
- * <p> A {@code DirectoryStream} is opened upon creation and is closed by
- * invoking the {@link #close close} method. Closing the directory stream
- * releases any resources associated with the stream. Once a directory stream
- * is closed, all further method invocations on the iterator throw {@link
- * java.util.ConcurrentModificationException} with cause {@link
- * ClosedDirectoryStreamException}.
+ * <p> Once a directory stream is closed, then further access to the directory,
+ * using the {@code Iterator}, behaves as if the end of stream has been reached.
+ * Due to read-ahead, the {@code Iterator} may return one or more elements
+ * after the directory stream has been closed. Once these buffered elements
+ * have been read, then subsequent calls to the {@code hasNext} method returns
+ * {@code false}, and subsequent calls to the {@code next} method will throw
+ * {@code NoSuchElementException}.
  *
  * <p> A directory stream is not required to be <i>asynchronously closeable</i>.
  * If a thread is blocked on the directory stream's iterator reading from the
  * directory, and another thread invokes the {@code close} method, then the
  * second thread may block until the read operation is complete.
  *
- * <p> The {@link Iterator#hasNext() hasNext} and {@link Iterator#next() next}
- * methods can encounter an I/O error when iterating over the directory in which
- * case {@code ConcurrentModificationException} is thrown with cause
- * {@link java.io.IOException}. The {@code hasNext} method is guaranteed to
- * read-ahead by at least one element. This means that if the {@code hasNext}
- * method returns {@code true} and is followed by a call to the {@code next}
- * method then it is guaranteed not to fail with a {@code
- * ConcurrentModificationException}.
+ * <p> If an I/O error is encountered when accessing the directory then it
+ * causes the {@code Iterator}'s {@code hasNext} or {@code next} methods to
+ * throw {@link DirectoryIteratorException} with the {@link IOException} as the
+ * cause. As stated above, the {@code hasNext} method is guaranteed to
+ * read-ahead by at least one element. This means that if {@code hasNext} method
+ * returns {@code true}, and is followed by a call to the {@code next} method,
+ * then it is guaranteed that the {@code next} method will not fail with a
+ * {@code DirectoryIteratorException}.
  *
  * <p> The elements returned by the iterator are in no specific order. Some file
  * systems maintain special links to the directory itself and the directory's
  * parent directory. Entries representing these links are not returned by the
  * iterator.
  *
- * <p> The iterator's {@link Iterator#remove() remove} method removes the
- * directory entry for the last element returned by the iterator, as if by
- * invoking the {@link Path#delete delete} method. If an I/O error or
- * security exception occurs then {@code ConcurrentModificationException} is
- * thrown with the cause.
- *
  * <p> The iterator is <i>weakly consistent</i>. It is thread safe but does not
  * freeze the directory while iterating, so it may (or may not) reflect updates
  * to the directory that occur after the {@code DirectoryStream} is created.
  *
+ * <p> <b>Usage Examples:</b>
+ * Suppose we want a list of the source files in a directory. This example uses
+ * both the for-each and try-with-resources constructs.
+ * <pre>
+ *   List&lt;Path&gt; listSourceFiles(Path dir) throws IOException {
+ *       List&lt;Path&gt; result = new ArrayList&lt;Path&gt;();
+ *       try (DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream("*.{c,h,cpp,hpp,java}")) {
+ *           for (Path entry: stream) {
+ *               result.add(entry);
+ *           }
+ *       } catch (DirectoryIteratorException ex) {
+ *           // I/O error encounted during the iteration, the cause is an IOException
+ *           throw ex.getCause();
+ *       }
+ *       return result;
+ *   }
+ * </pre>
  * @param   <T>     The type of element returned by the iterator
  *
  * @since 1.7