--- /dev/null Wed Nov 6 17:25:56 2013 +++ new/test/lib/testlibrary/jdk/testlibrary/FileUtils.java Wed Nov 6 17:25:55 2013 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2013, 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. + */ + +package jdk.testlibrary; + +import java.io.IOException; +import java.nio.file.DirectoryNotEmptyException; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; + + +/** + * Common library for various test file functions. + */ +public final class FileUtils { + + private static final boolean isWindows = + System.getProperty("os.name").startsWith("Windows"); + private static final int RETRY_DELETE_MILLIS = isWindows ? 500 : 0; + private static final int MAX_RETRY_DELETE_TIMES = isWindows ? 15 : 0; + + /** + * Deletes a file. + * + * @param path the file to delete + * + * @throws NoSuchFileException + * if the file does not exist (optional specific exception) + * @throws DirectoryNotEmptyException + * if the file is a directory and could not otherwise be deleted + * because the directory is not empty (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws InterruptedException + * if interrupted during the operation (optional) + */ + public static void delete(Path path) + throws IOException, InterruptedException + { + deleteWithRetry(path); + } + + private static void deleteWithRetry(Path path) + throws IOException, InterruptedException + { + int times = 0; + IOException ioe = null; + while (true) { + try { + Files.delete(path); + break; + } catch (NoSuchFileException | DirectoryNotEmptyException x) { + throw x; + } catch (IOException x) { + // Backoff/retry in case another process is accessing the file + times++; + if (ioe == null) + ioe = x; + else + ioe.addSuppressed(x); + if (times > MAX_RETRY_DELETE_TIMES) + throw ioe; + Thread.sleep(RETRY_DELETE_MILLIS); + } + } + } + + /** + * Deletes a directory and its subdirectories. + * + * @param dir the directory to delete + * + * @throws IOException + * If an I/O error occurs. Any such exceptions are caught + * internally. If only one is caught, then it is re-thrown. + * If more than one exception is caught, then the second and + * following exceptions are added as suppressed exceptions of the + * first one caught, which is then re-thrown. + */ + public static void deleteTree(Path dir) throws IOException { + IOException ioe = null; + final List excs = deleteTreeUnchecked(dir); + if (!excs.isEmpty()) { + ioe = excs.remove(0); + for (IOException x : excs) + ioe.addSuppressed(x); + } + if (ioe != null) + throw ioe; + } + + public static List deleteTreeUnchecked(Path dir) { + final List excs = new ArrayList<>(); + try { + java.nio.file.Files.walkFileTree(dir, new FileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + try { + deleteWithRetry(file); + } catch (IOException x) { + excs.add(x); + } catch (InterruptedException x) { + return FileVisitResult.TERMINATE; + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { + try { + deleteWithRetry(dir); + } catch (IOException x) { + excs.add(x); + } catch (InterruptedException x) { + return FileVisitResult.TERMINATE; + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + excs.add(exc); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException x) { + excs.add(x); + } + return excs; + } +} +