--- a/jdk/make/java/nio/FILES_java.gmk Thu Sep 09 11:50:40 2010 -0700
+++ b/jdk/make/java/nio/FILES_java.gmk Fri Sep 10 16:36:48 2010 +0100
@@ -83,6 +83,7 @@
java/nio/file/ClosedFileSystemException.java \
java/nio/file/ClosedWatchServiceException.java \
java/nio/file/CopyOption.java \
+ java/nio/file/DirectoryIteratorException.java \
java/nio/file/DirectoryNotEmptyException.java \
java/nio/file/DirectoryStream.java \
java/nio/file/FileAlreadyExistsException.java \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/file/DirectoryIteratorException.java Fri Sep 10 16:36:48 2010 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.file;
+
+import java.util.ConcurrentModificationException;
+import java.util.Objects;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.InvalidObjectException;
+
+/**
+ * Runtime exception thrown if an I/O error is encountered when iterating over
+ * the entries in a directory. The I/O error is retrieved as an {@link
+ * IOException} using the {@link #getCause() getCause()} method.
+ *
+ * @since 1.7
+ * @see DirectoryStream
+ */
+
+public final class DirectoryIteratorException
+ extends ConcurrentModificationException
+{
+ private static final long serialVersionUID = -6012699886086212874L;
+
+ /**
+ * Constructs an instance of this class.
+ *
+ * @param cause
+ * the {@code IOException} that caused the directory iteration
+ * to fail
+ *
+ * @throws NullPointerException
+ * if the cause is {@code null}
+ */
+ public DirectoryIteratorException(IOException cause) {
+ super(Objects.nonNull(cause));
+ }
+
+ /**
+ * Returns the cause of this exception.
+ *
+ * @return the cause
+ */
+ @Override
+ public IOException getCause() {
+ return (IOException)super.getCause();
+ }
+
+ /**
+ * Called to read the object from a stream.
+ *
+ * @throws InvalidObjectException
+ * if the object is invalid or has a cause that is not
+ * an {@code IOException}
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ Throwable cause = super.getCause();
+ if (!(cause instanceof IOException))
+ throw new InvalidObjectException("Cause must be an IOException");
+ }
+}
--- 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<Path> stream = dir.newDirectoryStream();
- * try {
+ * try (DirectoryStream<Path> 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<Path> listSourceFiles(Path dir) throws IOException {
+ * List<Path> result = new ArrayList<Path>();
+ * try (DirectoryStream<Path> 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
--- a/jdk/src/share/classes/java/nio/file/Path.java Thu Sep 09 11:50:40 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/Path.java Fri Sep 10 16:36:48 2010 +0100
@@ -984,11 +984,11 @@
* directory.
*
* <p> Where the filter terminates due to an uncaught error or runtime
- * exception then it is propogated to the iterator's {@link Iterator#hasNext()
+ * exception then it is propagated to the {@link Iterator#hasNext()
* hasNext} or {@link Iterator#next() next} method. Where an {@code
- * IOException} is thrown, it is propogated as a {@link
- * java.util.ConcurrentModificationException} with the {@code
- * IOException} as the cause.
+ * IOException} is thrown, it results in the {@code hasNext} or {@code
+ * next} method throwing a {@link DirectoryIteratorException} with the
+ * {@code IOException} as the cause.
*
* <p> When an implementation supports operations on entries in the
* directory that execute in a race-free manner then the returned directory
--- a/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java Thu Sep 09 11:50:40 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java Fri Sep 10 16:36:48 2010 +0100
@@ -47,15 +47,6 @@
* newDirectoryStream} method will be a {@code SecureDirectoryStream} and must
* be cast to that type in order to invoke the methods defined by this interface.
*
- * <p> As specified by {@code DirectoryStream}, the iterator's {@link
- * java.util.Iterator#remove() remove} method removes the directory entry for
- * the last element returned by the iterator. In the case of a {@code
- * SecureDirectoryStream} the {@code remove} method behaves as if by invoking
- * the {@link #deleteFile deleteFile} or {@link #deleteDirectory deleteDirectory}
- * methods defined by this interface. The {@code remove} may require to examine
- * the file to determine if the file is a directory, and consequently, it may
- * not be atomic with respect to other file system operations.
- *
* <p> In the case of the default {@link java.nio.file.spi.FileSystemProvider
* provider}, and a security manager is set, then the permission checks are
* performed using the path obtained by resolving the given relative path
--- a/jdk/src/share/classes/java/util/ConcurrentModificationException.java Thu Sep 09 11:50:40 2010 -0700
+++ b/jdk/src/share/classes/java/util/ConcurrentModificationException.java Fri Sep 10 16:36:48 2010 +0100
@@ -49,9 +49,9 @@
* <p>Note that fail-fast behavior cannot be guaranteed as it is, generally
* speaking, impossible to make any hard guarantees in the presence of
* unsynchronized concurrent modification. Fail-fast operations
- * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
+ * throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
- * exception for its correctness: <i><tt>ConcurrentModificationException</tt>
+ * exception for its correctness: <i>{@code ConcurrentModificationException}
* should be used only to detect bugs.</i>
*
* @author Josh Bloch
@@ -77,7 +77,7 @@
}
/**
- * Constructs a <tt>ConcurrentModificationException</tt> with the
+ * Constructs a {@code ConcurrentModificationException} with the
* specified detail message.
*
* @param message the detail message pertaining to this exception.
@@ -85,4 +85,39 @@
public ConcurrentModificationException(String message) {
super(message);
}
+
+ /**
+ * Constructs a new exception with the specified cause and a detail
+ * message of {@code (cause==null ? null : cause.toString())} (which
+ * typically contains the class and detail message of {@code cause}.
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link Throwable#getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.7
+ */
+ public ConcurrentModificationException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause.
+ *
+ * <p>Note that the detail message associated with <code>cause</code> is
+ * <i>not</i> automatically incorporated in this exception's detail
+ * message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link Throwable#getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link Throwable#getCause()} method). (A {@code null} value
+ * is permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.7
+ */
+ public ConcurrentModificationException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java Thu Sep 09 11:50:40 2010 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java Fri Sep 10 16:36:48 2010 +0100
@@ -27,7 +27,6 @@
import java.nio.file.*;
import java.util.Iterator;
-import java.util.ConcurrentModificationException;
import java.util.NoSuchElementException;
import java.util.concurrent.locks.*;
import java.io.IOException;
@@ -139,9 +138,6 @@
// next entry to return
private Path nextEntry;
- // previous entry returned by next method (needed by remove method)
- private Path prevEntry;
-
UnixDirectoryIterator(DirectoryStream<Path> stream) {
atEof = false;
this.stream = stream;
@@ -168,24 +164,19 @@
// prevent close while reading
readLock().lock();
try {
- if (isClosed)
- throwAsConcurrentModificationException(new
- ClosedDirectoryStreamException());
- try {
+ if (isOpen()) {
nameAsBytes = readdir(dp);
- } catch (UnixException x) {
- try {
- x.rethrowAsIOException(dir);
- } catch (IOException ioe) {
- throwAsConcurrentModificationException(ioe);
- }
}
+ } catch (UnixException x) {
+ IOException ioe = x.asIOException(dir);
+ throw new DirectoryIteratorException(ioe);
} finally {
readLock().unlock();
}
// EOF
if (nameAsBytes == null) {
+ atEof = true;
return null;
}
@@ -198,7 +189,7 @@
if (filter == null || filter.accept(entry))
return entry;
} catch (IOException ioe) {
- throwAsConcurrentModificationException(ioe);
+ throw new DirectoryIteratorException(ioe);
}
}
}
@@ -206,66 +197,28 @@
@Override
public synchronized boolean hasNext() {
- if (nextEntry == null && !atEof) {
+ if (nextEntry == null && !atEof)
nextEntry = readNextEntry();
-
- // at EOF?
- if (nextEntry == null)
- atEof = true;
- }
return nextEntry != null;
}
@Override
public synchronized Path next() {
- if (nextEntry == null) {
- if (!atEof) {
- nextEntry = readNextEntry();
- }
- if (nextEntry == null) {
- atEof = true;
- throw new NoSuchElementException();
- }
+ Path result;
+ if (nextEntry == null && !atEof) {
+ result = readNextEntry();
+ } else {
+ result = nextEntry;
+ nextEntry = null;
}
- prevEntry = nextEntry;
- nextEntry = null;
- return prevEntry;
+ if (result == null)
+ throw new NoSuchElementException();
+ return result;
}
@Override
public void remove() {
- if (isClosed) {
- throwAsConcurrentModificationException(new
- ClosedDirectoryStreamException());
- }
- Path entry;
- synchronized (this) {
- if (prevEntry == null)
- throw new IllegalStateException("No previous entry to remove");
- entry = prevEntry;
- prevEntry = null;
- }
-
- // use (race-free) unlinkat if available
- try {
- if (stream instanceof UnixSecureDirectoryStream) {
- ((UnixSecureDirectoryStream)stream)
- .implDelete(entry.getName(), false, 0);
- } else {
- entry.delete();
- }
- } catch (IOException ioe) {
- throwAsConcurrentModificationException(ioe);
- } catch (SecurityException se) {
- throwAsConcurrentModificationException(se);
- }
+ throw new UnsupportedOperationException();
}
}
-
- private static void throwAsConcurrentModificationException(Throwable t) {
- ConcurrentModificationException cme = new ConcurrentModificationException();
- cme.initCause(t);
- throw cme;
- }
-
}
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java Thu Sep 09 11:50:40 2010 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java Fri Sep 10 16:36:48 2010 +0100
@@ -166,7 +166,7 @@
* Deletes file/directory in this directory. Works in a race-free manner
* when invoked with flags.
*/
- void implDelete(Path obj, boolean haveFlags, int flags)
+ private void implDelete(Path obj, boolean haveFlags, int flags)
throws IOException
{
UnixPath file = getName(obj);
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java Thu Sep 09 11:50:40 2010 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java Fri Sep 10 16:36:48 2010 +0100
@@ -28,7 +28,6 @@
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Iterator;
-import java.util.ConcurrentModificationException;
import java.util.NoSuchElementException;
import java.io.IOException;
@@ -121,17 +120,10 @@
}
}
- private static void throwAsConcurrentModificationException(Throwable t) {
- ConcurrentModificationException cme = new ConcurrentModificationException();
- cme.initCause(t);
- throw cme;
- }
-
private class WindowsDirectoryIterator implements Iterator<Path> {
private boolean atEof;
private String first;
private Path nextEntry;
- private Path prevEntry;
WindowsDirectoryIterator(String first) {
atEof = false;
@@ -156,7 +148,7 @@
if (filter.accept(entry))
return entry;
} catch (IOException ioe) {
- throwAsConcurrentModificationException(ioe);
+ throw new DirectoryIteratorException(ioe);
}
return null;
}
@@ -177,21 +169,19 @@
// synchronize on closeLock to prevent close while reading
synchronized (closeLock) {
- if (!isOpen)
- throwAsConcurrentModificationException(new
- ClosedDirectoryStreamException());
try {
- name = FindNextFile(handle, findDataBuffer.address());
- if (name == null) {
- // NO_MORE_FILES
- return null;
+ if (isOpen) {
+ name = FindNextFile(handle, findDataBuffer.address());
}
} catch (WindowsException x) {
- try {
- x.rethrowAsIOException(dir);
- } catch (IOException ioe) {
- throwAsConcurrentModificationException(ioe);
- }
+ IOException ioe = x.asIOException(dir);
+ throw new DirectoryIteratorException(ioe);
+ }
+
+ // NO_MORE_FILES or stream closed
+ if (name == null) {
+ atEof = true;
+ return null;
}
// grab the attributes from the WIN32_FIND_DATA structure
@@ -210,49 +200,28 @@
@Override
public synchronized boolean hasNext() {
- if (nextEntry == null && !atEof) {
+ if (nextEntry == null && !atEof)
nextEntry = readNextEntry();
- atEof = (nextEntry == null);
- }
return nextEntry != null;
}
@Override
public synchronized Path next() {
- if (nextEntry == null) {
- if (!atEof) {
- nextEntry = readNextEntry();
- }
- if (nextEntry == null) {
- atEof = true;
- throw new NoSuchElementException();
- }
+ Path result = null;
+ if (nextEntry == null && !atEof) {
+ result = readNextEntry();
+ } else {
+ result = nextEntry;
+ nextEntry = null;
}
- prevEntry = nextEntry;
- nextEntry = null;
- return prevEntry;
+ if (result == null)
+ throw new NoSuchElementException();
+ return result;
}
@Override
public void remove() {
- if (!isOpen) {
- throwAsConcurrentModificationException(new
- ClosedDirectoryStreamException());
- }
- Path entry;
- synchronized (this) {
- if (prevEntry == null)
- throw new IllegalStateException("no last element");
- entry = prevEntry;
- prevEntry = null;
- }
- try {
- entry.delete();
- } catch (IOException ioe) {
- throwAsConcurrentModificationException(ioe);
- } catch (SecurityException se) {
- throwAsConcurrentModificationException(se);
- }
+ throw new UnsupportedOperationException();
}
}
}
--- a/jdk/test/java/nio/file/DirectoryStream/Basic.java Thu Sep 09 11:50:40 2010 -0700
+++ b/jdk/test/java/nio/file/DirectoryStream/Basic.java Fri Sep 10 16:36:48 2010 +0100
@@ -104,20 +104,20 @@
stream.close();
}
- // check that IOExceptions throws by filters are propagated
+ // check that an IOException thrown by a filter is propagated
filter = new DirectoryStream.Filter<Path>() {
public boolean accept(Path file) throws IOException {
- throw new IOException();
+ throw new java.util.zip.ZipException();
}
};
stream = dir.newDirectoryStream(filter);
try {
stream.iterator().hasNext();
- throw new RuntimeException("ConcurrentModificationException expected");
- } catch (ConcurrentModificationException x) {
- Throwable t = x.getCause();
- if (!(t instanceof IOException))
- throw new RuntimeException("Cause is not IOException as expected");
+ throw new RuntimeException("DirectoryIteratorException expected");
+ } catch (DirectoryIteratorException x) {
+ IOException cause = x.getCause();
+ if (!(cause instanceof java.util.zip.ZipException))
+ throw new RuntimeException("Expected IOException not propagated");
} finally {
stream.close();
}
@@ -142,58 +142,49 @@
} catch (NotDirectoryException x) {
}
- // test iterator remove method
- stream = dir.newDirectoryStream();
+ // test UnsupportedOperationException
+ stream = dir.newDirectoryStream();
Iterator<Path> i = stream.iterator();
- while (i.hasNext()) {
- Path entry = i.next();
- if (!entry.getName().equals(foo))
- throw new RuntimeException("entry not expected");
+ i.next();
+ try {
i.remove();
+ throw new RuntimeException("UnsupportedOperationException expected");
+ } catch (UnsupportedOperationException uoe) {
}
- stream.close();
// test IllegalStateException
- dir.resolve(foo).createFile();
stream = dir.newDirectoryStream();
- i = stream.iterator();
- i.next();
+ stream.iterator();
try {
+ // attempt to obtain second iterator
stream.iterator();
throw new RuntimeException("IllegalStateException not thrown as expected");
} catch (IllegalStateException x) {
}
stream.close();
+
+ stream = dir.newDirectoryStream();
+ stream.close();
try {
+ // attempt to obtain iterator after stream is closed
stream.iterator();
throw new RuntimeException("IllegalStateException not thrown as expected");
} catch (IllegalStateException x) {
}
- try {
- i.hasNext();
- throw new RuntimeException("ConcurrentModificationException not thrown as expected");
- } catch (ConcurrentModificationException x) {
- Throwable t = x.getCause();
- if (!(t instanceof ClosedDirectoryStreamException))
- throw new RuntimeException("Cause is not ClosedDirectoryStreamException as expected");
- }
- try {
+
+ // test that iterator reads to end of stream when closed
+ stream = dir.newDirectoryStream();
+ i = stream.iterator();
+ stream.close();
+ while (i.hasNext())
i.next();
- throw new RuntimeException("ConcurrentModificationException not thrown as expected");
- } catch (ConcurrentModificationException x) {
- Throwable t = x.getCause();
- if (!(t instanceof ClosedDirectoryStreamException))
- throw new RuntimeException("Cause is not ClosedDirectoryStreamException as expected");
- }
+
+ stream = dir.newDirectoryStream();
+ i = stream.iterator();
+ stream.close();
try {
- i.remove();
- throw new RuntimeException("ConcurrentModificationException not thrown as expected");
- } catch (ConcurrentModificationException x) {
- Throwable t = x.getCause();
- if (!(t instanceof ClosedDirectoryStreamException))
- throw new RuntimeException("Cause is not ClosedDirectoryStreamException as expected");
- }
-
+ for (;;) i.next();
+ } catch (NoSuchElementException expected) { }
}
public static void main(String[] args) throws IOException {
--- a/jdk/test/java/nio/file/DirectoryStream/SecureDS.java Thu Sep 09 11:50:40 2010 -0700
+++ b/jdk/test/java/nio/file/DirectoryStream/SecureDS.java Fri Sep 10 16:36:48 2010 +0100
@@ -166,22 +166,6 @@
stream.deleteDirectory(dirEntry);
stream.deleteFile(fileEntry);
- // Test: remove
- // (requires resetting environment to get new iterator)
- stream.close();
- dir2.moveTo(dir1);
- dir1.resolve(fileEntry).createFile();
- stream = (SecureDirectoryStream<Path>)dir1.newDirectoryStream();
- dir1.moveTo(dir2);
- Iterator<Path> iter = stream.iterator();
- int removed = 0;
- while (iter.hasNext()) {
- iter.next();
- iter.remove();
- removed++;
- }
- assertTrue(removed == 1);
-
// clean-up
stream.close();
dir2.delete();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/etc/Exceptions.java Fri Sep 10 16:36:48 2010 +0100
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 4313887 6881498
+ * @summary Miscellenous tests on exceptions in java.nio.file
+ */
+
+import java.nio.file.*;
+import java.io.*;
+import java.util.Objects;
+import java.lang.reflect.*;
+
+public class Exceptions {
+
+ public static void main(String[] args) throws Exception {
+ testFileSystemException();
+ testDirectoryIteratorException();
+ }
+
+ static void testFileSystemException() throws Exception {
+ String thisFile = "source";
+ String otherFile = "target";
+ String reason = "Access denied";
+
+ // getFile/getOtherFile
+ testFileSystemException(thisFile, otherFile, reason);
+ testFileSystemException(null, otherFile, reason);
+ testFileSystemException(thisFile, null, reason);
+ testFileSystemException(thisFile, otherFile, null);
+
+ // serialization
+ FileSystemException exc;
+ exc = new FileSystemException(thisFile, otherFile, reason);
+ exc = (FileSystemException)deserialize(serialize(exc));
+ if (!exc.getFile().equals(thisFile) || !exc.getOtherFile().equals(otherFile))
+ throw new RuntimeException("Exception not reconstituted completely");
+ }
+
+ static void testFileSystemException(String thisFile,
+ String otherFile,
+ String reason)
+ {
+ FileSystemException exc = new FileSystemException(thisFile, otherFile, reason);
+ if (!Objects.equals(thisFile, exc.getFile()))
+ throw new RuntimeException("getFile returned unexpected result");
+ if (!Objects.equals(otherFile, exc.getOtherFile()))
+ throw new RuntimeException("getOtherFile returned unexpected result");
+ if (!Objects.equals(reason, exc.getReason()))
+ throw new RuntimeException("getReason returned unexpected result");
+ }
+
+ static void testDirectoryIteratorException() throws Exception {
+ // NullPointerException
+ try {
+ new DirectoryIteratorException(null);
+ throw new RuntimeException("NullPointerException expected");
+ } catch (NullPointerException expected) { }
+
+ // serialization
+ DirectoryIteratorException exc;
+ exc = new DirectoryIteratorException(new IOException());
+ exc = (DirectoryIteratorException)deserialize(serialize(exc));
+ IOException ioe = exc.getCause();
+ if (ioe == null)
+ throw new RuntimeException("Cause should not be null");
+
+ // when deserializing then the cause should be an IOException
+ hackCause(exc, null);
+ try {
+ deserialize(serialize(exc));
+ throw new RuntimeException("InvalidObjectException expected");
+ } catch (InvalidObjectException expected) { }
+
+ hackCause(exc, new RuntimeException());
+ try {
+ deserialize(serialize(exc));
+ throw new RuntimeException("InvalidObjectException expected");
+ } catch (InvalidObjectException expected) { }
+ }
+
+
+ // Use reflection to set a Throwable's cause.
+ static void hackCause(Throwable t, Throwable cause)
+ throws NoSuchFieldException, IllegalAccessException
+ {
+ Field f = Throwable.class.getDeclaredField("cause");
+ f.setAccessible(true);
+ f.set(t, cause);
+ }
+
+ // Serialize the given object to a byte[]
+ static byte[] serialize(Object o) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(o);
+ oos.close();
+ return baos.toByteArray();
+ }
+
+ // Read an object from its serialized form
+ static Object deserialize(byte[] bytes)
+ throws IOException, ClassNotFoundException
+ {
+ ByteArrayInputStream in = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(in);
+ Object result = ois.readObject();
+ ois.close();
+ return result;
+ }
+}